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.










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.

Reply via email to