name = TextColumn(Unicode(16), nullable=False, index=True, plural='names',
info=dict(description="The name", format='plaintext', official=True))
- # Languages compare equal to its identifier, so a dictionary of
- # translations, with a Language as the key, can be indexed by the identifier
- def __eq__(self, other):
- try:
- return (
- self is other or
- self.identifier == other or
- self.identifier == other.identifier
- )
- except AttributeError:
- return NotImplemented
-
- def __ne__(self, other):
- return not (self == other)
-
- def __hash__(self):
- return hash(self.identifier)
-
class Location(TableBase):
u"""A place in the Pokémon world
"""
# Add full-table relations to the original class
# Class.foo_bars
- class LanguageMapping(MappedCollection):
- """Baby class that converts a language identifier key into an actual
- language object, allowing for `foo.bars['en'] = Translations(...)`.
-
- Needed for per-column association proxies to function as setters.
- """
- @collection.internally_instrumented
- def __setitem__(self, key, value, _sa_initiator=None):
- if key in self:
- raise NotImplementedError("Can't replace the whole row, sorry!")
-
- # Only do this nonsense if the value is a dangling object; if it's
- # in the db it already has its language_id
- if not object_session(value):
- # This took quite some source-diving to find, but it oughta be
- # the object that actually owns this collection.
- obj = collection_adapter(self).owner_state.obj()
- session = object_session(obj)
- value.language = session.query(_language_class) \
- .filter_by(identifier=key).one()
-
- super(LanguageMapping, self).__setitem__(key, value, _sa_initiator)
-
setattr(foreign_class, _table_name, relation(Translations,
primaryjoin=foreign_class.id == Translations.object_id,
- #collection_class=attribute_mapped_collection('_language_identifier'),
- collection_class=partial(LanguageMapping,
- lambda obj: obj._language_identifier),
+ collection_class=attribute_mapped_collection('language'),
# TODO
lazy='select',
))
# Add per-column proxies to the original class
for name, column in kwitems:
- # TODO should these proxies be mutable?
-
# Class.(column) -- accessor for the default language's value
setattr(foreign_class, name,
association_proxy(local_relation_name, name))
# Class.(column)_map -- accessor for the language dict
# Need a custom creator since Translations doesn't have an init, and
# these are passed as *args anyway
- def creator(language_code, value):
+ def creator(language, value):
row = Translations()
+ row.language = language
setattr(row, name, value)
return row
setattr(foreign_class, name + '_map',
from sqlalchemy.ext.declarative import declarative_base
from pokedex.db import tables, markdown
+from pokedex.db.multilang import create_translation_table
+from pokedex.db.tables import create_translation_table
def test_variable_names():
"""We want pokedex.db.tables to export tables using the class name"""
__singlename__ = 'foo'
id = Column(Integer, primary_key=True, nullable=False)
- FooText = tables.create_translation_table('foo_text', Foo,
+ FooText = create_translation_table('foo_text', Foo,
_language_class=Language,
name = Column(String(100)),
)
foo = sess.query(Foo).params(_default_language='en').one()
# Dictionary of language identifiers => names
- assert foo.name_map['en'] == 'english'
- assert foo.name_map['jp'] == 'nihongo'
+ assert foo.name_map[lang_en] == 'english'
+ assert foo.name_map[lang_jp] == 'nihongo'
# Default language, currently English
assert foo.name == 'english'
sess.expire_all()
- ### Test 2: joinedload on the default name should appear to work
+ ### Test 2: querying by default language name should work
+ foo = sess.query(Foo).filter_by(name='english').one()
+
+ assert foo.name == 'english'
+
+ sess.expire_all()
+
+ ### Test 3: joinedload on the default name should appear to work
# THIS SHOULD WORK SOMEDAY
# .options(joinedload(Foo.name)) \
foo = sess.query(Foo) \
sess.expire_all()
- ### Test 3: joinedload on all the names should appear to work
+ ### Test 4: joinedload on all the names should appear to work
# THIS SHOULD ALSO WORK SOMEDAY
# .options(joinedload(Foo.name_map)) \
foo = sess.query(Foo) \
.options(joinedload(Foo.foo_text)) \
.one()
- assert foo.name_map['en'] == 'english'
- assert foo.name_map['jp'] == 'nihongo'
+ assert foo.name_map[lang_en] == 'english'
+ assert foo.name_map[lang_jp] == 'nihongo'
sess.expire_all()
- ### Test 4: Mutating the dict collection should work
+ ### Test 5: Mutating the dict collection should work
foo = sess.query(Foo).one()
- foo.name_map['en'] = 'different english'
- foo.name_map['ru'] = 'new russian'
+ foo.name_map[lang_en] = 'different english'
+ foo.name_map[lang_ru] = 'new russian'
sess.commit()
- assert foo.name_map['en'] == 'different english'
- assert foo.name_map['ru'] == 'new russian'
+ assert foo.name_map[lang_en] == 'different english'
+ assert foo.name_map[lang_ru] == 'new russian'
def test_texts():
"""Check DB schema for integrity of text columns & translations.