Introspect relationships directly.

Possibly more fragile, but this way we don't need _set_relationships.

SQLAlchemy version bump for AssociationProxy.remote_attr.
This commit is contained in:
Andrew Ekstedt 2012-06-05 14:47:42 -07:00
parent 391fd1c1ac
commit 04b941755a
3 changed files with 44 additions and 53 deletions

View file

@ -1829,7 +1829,8 @@ def add_relationships():
secondary=secondary) secondary=secondary)
backref_info.update(backref_kwargs.pop('info', {})) backref_info.update(backref_kwargs.pop('info', {}))
argument.relationship_info[backref_name] = backref_info argument.relationship_info[backref_name] = backref_info
setattr(cls, name, relationship(argument, secondary=secondary, doc = info.get('description', None)
setattr(cls, name, relationship(argument, secondary=secondary, doc=doc,
**kwargs)) **kwargs))
def add_association_proxy(name, target_collection, attr, **kwargs): def add_association_proxy(name, target_collection, attr, **kwargs):
cls.relationship_info.setdefault('_order', []) cls.relationship_info.setdefault('_order', [])
@ -1840,7 +1841,7 @@ def add_relationships():
type='association_proxy', type='association_proxy',
target_collection=target_collection, target_collection=target_collection,
attr=attr)) attr=attr))
setattr(cls, name, association_proxy(name, target_collection, setattr(cls, name, association_proxy(target_collection, attr,
**kwargs)) **kwargs))
add_relationships(add_relationship=add_relationship, add_relationships(add_relationship=add_relationship,
add_association_proxy=add_association_proxy) add_association_proxy=add_association_proxy)

View file

@ -20,7 +20,8 @@ from sphinx.ext.autodoc import ClassLevelDocumenter
from sqlalchemy import types from sqlalchemy import types
from sqlalchemy.orm.attributes import InstrumentedAttribute from sqlalchemy.orm.attributes import InstrumentedAttribute
from sqlalchemy.orm import configure_mappers from sqlalchemy.orm.properties import RelationshipProperty
from sqlalchemy.orm import Mapper, configure_mappers
from sqlalchemy.ext.associationproxy import AssociationProxy from sqlalchemy.ext.associationproxy import AssociationProxy
from pokedex.db.markdown import MoveEffectPropertyMap, MoveEffectProperty from pokedex.db.markdown import MoveEffectPropertyMap, MoveEffectProperty
@ -196,55 +197,44 @@ def generate_strings(cls, remaining_attrs):
@with_header(u'Relationships') @with_header(u'Relationships')
def generate_relationships(cls, remaining_attrs): def generate_relationships(cls, remaining_attrs):
order = cls.relationship_info.get('_order', []) for attr_name in sorted(remaining_attrs):
def sort_key((key, value)): prop = getattr(cls, attr_name)
try: def isrelationship(prop):
return 0, order.index(key) return isinstance(prop, InstrumentedAttribute) and isinstance(prop.property, RelationshipProperty)
except ValueError: if isrelationship(prop):
return 1, key rel = prop.property
infos = sorted(cls.relationship_info.items(), key=sort_key) yield u'%s.\ **%s**' % (cls.__name__, attr_name)
for rel_name, info in infos: class_name = u':class:`~pokedex.db.tables.%s`' % rel.mapper.class_.__name__
if rel_name in remaining_attrs: if rel.uselist:
info = cls.relationship_info.get(rel_name) class_name = u'[%s]' % class_name
if info['type'] in ('relationship', 'backref'): yield u'(→ %s)' % class_name
yield u'%s.\ **%s**' % (cls.__name__, rel_name) if prop.__doc__:
class_name = u':class:`~pokedex.db.tables.%s`' % info['argument'].__name__ yield u''
if info.get('uselist', True): yield u' ' + unicode(prop.__doc__)
class_name = u'[%s]' % class_name if rel.secondary is not None:
yield u'(→ %s)' % class_name yield u''
if 'description' in info: yield ' Association table: ``%s``' % rel.secondary
yield u'' #if rel.primaryjoin is not None:
yield u' ' + unicode(info['description']) # yield u''
''' # yield ' Join condition: ``%s``' % rel.primaryjoin
if info.get('secondary') is not None: # if rel.secondaryjoin is not None:
yield u'' # yield ' , ``%s``' % rel.secondaryjoin
yield ' Association table: ``%s``' % info['secondary'] if rel.order_by:
if 'primaryjoin' in info: yield u''
yield u'') yield u' '
yield ' Join condition: ``%s``' % info['primaryjoin'] yield ' Ordered by: ' + u', '.join(
if 'secondaryjoin' in info: u'``%s``' % o for o in rel.order_by)
yield ' , ``%s``' % info['secondaryjoin'] elif isinstance(prop, AssociationProxy):
''' yield u'%s.\ **%s**:' % (cls.__name__, attr_name)
if 'order_by' in info: yield '``{prop.remote_attr.key}`` of ``self.{prop.target_collection}``'.format(
yield u'' prop=prop)
try: '''if 'description' in info:
order = iter(info['order_by']) yield u''
except TypeError: yield u' ' + unicode(info['description'])'''
order = [info['order_by']] else:
yield u' ' continue
yield ' Ordered by: ' + u', '.join( yield u''
u'``%s``' % o for o in order) remaining_attrs.remove(attr_name)
elif info['type'] == 'association_proxy':
yield u'%s.\ **%s**:' % (cls.__name__, rel_name)
yield '``{info[attr]}`` of ``self.{info[target_collection]}``'.format(
info=info)
if 'description' in info:
yield u''
yield u' ' + unicode(info['description'])
else:
continue
yield u''
remaining_attrs.remove(rel_name)
@with_header(u'Undocumented') @with_header(u'Undocumented')
def generate_undocumented(cls, remaining_attrs): def generate_undocumented(cls, remaining_attrs):

View file

@ -8,7 +8,7 @@ setup(
'pokedex': ['data/csv/*.csv'] 'pokedex': ['data/csv/*.csv']
}, },
install_requires=[ install_requires=[
'SQLAlchemy>=0.7', 'SQLAlchemy>=0.7.3',
'whoosh>=2.2.2', 'whoosh>=2.2.2',
'markdown', 'markdown',
'construct', 'construct',