Sigh! Remove support for strings as keys; use Language objects.
authorEevee <git@veekun.com>
Tue, 22 Mar 2011 00:54:28 +0000 (17:54 -0700)
committerEevee <git@veekun.com>
Tue, 22 Mar 2011 00:54:28 +0000 (17:54 -0700)
pokedex/db/tables.py
pokedex/tests/test_schema.py

index f40583e..20fcbea 100644 (file)
@@ -570,24 +570,6 @@ class Language(TableBase):
     name = TextColumn(Unicode(16), nullable=False, index=True, plural='names',
         info=dict(description="The name", format='plaintext', official=True))
 
     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
     """
 class Location(TableBase):
     u"""A place in the Pokémon world
     """
@@ -1965,34 +1947,9 @@ TODO remove this requirement
 
     # Add full-table relations to the original class
     # Class.foo_bars
 
     # 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,
     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',
     ))
         # TODO
         lazy='select',
     ))
@@ -2014,8 +1971,6 @@ TODO remove this requirement
 
     # Add per-column proxies to the original class
     for name, column in kwitems:
 
     # 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) -- accessor for the default language's value
         setattr(foreign_class, name,
             association_proxy(local_relation_name, name))
@@ -2023,8 +1978,9 @@ TODO remove this requirement
         # 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
         # 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 = Translations()
+            row.language = language
             setattr(row, name, value)
             return row
         setattr(foreign_class, name + '_map',
             setattr(row, name, value)
             return row
         setattr(foreign_class, name + '_map',
index 63f48ce..9aa3943 100644 (file)
@@ -7,6 +7,8 @@ from sqlalchemy.orm.session import Session
 from sqlalchemy.ext.declarative import declarative_base
 
 from pokedex.db import tables, markdown
 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"""
 
 def test_variable_names():
     """We want pokedex.db.tables to export tables using the class name"""
@@ -46,7 +48,7 @@ def test_i18n_table_creation():
         __singlename__ = 'foo'
         id = Column(Integer, primary_key=True, nullable=False)
 
         __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)),
     )
         _language_class=Language,
         name = Column(String(100)),
     )
@@ -97,15 +99,22 @@ def test_i18n_table_creation():
     foo = sess.query(Foo).params(_default_language='en').one()
 
     # Dictionary of language identifiers => names
     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()
 
 
     # 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) \
     # THIS SHOULD WORK SOMEDAY
     #    .options(joinedload(Foo.name)) \
     foo = sess.query(Foo) \
@@ -116,28 +125,28 @@ def test_i18n_table_creation():
 
     sess.expire_all()
 
 
     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()
 
     # 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()
 
 
     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 = 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()
 
 
     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.
 
 def test_texts():
     """Check DB schema for integrity of text columns & translations.