Selecting property to access programmatically - python

Given:
import configs
thingToLook = 'value'
channels = configs.value
Can I do something like
channels = config[thingToLook]
which is equivalent to
channels = config.value
?
If I do
channels = configs[thingToLook]
I get:
TypeError: 'module' object has no attribute '__getitem__'
I am trying to select the property to get from configs programmatically so I can set it via a string.

Unlike JavaScript, Python differentiates between items (bracket access) and attributes (dot access). Syntax that works for accessing one doesn't (usually) work for accessing the other.
You can use the getattr function to dynamically look up an attribute:
getattr(configs, thinkToLook)
and optionally set a default if nothing is found:
getattr(configs, thinkToLook, False)

config.value and config['value'] are not the same. They call different methods of the instance.
config.value is the same as config.__getattr__('value').
config['value'] is the same as config.__getitem__('value').
For more information look at this: https://docs.python.org/2/reference/datamodel.html

Related

Python: Selecting Object using String

I have a dataframe listing individual names, and for each one I have an identically-named object storing attributes about them. However, when iterating through the dataframe, I don't know how to use the listed name to access the correct object (which I want to pull an attribute from).
person = df._get_value(n, 'People')
getattr(person, 'Age')
When I run this, I get an Attribute Error because its attempting to access 'Age' in the string, but not the matching object. How should I convert the string dynamically so I can access the correct object?
You can use inbuilt function import (mind the double underscore). Sample code below
module = __import__("name of the package", globals(), locals(), ["moduleName"], 0)
obj_class = getattr(module, "moduleName")
cclass = obj_class()
getattr(cclass, "attributeName")
You can view this doc for more details on importlib

Set Django session variables through channels (http_session)

According to the Django channel docs,
You get access to a user’s normal Django session using the http_session
decorator - that gives you a message.http_session attribute that behaves
just like request.session. You can go one further and use
http_session_user which will provide a message.user attribute as well as
the session attribute.
Is there anyway I can set a session variable like so?
I did try it, and I get an error saying NoneType is not iterable.
if 'username' not in message.http_session:
message.http_session['username'] = 'temp'
In other words, message.http_session returns a NoneType. I've tried using the decorators #http_session and #channel_session_user_from_http, but they didn't help either.
You just set the variable.
foo = 'bar'
And it persists throughout the session

findChild returns None with custom widget

I have created a custom Qt widget in Python and managed to get it to load into the form at runtime however when I try and use findChild to grab it back of the form instance I get None back.
The widget is loaded and I can see it if I print out the names and objects on the form:
DEBUG:root:<PyQt4.QtGui.QCheckBox object at 0x11358030>
DEBUG:root:Near_Other_Infrastructure
DEBUG:root:<PyQt4.QtGui.QCheckBox object at 0x113582B8>
DEBUG:root:photo
DEBUG:root:<imagewidget.QMapImageWidget object at 0x113586A8>
This is the code:
images = self.forminstance.findChild(QMapImageWidget)
Update:
Seems doing this works:
images = self.forminstance.findChild(QWidget, "photo")
and it returns DEBUG:root:<imagewidget.QMapImageWidget object at 0x113586A8>
although I would really perfer to just get the control via the type without using the name.
Any ideas?
I also had this problem.
One easy solution is to find a non-custom base class and cast.
Custom* ptr = dynamic_cast<QWidget*>(root->findChild<QWidget*>("MyWidgetName"));
if (ptr)
{
//...whatever
}

Python model object validation

I'm writing an interface to be used by two applications. This interface should use some DoSomethingRequest and DoSomethingResponse classes to do the communication.
Is there any library that does some model validation, for example like Django's Model?
I basically want to be able to say something like:
Object A must have a "text" property of type str(), a "number" property of type int(), an "items" property of type list(). In a DRY way.
I'm looking for something like the following, or better:
class MyEmbeddedModelClass(EmbeddedModel):
text = TextField(required = True)
class MyModel(Model):
text = TextField(required = True)
number = IntField(default = 0)
items = ListField(EmbeddedModel)
a = MyModel()
a.text = "aaaa"
a.number = 1
a.items = [
MyEmbeddedModelClass("bbbb"),
MyEmbeddedModelClass("cccc"),
MyEmbeddedModelClass("dddd")
]
a.validate()
I know I can write my own, but I'd rather use a library if available, I'm a bit new to this.
If you want to enforce interfaces, or use design-by-contract, then you probably want the zope.interface library. Despite the name, which reflects its origins in Zope, it's not actually tied to that framework at all and is quite usable outside.
I think decorators could be used for this.
check this link
Combining Descriptors with Class Decorators for Validation
For a different approach check Duck typing
Because python is dynamic, the convention is to require an object to behave like an instance of a particular class rather than enforce a specific type.
Somewhere in your code, preferably at the point where you need to access those properties, but as early as possible assert that the object has those properties and further assert that those properties are what you expect them to be.
This raises an AssertionError exception if the object o, regardless of type, if it is missing the 'someattribute' attribute:
assert(hasattr(o, 'someattribute'))
Further, if o.someattribute is not a string:
assert(isinstance(o.someattribute, basestring))

How can I tell if an Expando subclass has a property defined?

I'm creating an app that I want to have an expandable set of properties (each a RatingProperty) I also want to validate that any dynamic properties are of the RatingProperty type.
In the Expando documentation it says:
Tip: If you want to validate a dynamic property value using a Property class, you can instantiate the Property class and call its validate() method on the value.
So if I want to validate a dynamic property I need to know what the class's non-dynamic properties are. How can I ask my class what it's defined properties are?
I've considered creating a class method that takes a string and returns true if that string is in a list of property names that I create and maintain, but it seems like a hack. I've searched the Google for tips, but haven't had any luck.
Thanks,
Pat
After a bit more research (damn you lazyweb!) I've found a solution that I think is acceptable:
A dynamic property can't be of a db subclassed property type. Thus, there are two distinct steps that must be taken. First you need to create an instance of your property class and validate your value:
test = db.RatingProperty()
if test.validate(valueToSave):
#do your thing
Next you need to check if the property you want to save is a declared property:
if valueToSaveKey not in myObject.properties():
#if not save it as desired
myObject.valueToSaveKey = valueToSave
The down side here is that the value you save isn't stored as the property type you want.
http://code.google.com/appengine/docs/python/datastore/modelclass.html#Model_properties
db.Model has methods to find out all the properties on an instance.
The class exposes a list of Property objects: db.Model.properties()
The instance exposes the dynamic names only: instance.dynamic_properties()
You want to loop through the list and build Property objects, and run p.validate().
for p_name in instance.dynamic_properties():
p = db.RatingProperty()
p.validate() # raises BadValueError, etc.
I may be misunderstanding your question, but if you have a list of properties you expect to find, why not just use a standard db.Model, instead of an Expando? You can add additional properties to a Model class, as long as you either provide a default or don't make them required.
It's actually quite easy!
ExpandoObject implements (IDictionary<String, Object>) so you just need to do this :
dynamic person = new ExpandoObject();
person.FirstName = "Barack";
person.LastName = "Obama"
(((IDictionary<String, Object>)person).Keys
=> { "FirstName", "LastName" }
(((IDictionary<String, Object>)person).ContainsKey("FirstName")
=> true
Note: You need to explicitly cast to (IDictionary<string, object> because ExpandoObject explicitly implements this interface - and the instance itself doesn't have ContainsKey() or Keys.
Don't expect this method to work with all dynamic objects - just ExpandoObject and anything else that implements this interface.

Categories