On Fri, 11 Nov 2016 13:27:09 -0500 mike bayer <mike...@zzzcomputing.com> wrote:
> > > On 11/11/2016 12:18 PM, Michael Williamson wrote: > > > > That still requires the repetition of the name of the attribute, > > which I'd rather avoid. I've put together a variation on > > hybrid_property which automatically assigns the label by scanning > > through the class dict. It could probably do with a bit of > > memoization and and proper handling of subtyping (i.e. checking > > __dict__ of supertypes), but does this seem sane to you? Is there a > > neater way? > > > > class hybrid_property2(hybrid_property): > > def __get__(self, instance, owner): > > if instance is None: > > expression = self.expr(owner) > > for key, value in owner.__dict__.items(): > > if value == self: > > return expression.label(key) > > > > return expression > > else: > > return self.fget(instance) > > > > Thanks for the suggestions so far, Mike and Simon. > > Getting the name of the attribute you're set on is not something I > know that there's any way to do without the kind of thing you're > doing. Decorators usually work out because fn.__name__ is there to > give us that info. Thanks Mike, in the end I defined my own metatype that inherits from DeclarativeMeta, and set __name__ on each property in __new__. > > > > > >> > >> > >> > >> > >> > >>> > >>> Is there a sensible way to do this? Or am I going about the > >>> problem the wrong way? In practice, I'm using this to define > >>> properties backed by a JSON field. In case it makes any > >>> different, here's the actual use-case I have: > >>> > >>> from __future__ import unicode_literals > >>> > >>> import os > >>> > >>> from sqlalchemy import create_engine, Column, Integer > >>> from sqlalchemy.dialects.postgresql import JSONB > >>> from sqlalchemy.event import listens_for > >>> from sqlalchemy.ext.hybrid import hybrid_property > >>> from sqlalchemy.ext.declarative import declarative_base > >>> from sqlalchemy.orm import Session > >>> from sqlalchemy.pool import StaticPool > >>> > >>> > >>> def json_property(json_column, name, type_=None): > >>> def instance_get(self): > >>> return getattr(self, json_column.key)[name] > >>> > >>> def instance_set(self, value): > >>> json_obj = getattr(self, json_column.key) > >>> if json_obj is None: > >>> setattr(self, json_column.key, {}) > >>> getattr(self, json_column.key)[name] = value > >>> > >>> def cls_get(cls): > >>> expression = json_column[name] > >>> if type_: > >>> return expression.astext.cast(type_) > >>> else: > >>> return expression > >>> > >>> return hybrid_property(fget=instance_get, expr=cls_get, > >>> fset=instance_set) > >>> > >>> > >>> Base = declarative_base() > >>> > >>> class Person(Base): > >>> __tablename__ = "person" > >>> > >>> id = Column(Integer, primary_key=True) > >>> data = Column(JSONB, nullable=False) > >>> born = json_property(data, "born", Integer()) > >>> > >>> > >>> engine = create_engine(os.environ["TEST_DATABASE"], > >>> poolclass=StaticPool) engine.execute("SET search_path TO pg_temp") > >>> > >>> @listens_for(engine, "engine_connect") > >>> def set_search_path(connection, branch): > >>> connection.execute("SET search_path TO pg_temp") > >>> > >>> > >>> Base.metadata.create_all(engine) > >>> session = Session(engine) > >>> > >>> session.add(Person(born=1881)) > >>> session.commit() > >>> > >>> assert session.query(Person.born).one() == (1881, ) # Works fine > >>> assert session.query(Person.born).one().born == 1881 # Raises > >>> AttributeError since hybrid_property uses instance_get as the name > >>> > >>> -- > >>> SQLAlchemy - > >>> The Python SQL Toolkit and Object Relational Mapper > >>> > >>> http://www.sqlalchemy.org/ > >>> > >>> To post example code, please provide an MCVE: Minimal, Complete, > >>> and Verifiable Example. See http://stackoverflow.com/help/mcve > >>> for a full description. > >>> --- > >>> You received this message because you are subscribed to the Google > >>> Groups "sqlalchemy" group. > >>> To unsubscribe from this group and stop receiving emails from it, > >>> send an email to sqlalchemy+unsubscr...@googlegroups.com > >>> <mailto:sqlalchemy+unsubscr...@googlegroups.com>. > >>> To post to this group, send email to sqlalchemy@googlegroups.com > >>> <mailto:sqlalchemy@googlegroups.com>. > >>> Visit this group at https://groups.google.com/group/sqlalchemy. > >>> For more options, visit https://groups.google.com/d/optout. > >> > > -- SQLAlchemy - The Python SQL Toolkit and Object Relational Mapper http://www.sqlalchemy.org/ To post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description. --- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at https://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.