hybrid properties not shown in iterate_properties?

796 views
Skip to first unread message

Gerald Thibault

unread,
Dec 29, 2012, 3:03:06 AM12/29/12
to sqlal...@googlegroups.com
I'll post a test case later if needed, but this is more of a technical question so i don't think it will be needed.

When i use iterate_properties on a class with a hybrid_property, it's not shown in the list. I am trying to 'extract' fields from classes in order to automatically build forms from them. iterate_properties was useful for getting most info, but eventually i had to start using 'for k in dir(class)' to get access to association proxies on the classes. I would use getattr(cls, k) to get the object, but for hybrid properties this calls fget, and directly returns a BinaryExpression, rather than the property itself. The only way I can find to access the actual hybrid_property object is via vars(cls), and then, this doesn't contain hybrid properties defined on the bases which are being used by the class.

Is there a way built into sqlalchemy to get all hybrid_property objects for a class, both those declared on the active class and those declared on the base classes? I'm mainly interested in determining whether a setter has been provided on the property, to determine if it's readonly or not.

Michael Bayer

unread,
Dec 29, 2012, 5:45:20 PM12/29/12
to sqlal...@googlegroups.com
There's no API system of reading non-MapperProperty objects, which includes all the various descriptors we have in sqlalchemy.ext.      It might be nice to add such an API to do so and make this an extension of the 0.8 inspect() system, but anyway for now when you read class-bound descriptors like this, you have to work around the fact that they have classbound behavior, which means you can't use getattr().

An iterative approach which uses __dict__ to get at everything might be like this (not tested):


def all_attrs(cls):
    keys = set()
    for supercls in cls.__mro__:
        for k in supercls.__dict__.difference(keys):
            keys.add(k)
            v = supercls.__dict__[k]
            if isinstance(v, (InstrumentedAttribute, AssociationProxy, hybrid_property):
                yield v







--
You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
To view this discussion on the web visit https://groups.google.com/d/msg/sqlalchemy/-/sOnrMob9HIoJ.
To post to this group, send email to sqlal...@googlegroups.com.
To unsubscribe from this group, send email to sqlalchemy+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.

Michael Bayer

unread,
Dec 29, 2012, 7:36:14 PM12/29/12
to sqlal...@googlegroups.com

On Dec 29, 2012, at 5:45 PM, Michael Bayer wrote:

>
> On Dec 29, 2012, at 3:03 AM, Gerald Thibault wrote:
>
>> I'll post a test case later if needed, but this is more of a technical question so i don't think it will be needed.
>>
>> When i use iterate_properties on a class with a hybrid_property, it's not shown in the list. I am trying to 'extract' fields from classes in order to automatically build forms from them. iterate_properties was useful for getting most info, but eventually i had to start using 'for k in dir(class)' to get access to association proxies on the classes. I would use getattr(cls, k) to get the object, but for hybrid properties this calls fget, and directly returns a BinaryExpression, rather than the property itself. The only way I can find to access the actual hybrid_property object is via vars(cls), and then, this doesn't contain hybrid properties defined on the bases which are being used by the class.
>>
>> Is there a way built into sqlalchemy to get all hybrid_property objects for a class, both those declared on the active class and those declared on the base classes? I'm mainly interested in determining whether a setter has been provided on the property, to determine if it's readonly or not.
>
>
> There's no API system of reading non-MapperProperty objects, which includes all the various descriptors we have in sqlalchemy.ext. It might be nice to add such an API to do so and make this an extension of the 0.8 inspect() system, but anyway for now when you read class-bound descriptors like this, you have to work around the fact that they have classbound behavior, which means you can't use getattr().

I've added this feature to the tip for 0.8.0:

from sqlalchemy import inspect

insp = inspect(MyClass) # note this is just the Mapper, as usual

for k, v in insp.all_orm_descriptors:
if v.extension_type is associationproxy.ASSOCIATION_PROXY:
# ...
elif v.extension_type is hybrid.HYBRID_PROPERTY
# ...

# etc.

see http://docs.sqlalchemy.org/en/latest/orm/mapper_config.html#sqlalchemy.orm.mapper.Mapper.all_orm_descriptors


JT Thibault

unread,
Dec 30, 2012, 12:26:36 AM12/30/12
to sqlal...@googlegroups.com
Awesome, this is exactly what I needed. Thanks Michael.


--
You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
Reply all
Reply to author
Forward
0 new messages