python: Accessing an instance variable using a name containing a variable - python

in python I'm trying to access a instance variable where I need to use the value of another variable to determine the name: Example Instance Variable: user.remote.directory where it point to the value of 'servername:/mnt/.....' and user portion contains the userid of the user, such as joe.remote.directory
from another class I need to be able to access the joe.remote.directory using a variable that contains the user id of joe. I tried variable.remote.directory but it doesn't work, any suggestions?

Unsure quite what you want, but I think getattr(obj, 'name') might help. See http://docs.python.org/library/functions.html#getattr

You can refer to instance variable called name of object obj this way:
obj.__dict__['name']
Therefore, if you have another variable prop which holds the name of the instance variable you'd like to refer to, you can do it this way:
obj.__dict__[prop]
If you find yourself needing this functionality, you should ask yourself whether it isn't in fact a good circumstance to use an instance of dict instead.

I would suggest you create an extra User-Object, which you pass to the appropriate Objects or functions as needed. You are being extremly vague, so it's hard to give you a more practical advice.
Example:
class User:
def __init__(self, name, uid=None, remote=None, dir=None):
self.name = name
self.uid = uid
self.remote = remote
self.directory = dir
def get_X(self)
...
def create_some_curios_String(self):
""" for uid = 'joe', remote='localhost' and directory = '/mnt/srv'
this method would return the string:
'joe#localhost://mnt/srv'
"""
return '%s#%s:/%s' % (self.uid, self.remote, self.directory)
class AnotherClass:
def __init__(self, user_obj):
self.user = user_obj
class YetAnotherClass:
def getServiceOrFunctionalityForUser(self, user):
doWhatEverNeedsToBeDoneWithUser(user)
doWhatEverNeedsToBeDoneWithUserUIDandRemote(user.uid, user.remote)
joe = User('Joe Smith', 'joe', 'localhost', '/mnt/srv')
srv_service = ServerService(joe.create_some_curios_String())
srv_service.do_something_super_important()

Related

Run some method at start of banch of methods (python)

May be I'm doing wrong way, so tell me how to do it better.
I'm implementing one class for all instances of some object, say users. (looks like it is pattern 'Table Module' in M. Fowler's "Patterns of Enterprise Application Architecture"). I attached the simplified example of my implementation.
user argument may be of different kinds:
just int ID
dictionary with information about user. it has key id among other
tuple or list with ID as element with index 0
I want to determine right type of input variable user and get ID from it. At the same time I'd like to check if the input is correct at all.
I'm confused about calling __get_id at the beginning of all methods handling user information.
I sure python can propose better and lighter solution of this problem. Or maybe the whole approach is wrong and I should implement another one.
Thanks in advance.
class BadInputError (Exception):
pass
class Users:
def __init__(self):
pass
def __is_wrong_id(self, id):
# code to check if `id` is wrong
return False
def __get_id(self, user):
if isinstance(user, int):
ID = user
elif isinstance(user, tuple) or isinstance(user, list):
ID = user[0]
elif isinstance(user, dict) and user.has_key('id'):
ID = user['id']
else:
raise BadInputError
if self.__is_wrong_id(ID):
raise BadInputError
return ID
def check_user(self, user):
uID = self.__get_id(user)
# ...
def delete_user(self, user):
uID = self.__get_id(user)
# ...
def assign_new_role_to(self, user):
uID = self.__get_id(user)
# ...
Here __get_id(self, user) make an attempt that would seem as overloading, however you're right - it's generally considered bad practice to check if a variable is an instance of a given class. In your definition you would only ever extract the first element of the tuple or list and hope that it corresponds to the ID.
Instead, you should strive to create wrappers of User that support the __get_id() method.
It's hard to tell with this stripped down code, but the problem that I see here is none of the methods actually use self (other than to call ___get_id -- which doesn't use self).
Normally a class stores data and associated methods -- If you just have methods, then it should be a module.
Here, it makes sense for a "User" to know it's ID, so it might be worth creating a "User" class which uses the __get_id function to store an attribute (self.id). Then the Users class (which represents a collection of Users) could just check user.id. e.g.:
class User(object):
def __init__(self, initialize_data):
self.__set_id(intialize_data)
def __set_id(self, data):
if isinstance(user, int):
self.id = user
elif isinstance(user, (tuple, list)):
self.id = user[0]
elif isinstance(user, dict) and user.has_key('id'):
self.id = user['id']
else:
raise BadInputError
class Users(object):
def __init__(self):
self.users = []
def delete_user(self, user):
self.users = [u for u in self.users if u.id != user.id]
Note that this example implementation is nowhere near optimal -- It was meant to show how I would structure the code. A bunch of improvements could probably be made to make it more efficient (i.e., maybe a User could be hashible based on the id in which case Users.users could be a set).

Attaching extra information to model instance - django

I have a django model that I want to attach an extra piece of information to, depending on the environment the instance is in (which user is logged in). For this reason, I don't want to do it at the database level.
Is this okay to do? Or are there problems that I don't foresee?
in models.py
class FooOrBar(models.Model):
"""Type is 'foo' or 'bar'
"""
def __init__(self, type):
self.type = type
in views.py
class FooCheck(FooOrBar):
"""Never saved to the database
"""
def __init__(self, foo_or_bar):
self.__dict__ = foo_or_bar.__dict__.copy()
def check_type(self, external_type):
if external_type == 'foo':
self.is_foo = True
else:
self.is_foo = False
foos_or_bars = FooOrBar.objects.all()
foochecks = map(FooCheck, foos_or_bars)
for foocheck in foochecks:
foocheck.check_type('foo')
extra credit question: Is there a more efficient way of calling a method on multiple objects i.e. replacing the last forloop with something clever?
Okay, this does not work. Trying to delete a FooOrBar objects throws a complaint about
OperationalError at /
no such table: test_FooCheck
To get around this I'm just not going to inherit from FooOrBar, but if anyone has a suggestion on a better way to do it I'd be interested in hearing it
I had a similar issue, I did something like:
class Foo(models.Model):
# specific info goes here
class Bar(models.Model):
# specific info goes here
class FooBar(models.Model):
CLASS_TYPES = {
"foo":Foo,
"bar":Bar
}
type = models.CharField(choices=CLASS_TYPES)
id = models.IntegerField()
#field to identify FooBar
then you can get the object back using
object = FooBar.CLASS_TYPES[instance.type].objects.get(id=instance.id)
where instance is the FooBar instance

python convert custom object to json using properties

In Bottle framework or python in general, is there a way to convert a custom object to json using the properties of the object?
I saw few posts which recommend to write to_json(self) kind sort of method on the custom class. Was wondering if there is any automated way of doing the same?
Coming from Java world, was hoping for Jackson type of module with XmlRootElement annotation (or decorator in python terms). But didn't find any so far.
UPDATE I do not want to use __dict__ elements. Instead want to use properties of my custom class to build the json.
You could use a decorator to "mark" the properties that needs to be represented.
You would still need to write a to_json function, but you will only need to define it once in the base class
Here's a simple example:
import json
import inspect
def viewable(fnc):
'''
Decorator, mark a function as viewable and gather some metadata in the process
'''
def call(*pargs, **kwargs):
return fnc(*pargs, **kwargs)
# Mark the function as viewable
call.is_viewable = True
return call
class BaseJsonable(object):
def to_json(self):
result = {}
for name, member in inspect.getmembers(self):
if getattr(member, 'is_viewable', False):
value = member()
result[name] = getattr(value, 'to_json', value.__str__)()
return json.dumps(result)
class Person(BaseJsonable):
#viewable
def name(self):
return self._name
#viewable
def surname(self):
return self._surname
def __init__(self, name, surname):
self._name = name
self._surname = surname
p = Person('hello', 'world')
print p.to_json()
Prints
{"surname": "world", "name": "hello"}

what does describe do in python?

I was going through code of https://github.com/hit9/CURD.py/blob/master/CURD.py which is a simple orm that performs normal curd operations .. and i could not understood part of code which goes like this(on line number 616):
.....#smthing #..
for name, attr in cls.__dict__.iteritems():
if isinstance(attr, Field):
attr.describe(name, cls)
fields[name] = attr
what does attr.describe(attr, Field) do ? I googled it out but found nothing.
It's not a Python language feature, it's a method on that library. You can see the definition here:
https://github.com/hit9/CURD.py/blob/master/CURD.py#L251
class Field(Leaf):
"""
Field object.
Field examples: User.name, User.age ..
"""
def __init__(self, is_primarykey=False, is_foreignkey=False):
self.is_primarykey = is_primarykey
self.is_foreignkey = is_foreignkey
# describe model's attr
def describe(self, name, model):
self.name = name
self.model = model
# fullname e.g. : User.id 's fullname is "user.id"
self.fullname = self.model.table_name + "." + self.name
# describe the attribute, reload its access control of writing, reading
setattr(model, name, FieldDescriptor(self))
setattr sets an attribute on an object. So if I call describe("field_name", myObject), it will set myObject.field_name to the description of the model. Or something like that.
That is not a python standard thing.
The loop iterates through the names and values of a class, and the attributes of that class that are instances of a Field type are added to a dictionary.
Field is not part of python standard library, you should search that project for the Field class.

Accessing model from FileSystemStorage

I have custom FileSystemStorage.
The idea is to pass optional filename parameter.
My custome storge code:
class SalesMapFileStores(FileSystemStorage):
def __init__(self, location=None, base_url=None, filename=None):
if filename:
self.filename = filename
super(SalesMapFileStores, self).__init__(location=location, base_url=base_url)
def get_available_name(self, name):
return name
def get_valid_name(self, name):
if self.filename:
return self.filename
return name
def _save(self, name, content):
if self.exists(name):
self.delete(name)
return super(SalesMapFileStores, self)._save(name, conten
What i whant is to pass this filename parameter from model.
Somethin like this:
class SalesMapImage(models.Model):
name = models.CharField(max_length=254, verbose_name='Filename')
image = SalesMapImageField(upload_to='SalesMap/Test', storage=SalesMapFileStores(filename=name), verbose_name='Test Image',
content_types=('image/jpeg', 'image/png'))
But in this case, Django passes as a parameter itself model.CharField (it's obvious :)).
The question is: how can I get access to my model instance from Storage?
Thanks in advance!
Well, it is a bit crazy idea but you can try to override the assignment to that field in that class so the SalesMapFileStores instance always keep in sync with the name field like this:
class SalesMapImage(models.Model):
name = models.CharField(max_length=254, verbose_name='Filename')
image = SalesMapImageField(upload_to='SalesMap/Test', storage=SalesMapFileStores(), verbose_name='Test Image',
content_types=('image/jpeg', 'image/png'))
def __setattr__(self, key, value):
self.__dict__[key]=value
if key=='name':
self.image.storage.filename = value
And the general idea is to hook the assignment of the value to the update of the filename field.
This is supposing that you don't want to update it manually from within your view. Because it wouldn't take much effort to do model_instance.storage.filename = self.name or even add a method to your custom storage class to update the filename.
UPDATE: Heads up for the storage=SalesMapFileStores(). There you are passing a instance of SalesMapFileStores. Not the class, so it might be possible you'll be using the same instace for storing all files and this my bring conflicts with filename. You can try it like this: storage=SalesMapFileStores
Hope this helps!

Categories