Merge branch 'encukou'

This commit is contained in:
Eevee 2011-04-05 21:04:32 -07:00
commit acf44c63a0
5 changed files with 70 additions and 39 deletions

View file

@ -1,7 +1,7 @@
from sqlalchemy import MetaData, Table, engine_from_config, orm from sqlalchemy import engine_from_config, orm
from ..defaults import get_default_db_uri from ..defaults import get_default_db_uri
from .tables import metadata from .tables import Language, metadata
from .multilang import MultilangSession, MultilangScopedSession from .multilang import MultilangSession, MultilangScopedSession
@ -41,7 +41,13 @@ def connect(uri=None, session_args={}, engine_args={}, engine_prefix=''):
all_session_args = dict(autoflush=True, autocommit=False, bind=engine) all_session_args = dict(autoflush=True, autocommit=False, bind=engine)
all_session_args.update(session_args) all_session_args.update(session_args)
sm = orm.sessionmaker(class_=MultilangSession, **all_session_args) sm = orm.sessionmaker(class_=MultilangSession, language_class=Language,
**all_session_args)
session = MultilangScopedSession(sm) session = MultilangScopedSession(sm)
# Default to English
session.default_language = session.query(Language) \
.filter_by(identifier=u'en') \
.one()
return session return session

View file

@ -106,6 +106,9 @@ class MarkdownColumn(sqlalchemy.types.TypeDecorator):
impl = sqlalchemy.types.Unicode impl = sqlalchemy.types.Unicode
def process_bind_param(self, value, dialect): def process_bind_param(self, value, dialect):
if value is None:
return None
if not isinstance(value, basestring): if not isinstance(value, basestring):
# Can't assign, e.g., MarkdownString objects yet # Can't assign, e.g., MarkdownString objects yet
raise NotImplementedError raise NotImplementedError
@ -113,4 +116,7 @@ class MarkdownColumn(sqlalchemy.types.TypeDecorator):
return unicode(value) return unicode(value)
def process_result_value(self, value, dialect): def process_result_value(self, value, dialect):
if value is None:
return None
return MarkdownString(value) return MarkdownString(value)

View file

@ -155,17 +155,26 @@ def create_translation_table(_table_name, foreign_class, relation_name,
return Translations return Translations
class MultilangSession(Session): class MultilangSession(Session):
"""A tiny Session subclass that adds support for a default language.""" """A tiny Session subclass that adds support for a default language.
_default_language_id = 9 # English. XXX magic constant
Caller will need to assign something to `default_language` before this will
actually work.
"""
_default_language_id = 0 # Better fill this in, caller
def __init__(self, *args, **kwargs):
self.language_class = kwargs.pop('language_class')
super(MultilangSession, self).__init__(*args, **kwargs)
@property @property
def default_language(self): def default_language(self):
# XXX need to get the right mapped class for this to work return self.query(self.language_class) \
raise NotImplementedError .filter_by(id=self._default_language_id) \
.one()
@default_language.setter @default_language.setter
def default_language(self, new): def default_language(self, new):
self._default_language_id = new#.id self._default_language_id = new.id
@default_language.deleter @default_language.deleter
def default_language(self): def default_language(self):

View file

@ -62,6 +62,9 @@ class TableSuperclass(object):
def __str__(self): def __str__(self):
return unicode(self).encode('utf8') return unicode(self).encode('utf8')
def __repr__(self):
return unicode(self).encode('utf8')
mapped_classes = [] mapped_classes = []
class TableMetaclass(DeclarativeMeta): class TableMetaclass(DeclarativeMeta):
def __init__(cls, name, bases, attrs): def __init__(cls, name, bases, attrs):
@ -121,9 +124,9 @@ create_translation_table('ability_names', Ability, 'names',
info=dict(description="The name", format='plaintext', official=True, ripped=True)), info=dict(description="The name", format='plaintext', official=True, ripped=True)),
) )
create_translation_table('ability_prose', Ability, 'prose', create_translation_table('ability_prose', Ability, 'prose',
effect = Column(markdown.MarkdownColumn(5120), nullable=False, effect = Column(markdown.MarkdownColumn(5120), nullable=True,
info=dict(description="A detailed description of this ability's effect", format='markdown')), info=dict(description="A detailed description of this ability's effect", format='markdown')),
short_effect = Column(markdown.MarkdownColumn(255), nullable=False, short_effect = Column(markdown.MarkdownColumn(255), nullable=True,
info=dict(description="A short summary of this ability's effect", format='markdown')), info=dict(description="A short summary of this ability's effect", format='markdown')),
) )
@ -232,9 +235,9 @@ class ContestEffect(TableBase):
info=dict(description="The base number of hearts the user's opponent loses")) info=dict(description="The base number of hearts the user's opponent loses"))
create_translation_table('contest_effect_prose', ContestEffect, 'prose', create_translation_table('contest_effect_prose', ContestEffect, 'prose',
flavor_text = Column(Unicode(64), nullable=False, flavor_text = Column(Unicode(64), nullable=True,
info=dict(description="The in-game description of this effect", official=True, format='gametext')), info=dict(description="The in-game description of this effect", official=True, format='gametext')),
effect = Column(Unicode(255), nullable=False, effect = Column(Unicode(255), nullable=True,
info=dict(description="A detailed description of the effect", format='plaintext')), info=dict(description="A detailed description of the effect", format='plaintext')),
) )
@ -250,11 +253,11 @@ class ContestType(TableBase):
create_translation_table('contest_type_names', ContestType, 'names', create_translation_table('contest_type_names', ContestType, 'names',
relation_lazy='joined', relation_lazy='joined',
name = Column(Unicode(6), nullable=False, index=True, name = Column(Unicode(6), nullable=True, index=True,
info=dict(description="The name", format='plaintext', official=True)), info=dict(description="The name", format='plaintext', official=True)),
flavor = Column(Unicode(6), nullable=False, flavor = Column(Unicode(6), nullable=True,
info=dict(description="The name of the corresponding Berry flavor", official=True, format='plaintext')), info=dict(description="The name of the corresponding Berry flavor", official=True, format='plaintext')),
color = Column(Unicode(6), nullable=False, color = Column(Unicode(6), nullable=True,
info=dict(description=u"The name of the corresponding Pokéblock color", official=True, format='plaintext')), info=dict(description=u"The name of the corresponding Pokéblock color", official=True, format='plaintext')),
) )
@ -500,9 +503,9 @@ create_translation_table('item_names', Item, 'names',
info=dict(description="The name", format='plaintext', official=True, ripped=True)), info=dict(description="The name", format='plaintext', official=True, ripped=True)),
) )
create_translation_table('item_prose', Item, 'prose', create_translation_table('item_prose', Item, 'prose',
short_effect = Column(markdown.MarkdownColumn(256), nullable=False, short_effect = Column(markdown.MarkdownColumn(256), nullable=True,
info=dict(description="A short summary of the effect", format='plaintext')), info=dict(description="A short summary of the effect", format='markdown')),
effect = Column(markdown.MarkdownColumn(5120), nullable=False, effect = Column(markdown.MarkdownColumn(5120), nullable=True,
info=dict(description=u"Detailed description of the item's effect.", format='markdown')), info=dict(description=u"Detailed description of the item's effect.", format='markdown')),
) )
create_translation_table('item_flavor_summaries', Item, 'flavor_summaries', create_translation_table('item_flavor_summaries', Item, 'flavor_summaries',
@ -540,9 +543,9 @@ class ItemFlag(TableBase):
info=dict(description="Identifier of the flag", format='identifier')) info=dict(description="Identifier of the flag", format='identifier'))
create_translation_table('item_flag_prose', ItemFlag, 'prose', create_translation_table('item_flag_prose', ItemFlag, 'prose',
name = Column(Unicode(24), nullable=False, index=True, name = Column(Unicode(24), nullable=True, index=True,
info=dict(description="The name", format='plaintext', official=False)), info=dict(description="The name", format='plaintext', official=False)),
description = Column(Unicode(64), nullable=False, description = Column(Unicode(64), nullable=True,
info=dict(description="Short description of the flag", format='plaintext')), info=dict(description="Short description of the flag", format='plaintext')),
) )
@ -784,9 +787,9 @@ class MoveDamageClass(TableBase):
create_translation_table('move_damage_class_prose', MoveDamageClass, 'prose', create_translation_table('move_damage_class_prose', MoveDamageClass, 'prose',
relation_lazy='joined', relation_lazy='joined',
name = Column(Unicode(16), nullable=False, index=True, name = Column(Unicode(16), nullable=True, index=True,
info=dict(description="The name", format='plaintext', official=False)), info=dict(description="The name", format='plaintext', official=False)),
description = Column(Unicode(64), nullable=False, description = Column(Unicode(64), nullable=True,
info=dict(description="A description of the class", format='plaintext')), info=dict(description="A description of the class", format='plaintext')),
) )
@ -799,9 +802,9 @@ class MoveEffect(TableBase):
info=dict(description="A numeric ID")) info=dict(description="A numeric ID"))
create_translation_table('move_effect_prose', MoveEffect, 'prose', create_translation_table('move_effect_prose', MoveEffect, 'prose',
short_effect = Column(Unicode(256), nullable=False, short_effect = Column(Unicode(256), nullable=True,
info=dict(description="A short summary of the effect", format='plaintext')), info=dict(description="A short summary of the effect", format='plaintext')),
effect = Column(Unicode(5120), nullable=False, effect = Column(Unicode(5120), nullable=True,
info=dict(description="A detailed description of the effect", format='plaintext')), info=dict(description="A detailed description of the effect", format='plaintext')),
) )
@ -877,9 +880,9 @@ class MoveFlagType(TableBase):
create_translation_table('move_flag_type_prose', MoveFlagType, 'prose', create_translation_table('move_flag_type_prose', MoveFlagType, 'prose',
relation_lazy='joined', relation_lazy='joined',
name = Column(Unicode(32), nullable=False, index=True, name = Column(Unicode(32), nullable=True, index=True,
info=dict(description="The name", format='plaintext', official=False)), info=dict(description="The name", format='plaintext', official=False)),
description = Column(markdown.MarkdownColumn(128), nullable=False, description = Column(markdown.MarkdownColumn(128), nullable=True,
info=dict(description="A short description of the flag", format='markdown')), info=dict(description="A short description of the flag", format='markdown')),
) )
@ -979,9 +982,9 @@ class MoveTarget(TableBase):
create_translation_table('move_target_prose', MoveTarget, 'prose', create_translation_table('move_target_prose', MoveTarget, 'prose',
relation_lazy='joined', relation_lazy='joined',
name = Column(Unicode(32), nullable=False, index=True, name = Column(Unicode(32), nullable=True, index=True,
info=dict(description="The name", format='plaintext', official=False)), info=dict(description="The name", format='plaintext', official=False)),
description = Column(Unicode(128), nullable=False, description = Column(Unicode(128), nullable=True,
info=dict(description="A description", format='plaintext')), info=dict(description="A description", format='plaintext')),
) )
@ -1072,9 +1075,9 @@ class Pokedex(TableBase):
create_translation_table('pokedex_prose', Pokedex, 'prose', create_translation_table('pokedex_prose', Pokedex, 'prose',
relation_lazy='joined', relation_lazy='joined',
name = Column(Unicode(16), nullable=False, index=True, name = Column(Unicode(16), nullable=True, index=True,
info=dict(description="The name", format='plaintext', official=False)), info=dict(description="The name", format='plaintext', official=False)),
description = Column(Unicode(512), nullable=False, description = Column(Unicode(512), nullable=True,
info=dict(description=u"A longer description of the Pokédex", format='plaintext')), info=dict(description=u"A longer description of the Pokédex", format='plaintext')),
) )
@ -1202,9 +1205,9 @@ class Pokemon(TableBase):
create_translation_table('pokemon_names', Pokemon, 'names', create_translation_table('pokemon_names', Pokemon, 'names',
relation_lazy='joined', relation_lazy='joined',
name = Column(Unicode(20), nullable=False, index=True, name = Column(Unicode(20), nullable=True, index=True,
info=dict(description="The name", format='plaintext', official=True, ripped=True)), info=dict(description="The name", format='plaintext', official=True, ripped=True)),
species = Column(Unicode(16), nullable=False, species = Column(Unicode(16), nullable=True,
info=dict(description=u'The short flavor text, such as "Seed" or "Lizard"; usually affixed with the word "Pokémon"', info=dict(description=u'The short flavor text, such as "Seed" or "Lizard"; usually affixed with the word "Pokémon"',
official=True, format='plaintext')), official=True, format='plaintext')),
) )
@ -1389,7 +1392,7 @@ PokemonFormGroup.id = PokemonFormGroup.pokemon_id
create_translation_table('pokemon_form_group_prose', PokemonFormGroup, 'prose', create_translation_table('pokemon_form_group_prose', PokemonFormGroup, 'prose',
term = Column(Unicode(16), nullable=True, term = Column(Unicode(16), nullable=True,
info=dict(description=u"The term for this Pokémon's forms, e.g. \"Cloak\" for Burmy or \"Forme\" for Deoxys.", official=True, format='plaintext')), info=dict(description=u"The term for this Pokémon's forms, e.g. \"Cloak\" for Burmy or \"Forme\" for Deoxys.", official=True, format='plaintext')),
description = Column(markdown.MarkdownColumn(1024), nullable=False, description = Column(markdown.MarkdownColumn(1024), nullable=True,
info=dict(description=u"Description of how the forms work", format='markdown')), info=dict(description=u"Description of how the forms work", format='markdown')),
) )
@ -1481,9 +1484,9 @@ class PokemonMoveMethod(TableBase):
create_translation_table('pokemon_move_method_prose', PokemonMoveMethod, 'prose', create_translation_table('pokemon_move_method_prose', PokemonMoveMethod, 'prose',
relation_lazy='joined', relation_lazy='joined',
name = Column(Unicode(64), nullable=False, index=True, name = Column(Unicode(64), nullable=True, index=True,
info=dict(description="The name", format='plaintext', official=False)), info=dict(description="The name", format='plaintext', official=False)),
description = Column(Unicode(255), nullable=False, description = Column(Unicode(255), nullable=True,
info=dict(description=u"A detailed description of how the method works", format='plaintext')), info=dict(description=u"A detailed description of how the method works", format='plaintext')),
) )
@ -1499,9 +1502,9 @@ class PokemonShape(TableBase):
create_translation_table('pokemon_shape_prose', PokemonShape, 'prose', create_translation_table('pokemon_shape_prose', PokemonShape, 'prose',
relation_lazy='joined', relation_lazy='joined',
name = Column(Unicode(24), nullable=False, index=True, name = Column(Unicode(24), nullable=True, index=True,
info=dict(description="The name", format='plaintext', official=False)), info=dict(description="The name", format='plaintext', official=False)),
awesome_name = Column(Unicode(16), nullable=False, awesome_name = Column(Unicode(16), nullable=True,
info=dict(description=u"A splendiferous name of the body shape", format='plaintext')), info=dict(description=u"A splendiferous name of the body shape", format='plaintext')),
) )

View file

@ -66,7 +66,7 @@ def test_i18n_table_creation():
# OK, create all the tables and gimme a session # OK, create all the tables and gimme a session
Base.metadata.create_all() Base.metadata.create_all()
sm = sessionmaker(class_=MultilangSession) sm = sessionmaker(class_=MultilangSession, language_class=Language)
sess = MultilangScopedSession(sm) sess = MultilangScopedSession(sm)
# Create some languages and foos to bind together # Create some languages and foos to bind together
@ -82,7 +82,7 @@ def test_i18n_table_creation():
# Commit so the above get primary keys filled in # Commit so the above get primary keys filled in
sess.commit() sess.commit()
sess.default_language = lang_en.id sess.default_language = lang_en
# Give our foo some names, as directly as possible # Give our foo some names, as directly as possible
foo_text = FooText() foo_text = FooText()
@ -171,6 +171,7 @@ def test_texts():
good_formats = 'identifier latex'.split() good_formats = 'identifier latex'.split()
assert_text = '%s is not language-specific' assert_text = '%s is not language-specific'
columns = sorted(cls.__table__.c, key=lambda c: c.name) columns = sorted(cls.__table__.c, key=lambda c: c.name)
text_columns = []
for column in columns: for column in columns:
format = column.info.get('format', None) format = column.info.get('format', None)
if format is not None: if format is not None:
@ -183,6 +184,7 @@ def test_texts():
raise AssertionError('%s: identifier column name/type mismatch' % column) raise AssertionError('%s: identifier column name/type mismatch' % column)
if column.info.get('official', None) and format not in 'gametext plaintext': if column.info.get('official', None) and format not in 'gametext plaintext':
raise AssertionError('%s: official text with bad format' % column) raise AssertionError('%s: official text with bad format' % column)
text_columns.append(column)
else: else:
if isinstance(column.type, (markdown.MarkdownColumn, tables.Unicode)): if isinstance(column.type, (markdown.MarkdownColumn, tables.Unicode)):
raise AssertionError('%s: text column without format' % column) raise AssertionError('%s: text column without format' % column)
@ -190,6 +192,11 @@ def test_texts():
raise AssertionError('%s: non-plaintext name' % column) raise AssertionError('%s: non-plaintext name' % column)
# No mention of English in the description # No mention of English in the description
assert 'English' not in column.info['description'], column assert 'English' not in column.info['description'], column
# If there's more than one text column in a translation table,
# they have to be nullable, to support missing translations
if hasattr(cls, 'local_language') and len(text_columns) > 1:
for column in text_columns:
assert column.nullable
def test_identifiers_with_names(): def test_identifiers_with_names():
"""Test that named tables have identifiers, and non-named tables don't """Test that named tables have identifiers, and non-named tables don't