sqlalchemy: "Neither 'InstrumentedAttribute' object nor 'Comparator' object has an attribute" error

Lorin Hochstein picture Lorin Hochstein · May 25, 2011 · Viewed 9.1k times · Source

I've added a table to a database using sqlalchemy and sqlalchemy-migrate, and when I run unit tests on unrelated code that hits the database, I get the following error:

Traceback (most recent call last):
  File "/Users/lorin/nova/instance_type_metadata/.nova-venv/lib/python2.6/site-packages/nose/suite.py", line 208, in run
    self.setUp()
  File "/Users/lorin/nova/instance_type_metadata/.nova-venv/lib/python2.6/site-packages/nose/suite.py", line 291, in setUp
    self.setupContext(ancestor)
  File "/Users/lorin/nova/instance_type_metadata/.nova-venv/lib/python2.6/site-packages/nose/suite.py", line 314, in setupContext
    try_run(context, names)
  File "/Users/lorin/nova/instance_type_metadata/.nova-venv/lib/python2.6/site-packages/nose/util.py", line 478, in try_run
    return func()
  File "/Users/lorin/nova/metadata-debugging/nova/tests/__init__.py", line 62, in setup
    FLAGS.vpn_start,
  File "/Users/lorin/nova/metadata-debugging/nova/network/manager.py", line 577, in create_networks
    network_ref = db.network_get_by_cidr(context, cidr)
  File "/Users/lorin/nova/metadata-debugging/nova/db/api.py", line 628, in network_get_by_cidr
    return IMPL.network_get_by_cidr(context, cidr)
  File "/Users/lorin/nova/metadata-debugging/nova/db/sqlalchemy/api.py", line 99, in wrapper
    return f(*args, **kwargs)
  File "/Users/lorin/nova/metadata-debugging/nova/db/sqlalchemy/api.py", line 1308, in network_get_by_cidr
    result = session.query(models.Network).\
  File "/Users/lorin/nova/instance_type_metadata/.nova-venv/lib/python2.6/site-packages/sqlalchemy/orm/session.py", line 873, in query
    return self._query_cls(entities, self, **kwargs)
  File "/Users/lorin/nova/instance_type_metadata/.nova-venv/lib/python2.6/site-packages/sqlalchemy/orm/query.py", line 92, in __init__
    self._set_entities(entities)
  File "/Users/lorin/nova/instance_type_metadata/.nova-venv/lib/python2.6/site-packages/sqlalchemy/orm/query.py", line 101, in _set_entities
    self._setup_aliasizers(self._entities)
  File "/Users/lorin/nova/instance_type_metadata/.nova-venv/lib/python2.6/site-packages/sqlalchemy/orm/query.py", line 116, in _setup_aliasizers
    _entity_info(entity)
  File "/Users/lorin/nova/instance_type_metadata/.nova-venv/lib/python2.6/site-packages/sqlalchemy/orm/util.py", line 536, in _entity_info
    mapper = mapper.compile()
  File "/Users/lorin/nova/instance_type_metadata/.nova-venv/lib/python2.6/site-packages/sqlalchemy/orm/mapper.py", line 805, in compile
    mapper._post_configure_properties()
  File "/Users/lorin/nova/instance_type_metadata/.nova-venv/lib/python2.6/site-packages/sqlalchemy/orm/mapper.py", line 834, in _post_configure_properties
    prop.init()
  File "/Users/lorin/nova/instance_type_metadata/.nova-venv/lib/python2.6/site-packages/sqlalchemy/orm/interfaces.py", line 493, in init
    self.do_init()
  File "/Users/lorin/nova/instance_type_metadata/.nova-venv/lib/python2.6/site-packages/sqlalchemy/orm/properties.py", line 839, in do_init
    self._process_dependent_arguments()
  File "/Users/lorin/nova/instance_type_metadata/.nova-venv/lib/python2.6/site-packages/sqlalchemy/orm/properties.py", line 883, in _process_dependent_arguments
    setattr(self, attr, getattr(self, attr)())
  File "/Users/lorin/nova/instance_type_metadata/.nova-venv/lib/python2.6/site-packages/sqlalchemy/ext/declarative.py", line 1078, in return_cls
    x = eval(arg, globals(), d)
  File "<string>", line 1, in <module>
  File "/Users/lorin/nova/instance_type_metadata/.nova-venv/lib/python2.6/site-packages/sqlalchemy/util.py", line 76, in __missing__
    self[key] = val = self.creator(key)
  File "/Users/lorin/nova/instance_type_metadata/.nova-venv/lib/python2.6/site-packages/sqlalchemy/ext/declarative.py", line 1070, in access_cls
    elif key in cls.metadata.tables:
  File "/Users/lorin/nova/instance_type_metadata/.nova-venv/lib/python2.6/site-packages/sqlalchemy/orm/attributes.py", line 138, in __getattr__
    key)
AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object has an attribute 'tables'

What could I have done to cause wrong in my sqlalchemy models to cause this error? The code is on Launchpad at lp:~usc-isi/nova/instance_type_metadata, revisions 1109-1115 have my changes.

I added one model to nova/db/sqlalchemy/models.py:

class InstanceTypeMetadata(BASE, NovaBase):
    """Represents a metadata key/value pair for an instance_type"""
    __tablename__ = 'instance_type_metadata'
    id = Column(Integer, primary_key=True)
    key = Column(String(255))
    value = Column(String(255))
    instance_type_id = Column(Integer, ForeignKey('instance_types.id'),
                              nullable=False)
    instance_type = relationship(InstanceTypes, backref="metadata",
                 foreign_keys=instance_type_id,
                 primaryjoin='and_('
                 'InstanceTypeMetadata.instance_type_id == InstanceTypes.id,'
                 'InstanceTypeMetadata.deleted == False)')

And I added the file nova/db/sqlalchemy/migrate_repo/versions/019_add_instance_type_metadata.py

Answer

Denis Otkidach picture Denis Otkidach · May 26, 2011

As you can see from traceback attribute metadata of mapped class is used internally by declarative extension for SQLAlchemy's MetaData instance, while you replaced it with your own relation (backref="metadata") with different meaning. Renaming it to something else should solve the problem.