Merge branch 'encukou'

This commit is contained in:
Eevee 2011-04-01 17:10:13 -07:00
commit 42a3989dc6
10 changed files with 245 additions and 225 deletions

View file

@ -0,0 +1 @@
item_id,local_language_id,flavor_summary
1 item_id local_language_id flavor_summary

View file

@ -8,3 +8,4 @@ language_id,local_language_id,name
7,9,Spanish
8,9,Italian
9,9,English
10,9,Czech

1 language_id local_language_id name
8 7 9 Spanish
9 8 9 Italian
10 9 9 English
11 10 9 Czech

View file

@ -8,3 +8,4 @@ id,iso639,iso3166,identifier,official,order
7,es,es,es,1,
8,it,it,it,1,
9,en,us,en,1,0
10,cs,cz,cs,0,

1 id iso639 iso3166 identifier official order
8 7 es es es 1
9 8 it it it 1
10 9 en us en 1 0
11 10 cs cz cs 0

View file

@ -0,0 +1 @@
move_id,local_language_id,flavor_summary
1 move_id local_language_id flavor_summary

View file

@ -0,0 +1 @@
pokemon_id,local_language_id,flavor_summary
1 pokemon_id local_language_id flavor_summary

View file

@ -174,14 +174,10 @@ def load(session, tables=[], directory=None, drop_tables=False, verbose=False, s
if not safe and session.connection().dialect.name == 'postgresql':
"""
Postgres' CSV dialect is nearly the same as ours, except that it
treats completely empty values as NULL, and empty quoted
strings ("") as an empty strings.
Pokedex dump does not quote empty strings. So, both empty strings
and NULLs are read in as NULL.
For an empty string in a NOT NULL column, the load will fail, and
load will fall back to the cross-backend row-by-row loading. And in
nullable columns, we already load empty stings as NULL.
Postgres' CSV dialect works with our data, if we mark the not-null
columns with FORCE NOT NULL.
COPY is only allowed for DB superusers. If you're not one, use safe
loading (pokedex load -S).
"""
session.commit()
not_null_cols = [c for c in column_names if not table_obj.c[c].nullable]

View file

@ -77,9 +77,11 @@ def create_translation_table(_table_name, foreign_class, relation_name,
# Create the table object
table = Table(_table_name, foreign_class.__table__.metadata,
Column(foreign_key_name, Integer, ForeignKey(foreign_class.id),
primary_key=True, nullable=False),
primary_key=True, nullable=False,
info=dict(description="ID of the %s these texts relate to" % foreign_class.__singlename__)),
Column('local_language_id', Integer, ForeignKey(language_class.id),
primary_key=True, nullable=False),
primary_key=True, nullable=False,
info=dict(description="Language these texts are in")),
)
Translations.__table__ = table
@ -145,6 +147,9 @@ def create_translation_table(_table_name, foreign_class, relation_name,
setattr(foreign_class, name + '_map',
association_proxy(relation_name, name, creator=creator))
# Add to the list of translation classes
foreign_class.translation_classes.append(Translations)
# Done
return Translations

View file

@ -15,6 +15,8 @@ Columns have a info dictionary with these keys:
- identifier: A fan-made identifier in the [-_a-z0-9]* format. Not intended
for translation.
- latex: A formula in LaTeX syntax.
- ripped: True for text that has been ripped from the games, and can be ripped
again for new versions or languages
See `pokedex.db.multilang` for how localizable text columns work. The session
classes in that module can be used to change the default language.
@ -25,7 +27,7 @@ import collections
from functools import partial
from sqlalchemy import Column, ForeignKey, MetaData, PrimaryKeyConstraint, Table, UniqueConstraint
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.orm import backref, relation
from sqlalchemy.orm.session import Session
@ -60,8 +62,16 @@ class TableSuperclass(object):
def __str__(self):
return unicode(self).encode('utf8')
mapped_classes = []
class TableMetaclass(DeclarativeMeta):
def __init__(cls, name, bases, attrs):
super(TableMetaclass, cls).__init__(name, bases, attrs)
if hasattr(cls, '__tablename__'):
mapped_classes.append(cls)
cls.translation_classes = []
metadata = MetaData()
TableBase = declarative_base(metadata=metadata, cls=TableSuperclass)
TableBase = declarative_base(metadata=metadata, cls=TableSuperclass, metaclass=TableMetaclass)
### Need Language first, to create the partial() below
@ -108,7 +118,7 @@ class Ability(TableBase):
create_translation_table('ability_names', Ability, 'names',
relation_lazy='joined',
name = Column(Unicode(24), nullable=False, index=True,
info=dict(description="The name", format='plaintext', official=True)),
info=dict(description="The name", format='plaintext', official=True, ripped=True)),
)
create_translation_table('ability_prose', Ability, 'prose',
effect = Column(markdown.MarkdownColumn(5120), nullable=False,
@ -351,22 +361,6 @@ class EncounterConditionValueMap(TableBase):
encounter_condition_value_id = Column(Integer, ForeignKey('encounter_condition_values.id'), primary_key=True, nullable=False, autoincrement=False,
info=dict(description="The ID of the encounter condition value"))
class EncounterTerrain(TableBase):
u"""A way the player can enter a wild encounter, e.g., surfing, fishing, or walking through tall grass.
"""
__tablename__ = 'encounter_terrain'
__singlename__ = __tablename__
id = Column(Integer, primary_key=True, nullable=False,
info=dict(description="A unique ID for the terrain"))
identifier = Column(Unicode(64), nullable=False,
info=dict(description="An identifier", format='identifier'))
create_translation_table('encounter_terrain_prose', EncounterTerrain, 'prose',
name = Column(Unicode(64), nullable=False, index=True,
info=dict(description="The name", format='plaintext', official=False)),
)
class EncounterSlot(TableBase):
u"""An abstract "slot" within a terrain, associated with both some set of conditions and a rarity.
@ -386,6 +380,22 @@ class EncounterSlot(TableBase):
rarity = Column(Integer, nullable=False,
info=dict(description="The chance of the encounter as a percentage"))
class EncounterTerrain(TableBase):
u"""A way the player can enter a wild encounter, e.g., surfing, fishing, or walking through tall grass.
"""
__tablename__ = 'encounter_terrain'
__singlename__ = __tablename__
id = Column(Integer, primary_key=True, nullable=False,
info=dict(description="A unique ID for the terrain"))
identifier = Column(Unicode(64), nullable=False,
info=dict(description="An identifier", format='identifier'))
create_translation_table('encounter_terrain_prose', EncounterTerrain, 'prose',
name = Column(Unicode(64), nullable=False, index=True,
info=dict(description="The name", format='plaintext', official=False)),
)
class EvolutionChain(TableBase):
u"""A family of Pokémon that are linked by evolution
"""
@ -487,7 +497,7 @@ class Item(TableBase):
create_translation_table('item_names', Item, 'names',
relation_lazy='joined',
name = Column(Unicode(20), nullable=False, index=True,
info=dict(description="The name", format='plaintext', official=True)),
info=dict(description="The name", format='plaintext', official=True, ripped=True)),
)
create_translation_table('item_prose', Item, 'prose',
short_effect = Column(Unicode(256), nullable=False,
@ -495,6 +505,10 @@ create_translation_table('item_prose', Item, 'prose',
effect = Column(markdown.MarkdownColumn(5120), nullable=False,
info=dict(description=u"Detailed description of the item's effect.", format='markdown')),
)
create_translation_table('item_flavor_summaries', Item, 'flavor_summaries',
flavor_summary = Column(Unicode(512), nullable=True,
info=dict(description=u"Text containing facts from all flavor texts, for languages without official game translations", official=False, format='plaintext', ripped=True)),
)
class ItemCategory(TableBase):
u"""An item category
@ -546,6 +560,7 @@ class ItemFlavorText(TableBase):
"""
__tablename__ = 'item_flavor_text'
__singlename__ = 'item_flavor_text'
summary_column = Item.flavor_summaries_table, 'flavor_summary'
item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False,
info=dict(description="The ID of the item"))
version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, autoincrement=False, nullable=False,
@ -675,6 +690,52 @@ class Machine(TableBase):
"""
return self.machine_number >= 100
class Move(TableBase):
u"""A Move: technique or attack a Pokémon can learn to use
"""
__tablename__ = 'moves'
__singlename__ = 'move'
id = Column(Integer, primary_key=True, nullable=False,
info=dict(description="A numeric ID"))
identifier = Column(Unicode(24), nullable=False,
info=dict(description="An identifier", format='identifier'))
generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False,
info=dict(description="ID of the generation this move first appeared in"))
type_id = Column(Integer, ForeignKey('types.id'), nullable=False,
info=dict(description="ID of the move's elemental type"))
power = Column(SmallInteger, nullable=False,
info=dict(description="Base power of the move"))
pp = Column(SmallInteger, nullable=True,
info=dict(description="Base PP (Power Points) of the move, nullable if not applicable (e.g. Struggle and Shadow moves)."))
accuracy = Column(SmallInteger, nullable=True,
info=dict(description="Accuracy of the move; NULL means it never misses"))
priority = Column(SmallInteger, nullable=False,
info=dict(description="The move's priority bracket"))
target_id = Column(Integer, ForeignKey('move_targets.id'), nullable=False,
info=dict(description="ID of the target (range) of the move"))
damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=False,
info=dict(description="ID of the damage class (physical/special) of the move"))
effect_id = Column(Integer, ForeignKey('move_effects.id'), nullable=False,
info=dict(description="ID of the move's effect"))
effect_chance = Column(Integer, nullable=True,
info=dict(description="The chance for a secondary effect. What this is a chance of is specified by the move's effect."))
contest_type_id = Column(Integer, ForeignKey('contest_types.id'), nullable=True,
info=dict(description="ID of the move's Contest type (e.g. cool or smart)"))
contest_effect_id = Column(Integer, ForeignKey('contest_effects.id'), nullable=True,
info=dict(description="ID of the move's Contest effect"))
super_contest_effect_id = Column(Integer, ForeignKey('super_contest_effects.id'), nullable=True,
info=dict(description="ID of the move's Super Contest effect"))
create_translation_table('move_names', Move, 'names',
relation_lazy='joined',
name = Column(Unicode(24), nullable=False, index=True,
info=dict(description="The name", format='plaintext', official=True, ripped=True))
)
create_translation_table('move_flavor_summaries', Move, 'flavor_summaries',
flavor_summary = Column(Unicode(512), nullable=True,
info=dict(description=u"Text containing facts from all flavor texts, for languages without official game translations", official=False, format='plaintext', ripped=True)),
)
class MoveBattleStyle(TableBase):
u"""A battle style of a move""" # XXX: Explain better
__tablename__ = 'move_battle_styles'
@ -690,33 +751,26 @@ create_translation_table('move_battle_style_prose', MoveBattleStyle, 'prose',
info=dict(description="The name", format='plaintext', official=False)),
)
class MoveEffectCategory(TableBase):
u"""Category of a move effect
"""
__tablename__ = 'move_effect_categories'
__singlename__ = 'move_effect_category'
id = Column(Integer, primary_key=True, nullable=False,
info=dict(description="A numeric ID"))
identifier = Column(Unicode(64), nullable=False,
info=dict(description="An identifier", format='identifier'))
can_affect_user = Column(Boolean, nullable=False,
info=dict(description="Set if the user can be affected"))
create_translation_table('move_effect_category_prose', MoveEffectCategory, 'prose',
name = Column(Unicode(64), nullable=False, index=True,
info=dict(description="The name", format='plaintext', official=False)),
)
class MoveEffectCategoryMap(TableBase):
u"""Maps a move effect category to a move effect
"""
__tablename__ = 'move_effect_category_map'
move_effect_id = Column(Integer, ForeignKey('move_effects.id'), primary_key=True, nullable=False,
info=dict(description="ID of the move effect"))
move_effect_category_id = Column(Integer, ForeignKey('move_effect_categories.id'), primary_key=True, nullable=False,
info=dict(description="ID of the category"))
affects_user = Column(Boolean, primary_key=True, nullable=False,
info=dict(description="Set if the user is affected"))
class MoveChangelog(TableBase):
"""History of changes to moves across main game versions."""
__tablename__ = 'move_changelog'
__singlename__ = 'move_changelog'
move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False,
info=dict(description="ID of the move that changed"))
changed_in_version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False,
info=dict(description="ID of the version group in which the move changed"))
type_id = Column(Integer, ForeignKey('types.id'), nullable=True,
info=dict(description="Prior type of the move, or NULL if unchanged"))
power = Column(SmallInteger, nullable=True,
info=dict(description="Prior base power of the move, or NULL if unchanged"))
pp = Column(SmallInteger, nullable=True,
info=dict(description="Prior base PP of the move, or NULL if unchanged"))
accuracy = Column(SmallInteger, nullable=True,
info=dict(description="Prior accuracy of the move, or NULL if unchanged"))
effect_id = Column(Integer, ForeignKey('move_effects.id'), nullable=True,
info=dict(description="Prior ID of the effect, or NULL if unchanged"))
effect_chance = Column(Integer, nullable=True,
info=dict(description="Prior effect chance, or NULL if unchanged"))
class MoveDamageClass(TableBase):
u"""Any of the damage classes moves can have, i.e. physical, special, or non-damaging.
@ -751,6 +805,34 @@ create_translation_table('move_effect_prose', MoveEffect, 'prose',
info=dict(description="A detailed description of the effect", format='plaintext')),
)
class MoveEffectCategory(TableBase):
u"""Category of a move effect
"""
__tablename__ = 'move_effect_categories'
__singlename__ = 'move_effect_category'
id = Column(Integer, primary_key=True, nullable=False,
info=dict(description="A numeric ID"))
identifier = Column(Unicode(64), nullable=False,
info=dict(description="An identifier", format='identifier'))
can_affect_user = Column(Boolean, nullable=False,
info=dict(description="Set if the user can be affected"))
create_translation_table('move_effect_category_prose', MoveEffectCategory, 'prose',
name = Column(Unicode(64), nullable=False, index=True,
info=dict(description="The name", format='plaintext', official=False)),
)
class MoveEffectCategoryMap(TableBase):
u"""Maps a move effect category to a move effect
"""
__tablename__ = 'move_effect_category_map'
move_effect_id = Column(Integer, ForeignKey('move_effects.id'), primary_key=True, nullable=False,
info=dict(description="ID of the move effect"))
move_effect_category_id = Column(Integer, ForeignKey('move_effect_categories.id'), primary_key=True, nullable=False,
info=dict(description="ID of the category"))
affects_user = Column(Boolean, primary_key=True, nullable=False,
info=dict(description="Set if the user is affected"))
class MoveEffectChangelog(TableBase):
"""History of changes to move effects across main game versions."""
__tablename__ = 'move_effect_changelog'
@ -805,6 +887,7 @@ class MoveFlavorText(TableBase):
u"""In-game description of a move
"""
__tablename__ = 'move_flavor_text'
summary_column = Move.flavor_summaries_table, 'flavor_summary'
move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
info=dict(description="ID of the move"))
version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False,
@ -871,7 +954,7 @@ class MoveMetaCategory(TableBase):
create_translation_table('move_meta_category_prose', MoveMetaCategory, 'prose',
relation_lazy='joined',
description = Column(Unicode(64), nullable=False,
info=dict(description="A description of the category")),
info=dict(description="A description of the category", format="plaintext", official=False)),
)
class MoveMetaStatChange(TableBase):
@ -902,70 +985,6 @@ create_translation_table('move_target_prose', MoveTarget, 'prose',
info=dict(description="A description", format='plaintext')),
)
class Move(TableBase):
u"""A Move: technique or attack a Pokémon can learn to use
"""
__tablename__ = 'moves'
__singlename__ = 'move'
id = Column(Integer, primary_key=True, nullable=False,
info=dict(description="A numeric ID"))
identifier = Column(Unicode(24), nullable=False,
info=dict(description="An identifier", format='identifier'))
generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False,
info=dict(description="ID of the generation this move first appeared in"))
type_id = Column(Integer, ForeignKey('types.id'), nullable=False,
info=dict(description="ID of the move's elemental type"))
power = Column(SmallInteger, nullable=False,
info=dict(description="Base power of the move"))
pp = Column(SmallInteger, nullable=True,
info=dict(description="Base PP (Power Points) of the move, nullable if not applicable (e.g. Struggle and Shadow moves)."))
accuracy = Column(SmallInteger, nullable=True,
info=dict(description="Accuracy of the move; NULL means it never misses"))
priority = Column(SmallInteger, nullable=False,
info=dict(description="The move's priority bracket"))
target_id = Column(Integer, ForeignKey('move_targets.id'), nullable=False,
info=dict(description="ID of the target (range) of the move"))
damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=False,
info=dict(description="ID of the damage class (physical/special) of the move"))
effect_id = Column(Integer, ForeignKey('move_effects.id'), nullable=False,
info=dict(description="ID of the move's effect"))
effect_chance = Column(Integer, nullable=True,
info=dict(description="The chance for a secondary effect. What this is a chance of is specified by the move's effect."))
contest_type_id = Column(Integer, ForeignKey('contest_types.id'), nullable=True,
info=dict(description="ID of the move's Contest type (e.g. cool or smart)"))
contest_effect_id = Column(Integer, ForeignKey('contest_effects.id'), nullable=True,
info=dict(description="ID of the move's Contest effect"))
super_contest_effect_id = Column(Integer, ForeignKey('super_contest_effects.id'), nullable=True,
info=dict(description="ID of the move's Super Contest effect"))
create_translation_table('move_names', Move, 'names',
relation_lazy='joined',
name = Column(Unicode(24), nullable=False, index=True,
info=dict(description="The name", format='plaintext', official=True))
)
class MoveChangelog(TableBase):
"""History of changes to moves across main game versions."""
__tablename__ = 'move_changelog'
__singlename__ = 'move_changelog'
move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False,
info=dict(description="ID of the move that changed"))
changed_in_version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False,
info=dict(description="ID of the version group in which the move changed"))
type_id = Column(Integer, ForeignKey('types.id'), nullable=True,
info=dict(description="Prior type of the move, or NULL if unchanged"))
power = Column(SmallInteger, nullable=True,
info=dict(description="Prior base power of the move, or NULL if unchanged"))
pp = Column(SmallInteger, nullable=True,
info=dict(description="Prior base PP of the move, or NULL if unchanged"))
accuracy = Column(SmallInteger, nullable=True,
info=dict(description="Prior accuracy of the move, or NULL if unchanged"))
effect_id = Column(Integer, ForeignKey('move_effects.id'), nullable=True,
info=dict(description="Prior ID of the effect, or NULL if unchanged"))
effect_chance = Column(Integer, nullable=True,
info=dict(description="Prior effect chance, or NULL if unchanged"))
class Nature(TableBase):
u"""A nature a Pokémon can have, such as Calm or Brave
"""
@ -994,7 +1013,7 @@ class Nature(TableBase):
create_translation_table('nature_names', Nature, 'names',
relation_lazy='joined',
name = Column(Unicode(8), nullable=False, index=True,
info=dict(description="The name", format='plaintext', official=True)),
info=dict(description="The name", format='plaintext', official=True, ripped=True)),
)
class NatureBattleStylePreference(TableBase):
@ -1184,11 +1203,15 @@ class Pokemon(TableBase):
create_translation_table('pokemon_names', Pokemon, 'names',
relation_lazy='joined',
name = Column(Unicode(20), nullable=False, index=True,
info=dict(description="The name", format='plaintext', official=True)),
info=dict(description="The name", format='plaintext', official=True, ripped=True)),
species = Column(Unicode(16), nullable=False,
info=dict(description=u'The short flavor text, such as "Seed" or "Lizard"; usually affixed with the word "Pokémon"',
official=True, format='plaintext')),
)
create_translation_table('pokemon_flavor_summaries', Pokemon, 'flavor_summaries',
flavor_summary = Column(Unicode(512), nullable=True,
info=dict(description=u"Text containing facts from all flavor texts, for languages without official game translations", official=False, format='plaintext', ripped=True)),
)
class PokemonAbility(TableBase):
u"""Maps an ability to a Pokémon that can have it
@ -1284,6 +1307,7 @@ class PokemonFlavorText(TableBase):
u"""In-game Pokédex descrption of a Pokémon.
"""
__tablename__ = 'pokemon_flavor_text'
summary_column = Pokemon.flavor_summaries_table, 'flavor_summary'
pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
info=dict(description=u"ID of the Pokémon"))
version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, nullable=False, autoincrement=False,
@ -1291,7 +1315,7 @@ class PokemonFlavorText(TableBase):
language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False,
info=dict(description="The language"))
flavor_text = Column(Unicode(255), nullable=False,
info=dict(description=u"ID of the version that has this flavor text", official=True, format='gametext'))
info=dict(description=u"The flavor text", official=True, format='gametext'))
class PokemonForm(TableBase):
u"""An individual form of a Pokémon.
@ -1383,6 +1407,17 @@ class PokemonFormPokeathlonStat(TableBase):
maximum_stat = Column(Integer, nullable=False, autoincrement=False,
info=dict(description=u'The maximum value for this stat for this Pokémon form.'))
class PokemonGameIndex(TableBase):
u"""The number of a Pokémon a game uses internally
"""
__tablename__ = 'pokemon_game_indices'
pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, autoincrement=False, nullable=False,
info=dict(description=u"Database ID of the Pokémon"))
generation_id = Column(Integer, ForeignKey('generations.id'), primary_key=True, autoincrement=False, nullable=False,
info=dict(description=u"Database ID of the generation"))
game_index = Column(Integer, nullable=False,
info=dict(description=u"Internal ID the generation's games use for the Pokémon"))
class PokemonHabitat(TableBase):
u"""The habitat of a Pokémon, as given in the FireRed/LeafGreen version Pokédex
"""
@ -1399,17 +1434,6 @@ create_translation_table('pokemon_habitat_names', PokemonHabitat, 'names',
info=dict(description="The name", format='plaintext', official=True)),
)
class PokemonGameIndex(TableBase):
u"""The number of a Pokémon a game uses internally
"""
__tablename__ = 'pokemon_game_indices'
pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, autoincrement=False, nullable=False,
info=dict(description=u"Database ID of the Pokémon"))
generation_id = Column(Integer, ForeignKey('generations.id'), primary_key=True, autoincrement=False, nullable=False,
info=dict(description=u"Database ID of the generation"))
game_index = Column(Integer, nullable=False,
info=dict(description=u"Internal ID the generation's games use for the Pokémon"))
class PokemonItem(TableBase):
u"""Record of an item a Pokémon can hold in the wild
"""
@ -1463,7 +1487,6 @@ create_translation_table('pokemon_move_method_prose', PokemonMoveMethod, 'prose'
info=dict(description=u"A detailed description of how the method works", format='plaintext')),
)
class PokemonShape(TableBase):
u"""The shape of a Pokémon's body, as used in generation IV Pokédexes.
"""
@ -1585,19 +1608,6 @@ create_translation_table('super_contest_effect_prose', SuperContestEffect, 'pros
info=dict(description=u"A description of the effect.", format='plaintext', official=True)),
)
class TypeEfficacy(TableBase):
u"""The damage multiplier used when a move of a particular type damages a
Pokémon of a particular other type.
"""
__tablename__ = 'type_efficacy'
damage_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False,
info=dict(description=u"The ID of the damaging type."))
target_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False,
info=dict(description=u"The ID of the defending Pokémon's type."))
damage_factor = Column(Integer, nullable=False,
info=dict(description=u"The multiplier, as a percentage of damage inflicted."))
class Type(TableBase):
u"""Any of the elemental types Pokémon and moves can have."""
__tablename__ = 'types'
@ -1617,6 +1627,35 @@ create_translation_table('type_names', Type, 'names',
info=dict(description="The name", format='plaintext', official=True)),
)
class TypeEfficacy(TableBase):
u"""The damage multiplier used when a move of a particular type damages a
Pokémon of a particular other type.
"""
__tablename__ = 'type_efficacy'
damage_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False,
info=dict(description=u"The ID of the damaging type."))
target_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False,
info=dict(description=u"The ID of the defending Pokémon's type."))
damage_factor = Column(Integer, nullable=False,
info=dict(description=u"The multiplier, as a percentage of damage inflicted."))
class Version(TableBase):
u"""An individual main-series Pokémon game."""
__tablename__ = 'versions'
__singlename__ = 'version'
id = Column(Integer, primary_key=True, nullable=False,
info=dict(description=u"A unique ID for this version."))
version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False,
info=dict(description=u"The ID of the version group this game belongs to."))
identifier = Column(Unicode(32), nullable=False,
info=dict(description=u'And identifier', format='identifier'))
create_translation_table('version_names', Version, 'names',
relation_lazy='joined',
name = Column(Unicode(32), nullable=False, index=True,
info=dict(description="The name", format='plaintext', official=True)),
)
class VersionGroup(TableBase):
u"""A group of versions, containing either two paired versions (such as Red
and Blue) or a single game (such as Yellow.)
@ -1637,24 +1676,6 @@ class VersionGroupRegion(TableBase):
region_id = Column(Integer, ForeignKey('regions.id'), primary_key=True, nullable=False,
info=dict(description=u"The ID of the region."))
class Version(TableBase):
u"""An individual main-series Pokémon game."""
__tablename__ = 'versions'
__singlename__ = 'version'
id = Column(Integer, primary_key=True, nullable=False,
info=dict(description=u"A unique ID for this version."))
version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False,
info=dict(description=u"The ID of the version group this game belongs to."))
identifier = Column(Unicode(32), nullable=False,
info=dict(description=u'And identifier', format='identifier'))
create_translation_table('version_names', Version, 'names',
relation_lazy='joined',
name = Column(Unicode(32), nullable=False, index=True,
info=dict(description="The name", format='plaintext', official=True)),
)
### Relations down here, to avoid ordering problems
Ability.changelog = relation(AbilityChangelog,
order_by=AbilityChangelog.changed_in_version_group_id.desc(),

View file

@ -23,9 +23,19 @@ def test_variable_names():
classname = table.__name__
if classname and varname[0].isupper():
assert varname == classname, '%s refers to %s' % (varname, classname)
for table in tables.table_classes:
for table in tables.mapped_classes:
assert getattr(tables, table.__name__) is table
def test_class_order():
"""The declarative classes should be defined in alphabetical order.
Except for Language which should be first.
"""
class_names = [table.__name__ for table in tables.mapped_classes]
def key(name):
return name != 'Language', name
print [(a,b) for (a,b) in zip(class_names, sorted(class_names, key=key)) if a!=b]
assert class_names == sorted(class_names, key=key)
def test_i18n_table_creation():
"""Creates and manipulates a magical i18n table, completely independent of
the existing schema and data. Makes sure that the expected behavior of the
@ -46,8 +56,9 @@ def test_i18n_table_creation():
__tablename__ = 'foos'
__singlename__ = 'foo'
id = Column(Integer, primary_key=True, nullable=False)
translation_classes = []
FooText = create_translation_table('foo_text', Foo,
FooText = create_translation_table('foo_text', Foo, 'texts',
language_class=Language,
name = Column(String(100)),
)
@ -79,14 +90,14 @@ def test_i18n_table_creation():
# Give our foo some names, as directly as possible
foo_text = FooText()
foo_text.object_id = foo.id
foo_text.language_id = lang_en.id
foo_text.foreign_id = foo.id
foo_text.local_language_id = lang_en.id
foo_text.name = 'english'
sess.add(foo_text)
foo_text = FooText()
foo_text.object_id = foo.id
foo_text.language_id = lang_jp.id
foo_text.foo_id = foo.id
foo_text.local_language_id = lang_jp.id
foo_text.name = 'nihongo'
sess.add(foo_text)
@ -116,7 +127,7 @@ def test_i18n_table_creation():
# THIS SHOULD WORK SOMEDAY
# .options(joinedload(Foo.name)) \
foo = sess.query(Foo) \
.options(joinedload(Foo.foo_text_local)) \
.options(joinedload(Foo.texts_local)) \
.one()
assert foo.name == 'english'
@ -127,7 +138,7 @@ def test_i18n_table_creation():
# THIS SHOULD ALSO WORK SOMEDAY
# .options(joinedload(Foo.name_map)) \
foo = sess.query(Foo) \
.options(joinedload(Foo.foo_text)) \
.options(joinedload(Foo.texts)) \
.one()
assert foo.name_map[lang_en] == 'english'
@ -152,15 +163,19 @@ def test_texts():
Mostly protects against copy/paste oversights and rebase hiccups.
If there's a reason to relax the tests, do it
"""
for table in sorted(tables.table_classes, key=lambda t: t.__name__):
if issubclass(table, tables.LanguageSpecific):
classes = []
for cls in tables.mapped_classes:
classes.append(cls)
classes += cls.translation_classes
for cls in classes:
if hasattr(cls, 'local_language') or hasattr(cls, 'language'):
good_formats = 'markdown plaintext gametext'.split()
assert_text = '%s is language-specific'
else:
good_formats = 'identifier latex'.split()
assert_text = '%s is not language-specific'
mapper = class_mapper(table)
for column in sorted(mapper.c, key=lambda c: c.name):
columns = sorted(cls.__table__.c, key=lambda c: c.name)
for column in columns:
format = column.info.get('format', None)
if format is not None:
if format not in good_formats:
@ -185,11 +200,8 @@ def test_identifiers_with_names():
...have either names or identifiers.
"""
for table in sorted(tables.table_classes, key=lambda t: t.__name__):
if issubclass(table, tables.Named):
assert issubclass(table, tables.OfficiallyNamed) or issubclass(table, tables.UnofficiallyNamed), table
for table in sorted(tables.mapped_classes, key=lambda t: t.__name__):
if hasattr(table, 'name'):
assert hasattr(table, 'identifier'), table
else:
assert not hasattr(table, 'identifier'), table
if not issubclass(table, tables.LanguageSpecific):
assert not hasattr(table, 'name'), table

View file

@ -16,16 +16,6 @@ class TestStrings(object):
tables.Pokemon.name == u"Marowak")
assert q.one().identifier == 'marowak'
def test_gt(self):
# Assuming that the identifiers are just lowercase names
q1 = self.connection.query(tables.Pokemon).filter(
tables.Pokemon.name > u"Xatu").order_by(
tables.Pokemon.id)
q2 = self.connection.query(tables.Pokemon).filter(
tables.Pokemon.identifier > u"xatu").order_by(
tables.Pokemon.id)
assert q1.all() == q2.all()
def test_languages(self):
q = self.connection.query(tables.Pokemon).filter(
tables.Pokemon.name == u"Mightyena")
@ -36,7 +26,9 @@ class TestStrings(object):
('roomaji', u'Guraena'),
('fr', u'Grahyèna'),
):
assert pkmn.names[lang] == name
language = self.connection.query(tables.Language).filter_by(
identifier=lang).one()
assert pkmn.name_map[language] == name
@raises(KeyError)
def test_bad_lang(self):
@ -50,12 +42,10 @@ class TestStrings(object):
identifier=u"jade-orb").one()
language = self.connection.query(tables.Language).filter_by(
identifier=u"de").one()
item.names['de'] = u"foo"
assert item.names['de'] == "foo"
assert item.names[language] == "foo"
item.names[language] = u"xyzzy"
assert item.names['de'] == "xyzzy"
assert item.names[language] == "xyzzy"
item.name_map[language] = u"foo"
assert item.name_map[language] == "foo"
item.name_map[language] = u"xyzzy"
assert item.name_map[language] == "xyzzy"
def test_mutating_default(self):
item = self.connection.query(tables.Item).filter_by(
@ -66,14 +56,12 @@ class TestStrings(object):
def test_string_mapping(self):
item = self.connection.query(tables.Item).filter_by(
identifier=u"jade-orb").one()
assert len(item.names) == len(item.texts)
for lang in item.texts:
assert item.names[lang] == item.texts[lang].name
assert item.names[lang] == item.names[lang.identifier]
assert lang in item.names
assert lang.identifier in item.names
assert "language that doesn't exist" not in item.names
assert tables.Language() not in item.names
assert len(item.name_map) == len(item.names)
for lang in item.names:
assert item.name_map[lang] == item.names[lang].name
assert lang in item.name_map
assert "language that doesn't exist" not in item.name_map
assert tables.Language() not in item.name_map
def test_new_language(self):
item = self.connection.query(tables.Item).filter_by(
@ -84,23 +72,16 @@ class TestStrings(object):
language.iso639 = language.iso3166 = u'--'
language.official = False
self.connection.add(language)
item.names[u'test'] = u"foo"
assert item.names[language] == "foo"
assert item.names['test'] == "foo"
assert 'de' in item.names
assert language in item.names
item.names[language] = u"xyzzy"
assert item.names[language] == "xyzzy"
assert item.names['test'] == "xyzzy"
@raises(NotImplementedError)
def test_delstring(self):
item = self.connection.query(tables.Item).filter_by(
identifier=u"jade-orb").one()
del item.names['en']
item.name_map[language] = u"foo"
assert item.name_map[language] == "foo"
assert language in item.name_map
item.name_map[language] = u"xyzzy"
assert item.name_map[language] == "xyzzy"
def test_markdown(self):
move = self.connection.query(tables.Move).filter_by(
identifier=u"thunderbolt").one()
language = self.connection.query(tables.Language).filter_by(
identifier=u"en").one()
assert '10%' in move.effect.as_text
assert '10%' in move.effects['en'].as_text
assert '10%' in move.effect_map[language].as_text