5 Columns have a info dictionary with these keys:
6 - description: The description of the column
7 - official: True if the values appear in games or official material; False if
8 they are fan-created or fan-written. This flag is currently only set for
10 - markup: The format of a text column. Can be one of:
11 - plaintext: Normal Unicode text (widely used in names)
12 - markdown: Veekun's Markdown flavor (generally used in effect descriptions)
13 - gametext: Transcription of in-game text that strives to be both
14 human-readable and represent the original text exactly.
15 - identifier: A fan-made identifier in the [-_a-z0-9]* format. Not intended
17 - latex: A formula in LaTeX syntax.
19 # XXX: Check if "gametext" is set correctly everywhere
23 from sqlalchemy
import Column
, ForeignKey
, MetaData
, PrimaryKeyConstraint
, Table
24 from sqlalchemy
.ext
.declarative
import (
25 declarative_base
, declared_attr
, DeclarativeMeta
,
27 from sqlalchemy
.ext
.associationproxy
import association_proxy
28 from sqlalchemy
.orm
import (
29 backref
, eagerload_all
, relation
, class_mapper
, synonym
, mapper
,
31 from sqlalchemy
.orm
.session
import Session
32 from sqlalchemy
.orm
.collections
import attribute_mapped_collection
33 from sqlalchemy
.sql
import and_
34 from sqlalchemy
.types
import *
35 from inspect
import isclass
37 from pokedex
.db
import markdown
39 # A list of all table classes will live in table_classes
42 class TableMetaclass(DeclarativeMeta
):
43 def __init__(cls
, name
, bases
, attrs
):
44 super(TableMetaclass
, cls
).__init__(name
, bases
, attrs
)
45 if hasattr(cls
, '__tablename__'):
46 table_classes
.append(cls
)
49 TableBase
= declarative_base(metadata
=metadata
, metaclass
=TableMetaclass
)
53 """Mixin for objects that have names"""
54 def __unicode__(self
):
56 return '<%s: %s>' %
(type(self
).__name__
, self
.identifier
)
57 except AttributeError:
58 return '<%s>' %
type(self
).__name__
61 return unicode(self
).encode('utf-8')
66 class OfficiallyNamed(Named
):
67 """Mixin for stuff with official names"""
69 class UnofficiallyNamed(Named
):
70 """Mixin for stuff with unofficial names"""
72 class LanguageSpecific(object):
73 """Mixin for prose and text tables"""
76 return Column(Integer
, ForeignKey('languages.id'), primary_key
=True, nullable
=False,
77 info
=dict(description
="The language"))
79 class LanguageSpecificColumn(object):
80 """A column that will not appear in the table it's defined in, but in a related one"""
82 def __init__(self
, *args
, **kwargs
):
84 self
.plural
= kwargs
.pop('plural')
86 self
.order
= self
._ordering
[0]
87 self
._ordering
[0] += 1
89 def makeSAColumn(self
):
90 return Column(*self
.args
, **self
.kwargs
)
92 class ProseColumn(LanguageSpecificColumn
):
93 """A column that will appear in the corresponding _prose table"""
95 class TextColumn(LanguageSpecificColumn
):
96 """A column that will appear in the corresponding _text table"""
101 class Ability(TableBase
, OfficiallyNamed
):
102 u
"""An ability a Pokémon can have, such as Static or Pressure.
104 __tablename__
= 'abilities'
105 __singlename__
= 'ability'
106 id = Column(Integer
, primary_key
=True, nullable
=False,
107 info
=dict(description
="This ability's unique ID; matches the games' internal ID"))
108 identifier
= Column(Unicode(24), nullable
=False,
109 info
=dict(description
="An identifier", format
='identifier'))
110 generation_id
= Column(Integer
, ForeignKey('generations.id'), nullable
=False,
111 info
=dict(description
="The ID of the generation this ability was introduced in", detail
=True))
112 effect
= ProseColumn(markdown
.MarkdownColumn(5120), plural
='effects', nullable
=False,
113 info
=dict(description
="A detailed description of this ability's effect", format
='markdown'))
114 short_effect
= ProseColumn(markdown
.MarkdownColumn(255), plural
='short_effects', nullable
=False,
115 info
=dict(description
="A short summary of this ability's effect", format
='markdown'))
117 class AbilityChangelog(TableBase
):
118 """History of changes to abilities across main game versions."""
119 __tablename__
= 'ability_changelog'
120 __singlename__
= 'ability_changelog'
121 id = Column(Integer
, primary_key
=True, nullable
=False,
122 info
=dict(description
="This change's unique ID"))
123 ability_id
= Column(Integer
, ForeignKey('abilities.id'), nullable
=False,
124 info
=dict(description
="The ID of the ability that changed"))
125 changed_in_version_group_id
= Column(Integer
, ForeignKey('version_groups.id'), nullable
=False,
126 info
=dict(description
="The ID of the version group in which the ability changed"))
127 effect
= ProseColumn(markdown
.MarkdownColumn(255), plural
='effects', nullable
=False,
128 info
=dict(description
="A description of the old behavior", format
='markdown'))
130 class AbilityFlavorText(TableBase
, LanguageSpecific
):
131 u
"""In-game flavor text of an ability
133 __tablename__
= 'ability_flavor_text'
134 ability_id
= Column(Integer
, ForeignKey('abilities.id'), primary_key
=True, nullable
=False, autoincrement
=False,
135 info
=dict(description
="The ID of the ability"))
136 version_group_id
= Column(Integer
, ForeignKey('version_groups.id'), primary_key
=True, nullable
=False, autoincrement
=False,
137 info
=dict(description
="The ID of the version group this flavor text is taken from"))
138 flavor_text
= Column(Unicode(64), nullable
=False,
139 info
=dict(description
="The actual flavor text", official
=True, format
='gametext'))
141 class Berry(TableBase
):
142 u
"""A Berry, consumable item that grows on trees
144 For data common to all items, such as the name, see the corresponding item entry.
146 __tablename__
= 'berries'
147 id = Column(Integer
, primary_key
=True, nullable
=False,
148 info
=dict(description
="This Berry's in-game number"))
149 item_id
= Column(Integer
, ForeignKey('items.id'), nullable
=False,
150 info
=dict(description
="The ID of the item that represents this Berry"))
151 firmness_id
= Column(Integer
, ForeignKey('berry_firmness.id'), nullable
=False,
152 info
=dict(description
="The ID of this Berry's firmness category"))
153 natural_gift_power
= Column(Integer
, nullable
=True,
154 info
=dict(description
="Natural Gift's power when used with this Berry"))
155 natural_gift_type_id
= Column(Integer
, ForeignKey('types.id'), nullable
=True,
156 info
=dict(description
="The ID of the Type that Natural Gift has when used with this Berry"))
157 size
= Column(Integer
, nullable
=False,
158 info
=dict(description
=u
"The size of this Berry, in millimeters"))
159 max_harvest
= Column(Integer
, nullable
=False,
160 info
=dict(description
="The maximum number of these berries that can grow on one tree in Generation IV"))
161 growth_time
= Column(Integer
, nullable
=False,
162 info
=dict(description
="Time it takes the tree to grow one stage, in hours. Berry trees go through four of these growth stages before they can be picked."))
163 soil_dryness
= Column(Integer
, nullable
=False,
164 info
=dict(description
="The speed at which this Berry dries out the soil as it grows. A higher rate means the soil dries more quickly."))
165 smoothness
= Column(Integer
, nullable
=False,
166 info
=dict(description
="The smoothness of this Berry, used in making Pokéblocks or Poffins"))
168 class BerryFirmness(TableBase
, OfficiallyNamed
):
169 u
"""A Berry firmness, such as "hard" or "very soft".
171 __tablename__
= 'berry_firmness'
172 __singlename__
= 'berry_firmness'
173 id = Column(Integer
, primary_key
=True, nullable
=False,
174 info
=dict(description
="A unique ID for this firmness"))
175 identifier
= Column(Unicode(10), nullable
=False,
176 info
=dict(description
="An identifier", format
='identifier'))
178 class BerryFlavor(TableBase
):
179 u
"""A Berry flavor level.
181 __tablename__
= 'berry_flavors'
182 berry_id
= Column(Integer
, ForeignKey('berries.id'), primary_key
=True, nullable
=False, autoincrement
=False,
183 info
=dict(description
="The ID of the berry"))
184 contest_type_id
= Column(Integer
, ForeignKey('contest_types.id'), primary_key
=True, nullable
=False, autoincrement
=False,
185 info
=dict(description
="The ID of the flavor"))
186 flavor
= Column(Integer
, nullable
=False,
187 info
=dict(description
="The level of the flavor in the berry"))
189 class ContestCombo(TableBase
):
190 u
"""Combo of two moves in a Contest.
192 __tablename__
= 'contest_combos'
193 first_move_id
= Column(Integer
, ForeignKey('moves.id'), primary_key
=True, nullable
=False, autoincrement
=False,
194 info
=dict(description
="The ID of the first move in the combo"))
195 second_move_id
= Column(Integer
, ForeignKey('moves.id'), primary_key
=True, nullable
=False, autoincrement
=False,
196 info
=dict(description
="The ID of the second and final move in the combo"))
198 class ContestEffect(TableBase
):
199 u
"""Effect of a move when used in a Contest.
201 __tablename__
= 'contest_effects'
202 __singlename__
= 'contest_effect'
203 id = Column(Integer
, primary_key
=True, nullable
=False,
204 info
=dict(description
="A unique ID for this effect"))
205 appeal
= Column(SmallInteger
, nullable
=False,
206 info
=dict(description
="The base number of hearts the user of this move gets"))
207 jam
= Column(SmallInteger
, nullable
=False,
208 info
=dict(description
="The base number of hearts the user's opponent loses"))
209 flavor_text
= ProseColumn(Unicode(64), plural
='flavor_texts', nullable
=False,
210 info
=dict(description
="The in-game description of this effect", official
=True, format
='gametext'))
211 effect
= ProseColumn(Unicode(255), plural
='effects', nullable
=False,
212 info
=dict(description
="A detailed description of the effect", format
='plaintext'))
214 class ContestType(TableBase
, OfficiallyNamed
):
215 u
"""A Contest type, such as "cool" or "smart", and their associated Berry flavors and Pokéblock colors.
217 __tablename__
= 'contest_types'
218 __singlename__
= 'contest_type'
219 id = Column(Integer
, primary_key
=True, nullable
=False,
220 info
=dict(description
="A unique ID for this Contest type"))
221 identifier
= Column(Unicode(6), nullable
=False,
222 info
=dict(description
="An identifier", format
='identifier'))
223 flavor
= TextColumn(Unicode(6), nullable
=False, plural
='flavors',
224 info
=dict(description
="The name of the corresponding Berry flavor", official
=True, format
='plaintext'))
225 color
= TextColumn(Unicode(6), nullable
=False, plural
='colors',
226 info
=dict(description
=u
"The name of the corresponding Pokéblock color", official
=True, format
='plaintext'))
228 class EggGroup(TableBase
, UnofficiallyNamed
):
229 u
"""An Egg group. Usually, two Pokémon can breed if they share an Egg Group.
231 (exceptions are the Ditto and No Eggs groups)
233 __tablename__
= 'egg_groups'
234 __singlename__
= 'egg_group'
235 id = Column(Integer
, primary_key
=True, nullable
=False,
236 info
=dict(description
="A unique ID for this group"))
237 identifier
= Column(Unicode(16), nullable
=False,
238 info
=dict(description
=u
"An identifier.", format
='identifier'))
240 class Encounter(TableBase
):
241 u
"""Encounters with wild Pokémon.
245 Within a given area in a given game, encounters are differentiated by the
246 "slot" they are in and the state of the game world.
248 What the player is doing to get an encounter, such as surfing or walking
249 through tall grass, is called terrain. Each terrain has its own set of
252 Within a terrain, slots are defined primarily by rarity. Each slot can
253 also be affected by world conditions; for example, the 20% slot for walking
254 in tall grass is affected by whether a swarm is in effect in that area.
255 "Is there a swarm?" is a condition; "there is a swarm" and "there is not a
256 swarm" are the possible values of this condition.
258 A slot (20% walking in grass) and any appropriate world conditions (no
259 swarm) are thus enough to define a specific encounter.
261 Well, okay, almost: each slot actually appears twice.
264 __tablename__
= 'encounters'
265 id = Column(Integer
, primary_key
=True, nullable
=False,
266 info
=dict(description
="A unique ID for this encounter"))
267 version_id
= Column(Integer
, ForeignKey('versions.id'), nullable
=False, autoincrement
=False,
268 info
=dict(description
="The ID of the version this applies to"))
269 location_area_id
= Column(Integer
, ForeignKey('location_areas.id'), nullable
=False, autoincrement
=False,
270 info
=dict(description
="The ID of the location of this encounter"))
271 encounter_slot_id
= Column(Integer
, ForeignKey('encounter_slots.id'), nullable
=False, autoincrement
=False,
272 info
=dict(description
="The ID of the encounter slot, which determines terrain and rarity"))
273 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), nullable
=False, autoincrement
=False,
274 info
=dict(description
=u
"The ID of the encountered Pokémon"))
275 min_level
= Column(Integer
, nullable
=False, autoincrement
=False,
276 info
=dict(description
=u
"The minimum level of the encountered Pokémon"))
277 max_level
= Column(Integer
, nullable
=False, autoincrement
=False,
278 info
=dict(description
=u
"The maxmum level of the encountered Pokémon"))
280 class EncounterCondition(TableBase
, UnofficiallyNamed
):
281 u
"""A conditions in the game world that affects Pokémon encounters, such as time of day.
284 __tablename__
= 'encounter_conditions'
285 __singlename__
= 'encounter_condition'
286 id = Column(Integer
, primary_key
=True, nullable
=False,
287 info
=dict(description
="A unique ID for this condition"))
288 identifier
= Column(Unicode(64), nullable
=False,
289 info
=dict(description
="An identifier", format
='identifier'))
291 class EncounterConditionValue(TableBase
, UnofficiallyNamed
):
292 u
"""A possible state for a condition; for example, the state of 'swarm' could be 'swarm' or 'no swarm'.
295 __tablename__
= 'encounter_condition_values'
296 __singlename__
= 'encounter_condition_value'
297 id = Column(Integer
, primary_key
=True, nullable
=False,
298 info
=dict(description
="A numeric ID"))
299 encounter_condition_id
= Column(Integer
, ForeignKey('encounter_conditions.id'), primary_key
=False, nullable
=False, autoincrement
=False,
300 info
=dict(description
="The ID of the encounter condition this is a value of"))
301 identifier
= Column(Unicode(64), nullable
=False,
302 info
=dict(description
="An identifier", format
='identifier'))
303 is_default
= Column(Boolean
, nullable
=False,
304 info
=dict(description
='Set if this value is the default state for the condition'))
306 class EncounterConditionValueMap(TableBase
):
307 u
"""Maps encounters to the specific conditions under which they occur.
309 __tablename__
= 'encounter_condition_value_map'
310 encounter_id
= Column(Integer
, ForeignKey('encounters.id'), primary_key
=True, nullable
=False, autoincrement
=False,
311 info
=dict(description
="The ID of the encounter"))
312 encounter_condition_value_id
= Column(Integer
, ForeignKey('encounter_condition_values.id'), primary_key
=True, nullable
=False, autoincrement
=False,
313 info
=dict(description
="The ID of the encounter condition value"))
315 class EncounterTerrain(TableBase
, UnofficiallyNamed
):
316 u
"""A way the player can enter a wild encounter, e.g., surfing, fishing, or walking through tall grass.
319 __tablename__
= 'encounter_terrain'
320 __singlename__
= __tablename__
321 id = Column(Integer
, primary_key
=True, nullable
=False,
322 info
=dict(description
="A unique ID for the terrain"))
323 identifier
= Column(Unicode(64), nullable
=False,
324 info
=dict(description
="An identifier", format
='identifier'))
326 class EncounterSlot(TableBase
):
327 u
"""An abstract "slot" within a terrain, associated with both some set of conditions and a rarity.
329 Note that there are two encounters per slot, so the rarities will only add
333 __tablename__
= 'encounter_slots'
334 id = Column(Integer
, primary_key
=True, nullable
=False,
335 info
=dict(description
="A unique ID for this slot"))
336 version_group_id
= Column(Integer
, ForeignKey('version_groups.id'), nullable
=False, autoincrement
=False,
337 info
=dict(description
="The ID of the version group this slot is in"))
338 encounter_terrain_id
= Column(Integer
, ForeignKey('encounter_terrain.id'), primary_key
=False, nullable
=False, autoincrement
=False,
339 info
=dict(description
="The ID of the terrain"))
340 slot
= Column(Integer
, nullable
=True,
341 info
=dict(description
="This slot's order for the location and terrain"))
342 rarity
= Column(Integer
, nullable
=False,
343 info
=dict(description
="The chance of the encounter as a percentage"))
345 class EvolutionChain(TableBase
):
346 u
"""A family of Pokémon that are linked by evolution
348 __tablename__
= 'evolution_chains'
349 id = Column(Integer
, primary_key
=True, nullable
=False,
350 info
=dict(description
="A numeric ID"))
351 growth_rate_id
= Column(Integer
, ForeignKey('growth_rates.id'), nullable
=False,
352 info
=dict(description
="ID of the growth rate for this family"))
353 baby_trigger_item_id
= Column(Integer
, ForeignKey('items.id'), nullable
=True,
354 info
=dict(description
="Item that a parent must hold while breeding to produce a baby"))
356 class EvolutionTrigger(TableBase
, UnofficiallyNamed
):
357 u
"""An evolution type, such as "level" or "trade".
359 __tablename__
= 'evolution_triggers'
360 __singlename__
= 'evolution_trigger'
361 id = Column(Integer
, primary_key
=True, nullable
=False,
362 info
=dict(description
="A numeric ID"))
363 identifier
= Column(Unicode(16), nullable
=False,
364 info
=dict(description
="An identifier", format
='identifier'))
366 class Experience(TableBase
):
367 u
"""EXP needed for a certain level with a certain growth rate
369 __tablename__
= 'experience'
370 growth_rate_id
= Column(Integer
, ForeignKey('growth_rates.id'), primary_key
=True, nullable
=False,
371 info
=dict(description
="ID of the growth rate"))
372 level
= Column(Integer
, primary_key
=True, nullable
=False, autoincrement
=False,
373 info
=dict(description
="The level"))
374 experience
= Column(Integer
, nullable
=False,
375 info
=dict(description
="The number of EXP points needed to get to that level"))
377 class Generation(TableBase
, OfficiallyNamed
):
378 u
"""A Generation of the Pokémon franchise
380 __tablename__
= 'generations'
381 __singlename__
= 'generation'
382 id = Column(Integer
, primary_key
=True, nullable
=False,
383 info
=dict(description
="A numeric ID"))
384 main_region_id
= Column(Integer
, ForeignKey('regions.id'),
385 info
=dict(description
="ID of the region this generation's main games take place in"))
386 canonical_pokedex_id
= Column(Integer
, ForeignKey('pokedexes.id'),
387 info
=dict(description
=u
"ID of the Pokédex this generation's main games use by default"))
388 identifier
= Column(Unicode(16), nullable
=False,
389 info
=dict(description
=u
'An identifier', format
='identifier'))
391 class GrowthRate(TableBase
, UnofficiallyNamed
):
392 u
"""Growth rate of a Pokémon, i.e. the EXP → level function.
394 __tablename__
= 'growth_rates'
395 __singlename__
= 'growth_rate'
396 id = Column(Integer
, primary_key
=True, nullable
=False,
397 info
=dict(description
="A numeric ID"))
398 identifier
= Column(Unicode(20), nullable
=False,
399 info
=dict(description
="An identifier", format
='identifier'))
400 formula
= Column(Unicode(500), nullable
=False,
401 info
=dict(description
="The formula", format
='latex'))
403 class Item(TableBase
, OfficiallyNamed
):
404 u
"""An Item from the games, like "Poké Ball" or "Bicycle".
406 __tablename__
= 'items'
407 __singlename__
= 'item'
408 id = Column(Integer
, primary_key
=True, nullable
=False,
409 info
=dict(description
="A numeric ID"))
410 identifier
= Column(Unicode(20), nullable
=False,
411 info
=dict(description
="An identifier", format
='identifier'))
412 category_id
= Column(Integer
, ForeignKey('item_categories.id'), nullable
=False,
413 info
=dict(description
="ID of a category this item belongs to"))
414 cost
= Column(Integer
, nullable
=False,
415 info
=dict(description
=u
"Cost of the item when bought. Items sell for half this price."))
416 fling_power
= Column(Integer
, nullable
=True,
417 info
=dict(description
=u
"Power of the move Fling when used with this item."))
418 fling_effect_id
= Column(Integer
, ForeignKey('item_fling_effects.id'), nullable
=True,
419 info
=dict(description
=u
"ID of the fling-effect of the move Fling when used with this item. Note that these are different from move effects."))
420 short_effect
= ProseColumn(Unicode(256), plural
='short_effects', nullable
=False,
421 info
=dict(description
="A short summary of the effect", format
='plaintext'))
422 effect
= ProseColumn(markdown
.MarkdownColumn(5120), plural
='effects', nullable
=False,
423 info
=dict(description
=u
"Detailed description of the item's effect.", format
='markdown'))
426 def appears_underground(self
):
427 u
"""True if the item appears underground, as specified by the appropriate flag
429 return any(flag
.identifier
== u
'underground' for flag
in self
.flags
)
431 class ItemCategory(TableBase
, UnofficiallyNamed
):
434 # XXX: This is fanon, right?
435 __tablename__
= 'item_categories'
436 __singlename__
= 'item_category'
437 id = Column(Integer
, primary_key
=True, nullable
=False,
438 info
=dict(description
="A numeric ID"))
439 pocket_id
= Column(Integer
, ForeignKey('item_pockets.id'), nullable
=False,
440 info
=dict(description
="ID of the pocket these items go to"))
441 identifier
= Column(Unicode(16), nullable
=False,
442 info
=dict(description
="An identifier", format
='identifier'))
444 class ItemFlag(TableBase
, UnofficiallyNamed
):
445 u
"""An item attribute such as "consumable" or "holdable".
447 __tablename__
= 'item_flags'
448 __singlename__
= 'item_flag'
449 id = Column(Integer
, primary_key
=True, nullable
=False,
450 info
=dict(description
="A numeric ID"))
451 identifier
= Column(Unicode(24), nullable
=False,
452 info
=dict(description
="Identifier of the flag", format
='identifier'))
453 description
= ProseColumn(Unicode(64), plural
='descriptions', nullable
=False,
454 info
=dict(description
="Short description of the flag", format
='plaintext'))
456 class ItemFlagMap(TableBase
):
457 u
"""Maps an item flag to its item.
459 __tablename__
= 'item_flag_map'
460 item_id
= Column(Integer
, ForeignKey('items.id'), primary_key
=True, autoincrement
=False, nullable
=False,
461 info
=dict(description
="The ID of the item"))
462 item_flag_id
= Column(Integer
, ForeignKey('item_flags.id'), primary_key
=True, autoincrement
=False, nullable
=False,
463 info
=dict(description
="The ID of the item flag"))
465 class ItemFlavorText(TableBase
, LanguageSpecific
):
466 u
"""An in-game description of an item
468 __tablename__
= 'item_flavor_text'
469 __singlename__
= 'item_flavor_text'
470 item_id
= Column(Integer
, ForeignKey('items.id'), primary_key
=True, autoincrement
=False, nullable
=False,
471 info
=dict(description
="The ID of the item"))
472 version_group_id
= Column(Integer
, ForeignKey('version_groups.id'), primary_key
=True, autoincrement
=False, nullable
=False,
473 info
=dict(description
="ID of the version group that sports this text"))
474 flavor_text
= Column(Unicode(255), nullable
=False,
475 info
=dict(description
="The flavor text itself", official
=True, format
='gametext'))
477 class ItemFlingEffect(TableBase
):
478 u
"""An effect of the move Fling when used with a specific item
480 __tablename__
= 'item_fling_effects'
481 __singlename__
= 'item_fling_effect'
482 id = Column(Integer
, primary_key
=True, nullable
=False,
483 info
=dict(description
="A numeric ID"))
484 effect
= ProseColumn(Unicode(255), plural
='effects', nullable
=False,
485 info
=dict(description
="Description of the effect", format
='plaintext'))
487 class ItemInternalID(TableBase
):
488 u
"""The internal ID number a game uses for an item
490 __tablename__
= 'item_internal_ids'
491 item_id
= Column(Integer
, ForeignKey('items.id'), primary_key
=True, autoincrement
=False, nullable
=False,
492 info
=dict(description
="The database ID of the item"))
493 generation_id
= Column(Integer
, ForeignKey('generations.id'), primary_key
=True, autoincrement
=False, nullable
=False,
494 info
=dict(description
="ID of the generation of games"))
495 internal_id
= Column(Integer
, nullable
=False,
496 info
=dict(description
="Internal ID of the item in the generation"))
498 class ItemPocket(TableBase
, OfficiallyNamed
):
499 u
"""A pocket that categorizes items
501 __tablename__
= 'item_pockets'
502 __singlename__
= 'item_pocket'
503 id = Column(Integer
, primary_key
=True, nullable
=False,
504 info
=dict(description
="A numeric ID"))
505 identifier
= Column(Unicode(16), nullable
=False,
506 info
=dict(description
="An identifier of this pocket", format
='identifier'))
508 class Language(TableBase
, OfficiallyNamed
):
509 u
"""A language the Pokémon games have been transleted into
511 __tablename__
= 'languages'
512 __singlename__
= 'language'
513 id = Column(Integer
, primary_key
=True, nullable
=False,
514 info
=dict(description
="A numeric ID"))
515 iso639
= Column(Unicode(2), nullable
=False,
516 info
=dict(description
="The two-letter code of the country where this language is spoken. Note that it is not unique.", format
='identifier'))
517 iso3166
= Column(Unicode(2), nullable
=False,
518 info
=dict(description
="The two-letter code of the language. Note that it is not unique.", format
='identifier'))
519 identifier
= Column(Unicode(16), nullable
=False,
520 info
=dict(description
="An identifier", format
='identifier'))
521 official
= Column(Boolean
, nullable
=False, index
=True,
522 info
=dict(description
=u
"True iff games are produced in the language."))
523 order
= Column(Integer
, nullable
=True,
524 info
=dict(description
=u
"Order for sorting in foreign name lists."))
526 # Languages compare equal to its identifier, so a dictionary of
527 # translations, with a Language as the key, can be indexed by the identifier
528 def __eq__(self
, other
):
532 self
.identifier
== other
or
533 self
.identifier
== other
.identifier
535 except AttributeError:
536 return NotImplemented
538 def __ne__(self
, other
):
539 return not (self
== other
)
542 return hash(self
.identifier
)
544 class Location(TableBase
, OfficiallyNamed
):
545 u
"""A place in the Pokémon world
547 __tablename__
= 'locations'
548 __singlename__
= 'location'
549 id = Column(Integer
, primary_key
=True, nullable
=False,
550 info
=dict(description
="A numeric ID"))
551 region_id
= Column(Integer
, ForeignKey('regions.id'),
552 info
=dict(description
="ID of the region this location is in"))
553 identifier
= Column(Unicode(64), nullable
=False,
554 info
=dict(description
="An identifier", format
='identifier'))
556 class LocationArea(TableBase
, UnofficiallyNamed
):
557 u
"""A sub-area of a location
559 __tablename__
= 'location_areas'
560 __singlename__
= 'location_area'
561 id = Column(Integer
, primary_key
=True, nullable
=False,
562 info
=dict(description
="A numeric ID"))
563 location_id
= Column(Integer
, ForeignKey('locations.id'), nullable
=False,
564 info
=dict(description
="ID of the location this area is part of"))
565 internal_id
= Column(Integer
, nullable
=False,
566 info
=dict(description
="ID the games ude for this area"))
567 identifier
= Column(Unicode(64), nullable
=True,
568 info
=dict(description
="An identifier", format
='identifier'))
570 class LocationAreaEncounterRate(TableBase
):
571 # XXX: What's this exactly? Someone add the docstring & revise the descriptions
572 __tablename__
= 'location_area_encounter_rates'
573 location_area_id
= Column(Integer
, ForeignKey('location_areas.id'), primary_key
=True, nullable
=False, autoincrement
=False,
574 info
=dict(description
="ID of the area"))
575 encounter_terrain_id
= Column(Integer
, ForeignKey('encounter_terrain.id'), primary_key
=True, nullable
=False, autoincrement
=False,
576 info
=dict(description
="ID of the terrain"))
577 version_id
= Column(Integer
, ForeignKey('versions.id'), primary_key
=True, autoincrement
=False,
578 info
=dict(description
="ID of the version"))
579 rate
= Column(Integer
, nullable
=True,
580 info
=dict(description
="The encounter rate")) # units?
582 class LocationInternalID(TableBase
):
583 u
"""IDs the games use internally for locations
585 __tablename__
= 'location_internal_ids'
586 location_id
= Column(Integer
, ForeignKey('locations.id'), nullable
=False, primary_key
=True,
587 info
=dict(description
="Database ID of the locaion"))
588 generation_id
= Column(Integer
, ForeignKey('generations.id'), nullable
=False, primary_key
=True,
589 info
=dict(description
="ID of the generation this entry to"))
590 internal_id
= Column(Integer
, nullable
=False,
591 info
=dict(description
="Internal game ID of the location"))
593 class Machine(TableBase
):
594 u
"""A TM or HM; numbered item that can teach a move to a Pokémon
596 __tablename__
= 'machines'
597 machine_number
= Column(Integer
, primary_key
=True, nullable
=False, autoincrement
=False,
598 info
=dict(description
="Number of the machine for TMs, or 100 + the munber for HMs"))
599 version_group_id
= Column(Integer
, ForeignKey('version_groups.id'), primary_key
=True, nullable
=False, autoincrement
=False,
600 info
=dict(description
="Versions this entry applies to"))
601 item_id
= Column(Integer
, ForeignKey('items.id'), nullable
=False,
602 info
=dict(description
="ID of the corresponding Item"))
603 move_id
= Column(Integer
, ForeignKey('moves.id'), nullable
=False,
604 info
=dict(description
="ID of the taught move"))
608 u
"""True if this machine is a HM, False if it's a TM
610 return self
.machine_number
>= 100
612 class MoveBattleStyle(TableBase
, UnofficiallyNamed
):
613 u
"""A battle style of a move""" # XXX: Explain better
614 __tablename__
= 'move_battle_styles'
615 __singlename__
= 'move_battle_style'
616 id = Column(Integer
, primary_key
=True, nullable
=False,
617 info
=dict(description
="A numeric ID"))
618 identifier
= Column(Unicode(8), nullable
=False,
619 info
=dict(description
="An identifier", format
='identifier'))
621 class MoveEffectCategory(TableBase
, UnofficiallyNamed
):
622 u
"""Category of a move effect
624 __tablename__
= 'move_effect_categories'
625 __singlename__
= 'move_effect_category'
626 id = Column(Integer
, primary_key
=True, nullable
=False,
627 info
=dict(description
="A numeric ID"))
628 identifier
= Column(Unicode(64), nullable
=False,
629 info
=dict(description
="An identifier", format
='identifier'))
630 can_affect_user
= Column(Boolean
, nullable
=False,
631 info
=dict(description
="Set if the user can be affected"))
633 class MoveEffectCategoryMap(TableBase
):
634 u
"""Maps a move effect category to a move effect
636 __tablename__
= 'move_effect_category_map'
637 move_effect_id
= Column(Integer
, ForeignKey('move_effects.id'), primary_key
=True, nullable
=False,
638 info
=dict(description
="ID of the move effect"))
639 move_effect_category_id
= Column(Integer
, ForeignKey('move_effect_categories.id'), primary_key
=True, nullable
=False,
640 info
=dict(description
="ID of the category"))
641 affects_user
= Column(Boolean
, primary_key
=True, nullable
=False,
642 info
=dict(description
="Set if the user is affected"))
644 class MoveDamageClass(TableBase
, UnofficiallyNamed
):
645 u
"""Any of the damage classes moves can have, i.e. physical, special, or non-damaging.
647 __tablename__
= 'move_damage_classes'
648 __singlename__
= 'move_damage_class'
649 id = Column(Integer
, primary_key
=True, nullable
=False,
650 info
=dict(description
="A numeric ID"))
651 identifier
= Column(Unicode(16), nullable
=False,
652 info
=dict(description
="An identifier", format
='identifier'))
653 description
= ProseColumn(Unicode(64), plural
='descriptions', nullable
=False,
654 info
=dict(description
="A description of the class", format
='plaintext'))
656 class MoveEffect(TableBase
):
657 u
"""An effect of a move
659 __tablename__
= 'move_effects'
660 __singlename__
= 'move_effect'
661 id = Column(Integer
, primary_key
=True, nullable
=False,
662 info
=dict(description
="A numeric ID"))
663 short_effect
= ProseColumn(Unicode(256), plural
='short_effects', nullable
=False,
664 info
=dict(description
="A short summary of the effect", format
='plaintext'))
665 effect
= ProseColumn(Unicode(5120), plural
='effects', nullable
=False,
666 info
=dict(description
="A detailed description of the effect", format
='plaintext'))
668 class MoveEffectChangelog(TableBase
):
669 """History of changes to move effects across main game versions."""
670 __tablename__
= 'move_effect_changelog'
671 __singlename__
= 'move_effect_changelog'
672 id = Column(Integer
, primary_key
=True, nullable
=False,
673 info
=dict(description
="A numeric ID"))
674 effect_id
= Column(Integer
, ForeignKey('move_effects.id'), primary_key
=True, nullable
=False,
675 info
=dict(description
="The ID of the effect that changed"))
676 changed_in_version_group_id
= Column(Integer
, ForeignKey('version_groups.id'), primary_key
=True, nullable
=False,
677 info
=dict(description
="The ID of the version group in which the effect changed"))
678 effect
= ProseColumn(markdown
.MarkdownColumn(512), plural
='effects', nullable
=False,
679 info
=dict(description
="A description of the old behavior", format
='markdown'))
681 class MoveFlag(TableBase
):
682 u
"""Maps a move flag to a move
684 # XXX: Other flags have a ___Flag class for the actual flag and ___FlagMap for the map,
685 # these, somewhat confusingly, have MoveFlagType and MoveFlag
686 __tablename__
= 'move_flags'
687 move_id
= Column(Integer
, ForeignKey('moves.id'), primary_key
=True, nullable
=False, autoincrement
=False,
688 info
=dict(description
="ID of the move"))
689 move_flag_type_id
= Column(Integer
, ForeignKey('move_flag_types.id'), primary_key
=True, nullable
=False, autoincrement
=False,
690 info
=dict(description
="ID of the flag"))
692 class MoveFlagType(TableBase
, UnofficiallyNamed
):
693 u
"""A Move attribute such as "snatchable" or "contact".
695 __tablename__
= 'move_flag_types'
696 __singlename__
= 'move_flag_type'
697 id = Column(Integer
, primary_key
=True, nullable
=False,
698 info
=dict(description
="A numeric ID"))
699 identifier
= Column(Unicode(32), nullable
=False,
700 info
=dict(description
="A short identifier for the flag", format
='identifier'))
701 description
= ProseColumn(markdown
.MarkdownColumn(128), plural
='descriptions', nullable
=False,
702 info
=dict(description
="A short description of the flag", format
='markdown'))
704 class MoveFlavorText(TableBase
, LanguageSpecific
):
705 u
"""In-game description of a move
707 __tablename__
= 'move_flavor_text'
708 move_id
= Column(Integer
, ForeignKey('moves.id'), primary_key
=True, nullable
=False, autoincrement
=False,
709 info
=dict(description
="ID of the move"))
710 version_group_id
= Column(Integer
, ForeignKey('version_groups.id'), primary_key
=True, nullable
=False, autoincrement
=False,
711 info
=dict(description
="ID of the version group this text appears in"))
712 flavor_text
= Column(Unicode(255), nullable
=False,
713 info
=dict(description
="The flavor text", official
=True, format
='gametext'))
715 class MoveMeta(TableBase
):
716 u
"""Metadata for move effects, sorta-kinda ripped straight from the game"""
717 __tablename__
= 'move_meta'
718 move_id
= Column(Integer
, ForeignKey('moves.id'), primary_key
=True, nullable
=False, autoincrement
=False,
719 info
=dict(description
="A numeric ID"))
720 meta_category_id
= Column(Integer
, ForeignKey('move_meta_categories.id'), nullable
=False,
721 info
=dict(description
="ID of the move category"))
722 meta_ailment_id
= Column(Integer
, ForeignKey('move_meta_ailments.id'), nullable
=False,
723 info
=dict(description
="ID of the caused ailment"))
724 min_hits
= Column(Integer
, nullable
=True, index
=True,
725 info
=dict(description
="Minimum number of hits per use"))
726 max_hits
= Column(Integer
, nullable
=True, index
=True,
727 info
=dict(description
="Maximum number of hits per use"))
728 min_turns
= Column(Integer
, nullable
=True, index
=True,
729 info
=dict(description
="Minimum number of turns the user is forced to use the move"))
730 max_turns
= Column(Integer
, nullable
=True, index
=True,
731 info
=dict(description
="Maximum number of turns the user is forced to use the move"))
732 recoil
= Column(Integer
, nullable
=False, index
=True,
733 info
=dict(description
="Recoil damage, in percent of damage done"))
734 healing
= Column(Integer
, nullable
=False, index
=True,
735 info
=dict(description
="Healing, in percent of user's max HP"))
736 crit_rate
= Column(Integer
, nullable
=False, index
=True,
737 info
=dict(description
="Critical hit rate bonus"))
738 ailment_chance
= Column(Integer
, nullable
=False, index
=True,
739 info
=dict(description
="Chance to cause an ailment, in percent"))
740 flinch_chance
= Column(Integer
, nullable
=False, index
=True,
741 info
=dict(description
="Chance to cause flinching, in percent"))
742 stat_chance
= Column(Integer
, nullable
=False, index
=True,
743 info
=dict(description
="Chance to cause a stat change, in percent"))
745 class MoveMetaAilment(TableBase
, OfficiallyNamed
):
746 u
"""Common status ailments moves can inflict on a single Pokémon, including
747 major ailments like paralysis and minor ailments like trapping.
749 __tablename__
= 'move_meta_ailments'
750 __singlename__
= 'move_meta_ailment'
751 id = Column(Integer
, primary_key
=True, nullable
=False,
752 info
=dict(description
="A numeric ID"))
753 identifier
= Column(Unicode(24), nullable
=False,
754 info
=dict(description
="An identifier", format
='identifier'))
756 class MoveMetaCategory(TableBase
):
757 u
"""Very general categories that loosely group move effects."""
758 __tablename__
= 'move_meta_categories'
759 __singlename__
= 'move_meta_category'
760 id = Column(Integer
, primary_key
=True, nullable
=False,
761 info
=dict(description
="A numeric ID"))
762 description
= ProseColumn(Unicode(64), plural
='descriptions', nullable
=False,
763 info
=dict(description
="A description of the category"))
765 class MoveMetaStatChange(TableBase
):
766 u
"""Stat changes moves (may) make."""
767 __tablename__
= 'move_meta_stat_changes'
768 move_id
= Column(Integer
, ForeignKey('moves.id'), primary_key
=True, nullable
=False, autoincrement
=False,
769 info
=dict(description
="ID of the move"))
770 stat_id
= Column(Integer
, ForeignKey('stats.id'), primary_key
=True, nullable
=False, autoincrement
=False,
771 info
=dict(description
="ID of the stat"))
772 change
= Column(Integer
, nullable
=False, index
=True,
773 info
=dict(description
="Amount of increase/decrease, in stages"))
775 class MoveTarget(TableBase
, UnofficiallyNamed
):
776 u
"""Targetting or "range" of a move, e.g. "Affects all opponents" or "Affects user".
778 __tablename__
= 'move_targets'
779 __singlename__
= 'move_target'
780 id = Column(Integer
, primary_key
=True, nullable
=False,
781 info
=dict(description
="A numeric ID"))
782 identifier
= Column(Unicode(32), nullable
=False,
783 info
=dict(description
="An identifier", format
='identifier'))
784 description
= ProseColumn(Unicode(128), plural
='descriptions', nullable
=False,
785 info
=dict(description
="A description", format
='plaintext'))
787 class Move(TableBase
, OfficiallyNamed
):
788 u
"""A Move: technique or attack a Pokémon can learn to use
790 __tablename__
= 'moves'
791 __singlename__
= 'move'
792 id = Column(Integer
, primary_key
=True, nullable
=False,
793 info
=dict(description
="A numeric ID"))
794 identifier
= Column(Unicode(24), nullable
=False,
795 info
=dict(description
="An identifier", format
='identifier'))
796 generation_id
= Column(Integer
, ForeignKey('generations.id'), nullable
=False,
797 info
=dict(description
="ID of the generation this move first appeared in"))
798 type_id
= Column(Integer
, ForeignKey('types.id'), nullable
=False,
799 info
=dict(description
="ID of the move's elemental type"))
800 power
= Column(SmallInteger
, nullable
=False,
801 info
=dict(description
="Base power of the move"))
802 pp
= Column(SmallInteger
, nullable
=True,
803 info
=dict(description
="Base PP (Power Points) of the move, nullable if not applicable (e.g. Struggle and Shadow moves)."))
804 accuracy
= Column(SmallInteger
, nullable
=True,
805 info
=dict(description
="Accuracy of the move; NULL means it never misses"))
806 priority
= Column(SmallInteger
, nullable
=False,
807 info
=dict(description
="The move's priority bracket"))
808 target_id
= Column(Integer
, ForeignKey('move_targets.id'), nullable
=False,
809 info
=dict(description
="ID of the target (range) of the move"))
810 damage_class_id
= Column(Integer
, ForeignKey('move_damage_classes.id'), nullable
=False,
811 info
=dict(description
="ID of the damage class (physical/special) of the move"))
812 effect_id
= Column(Integer
, ForeignKey('move_effects.id'), nullable
=False,
813 info
=dict(description
="ID of the move's effect"))
814 effect_chance
= Column(Integer
, nullable
=True,
815 info
=dict(description
="The chance for a secondary effect. What this is a chance of is specified by the move's effect."))
816 contest_type_id
= Column(Integer
, ForeignKey('contest_types.id'), nullable
=True,
817 info
=dict(description
="ID of the move's Contest type (e.g. cool or smart)"))
818 contest_effect_id
= Column(Integer
, ForeignKey('contest_effects.id'), nullable
=True,
819 info
=dict(description
="ID of the move's Contest effect"))
820 super_contest_effect_id
= Column(Integer
, ForeignKey('super_contest_effects.id'), nullable
=True,
821 info
=dict(description
="ID of the move's Super Contest effect"))
823 class MoveChangelog(TableBase
):
824 """History of changes to moves across main game versions."""
825 __tablename__
= 'move_changelog'
826 __singlename__
= 'move_changelog'
827 move_id
= Column(Integer
, ForeignKey('moves.id'), primary_key
=True, nullable
=False,
828 info
=dict(description
="ID of the move that changed"))
829 changed_in_version_group_id
= Column(Integer
, ForeignKey('version_groups.id'), primary_key
=True, nullable
=False,
830 info
=dict(description
="ID of the version group in which the move changed"))
831 type_id
= Column(Integer
, ForeignKey('types.id'), nullable
=True,
832 info
=dict(description
="Prior type of the move, or NULL if unchanged"))
833 power
= Column(SmallInteger
, nullable
=True,
834 info
=dict(description
="Prior base power of the move, or NULL if unchanged"))
835 pp
= Column(SmallInteger
, nullable
=True,
836 info
=dict(description
="Prior base PP of the move, or NULL if unchanged"))
837 accuracy
= Column(SmallInteger
, nullable
=True,
838 info
=dict(description
="Prior accuracy of the move, or NULL if unchanged"))
839 effect_id
= Column(Integer
, ForeignKey('move_effects.id'), nullable
=True,
840 info
=dict(description
="Prior ID of the effect, or NULL if unchanged"))
841 effect_chance
= Column(Integer
, nullable
=True,
842 info
=dict(description
="Prior effect chance, or NULL if unchanged"))
844 class Nature(TableBase
, OfficiallyNamed
):
845 u
"""A nature a Pokémon can have, such as Calm or Brave
847 __tablename__
= 'natures'
848 __singlename__
= 'nature'
849 id = Column(Integer
, primary_key
=True, nullable
=False,
850 info
=dict(description
="A numeric ID"))
851 identifier
= Column(Unicode(8), nullable
=False,
852 info
=dict(description
="An identifier", format
='identifier'))
853 decreased_stat_id
= Column(Integer
, ForeignKey('stats.id'), nullable
=False,
854 info
=dict(description
="ID of the stat that this nature decreases by 10% (if decreased_stat_id is the same, the effects cancel out)"))
855 increased_stat_id
= Column(Integer
, ForeignKey('stats.id'), nullable
=False,
856 info
=dict(description
="ID of the stat that this nature increases by 10% (if decreased_stat_id is the same, the effects cancel out)"))
857 hates_flavor_id
= Column(Integer
, ForeignKey('contest_types.id'), nullable
=False,
858 info
=dict(description
=u
"ID of the Berry flavor the Pokémon hates (if likes_flavor_id is the same, the effects cancel out)"))
859 likes_flavor_id
= Column(Integer
, ForeignKey('contest_types.id'), nullable
=False,
860 info
=dict(description
=u
"ID of the Berry flavor the Pokémon likes (if hates_flavor_id is the same, the effects cancel out)"))
863 def is_neutral(self
):
864 u
"""Returns True iff this nature doesn't alter a Pokémon's stats,
865 bestow taste preferences, etc.
867 return self
.increased_stat_id
== self
.decreased_stat_id
869 class NatureBattleStylePreference(TableBase
):
870 u
"""Battle Palace move preference
872 Specifies how likely a Pokémon with a specific Nature is to use a move of
873 a particular battl style in Battle Palace or Battle Tent
875 __tablename__
= 'nature_battle_style_preferences'
876 nature_id
= Column(Integer
, ForeignKey('natures.id'), primary_key
=True, nullable
=False,
877 info
=dict(description
=u
"ID of the Pokémon's nature"))
878 move_battle_style_id
= Column(Integer
, ForeignKey('move_battle_styles.id'), primary_key
=True, nullable
=False,
879 info
=dict(description
="ID of the battle style"))
880 low_hp_preference
= Column(Integer
, nullable
=False,
881 info
=dict(description
=u
"Chance of using the move, in percent, if HP is under ½"))
882 high_hp_preference
= Column(Integer
, nullable
=False,
883 info
=dict(description
=u
"Chance of using the move, in percent, if HP is over ½"))
885 class NaturePokeathlonStat(TableBase
):
886 u
"""Specifies how a Nature affects a Pokéathlon stat
888 __tablename__
= 'nature_pokeathlon_stats'
889 nature_id
= Column(Integer
, ForeignKey('natures.id'), primary_key
=True, nullable
=False,
890 info
=dict(description
="ID of the nature"))
891 pokeathlon_stat_id
= Column(Integer
, ForeignKey('pokeathlon_stats.id'), primary_key
=True, nullable
=False,
892 info
=dict(description
="ID of the stat"))
893 max_change
= Column(Integer
, nullable
=False,
894 info
=dict(description
="Maximum change"))
896 class PokeathlonStat(TableBase
, OfficiallyNamed
):
897 u
"""A Pokéathlon stat, such as "Stamina" or "Jump".
899 __tablename__
= 'pokeathlon_stats'
900 __singlename__
= 'pokeathlon_stat'
901 id = Column(Integer
, primary_key
=True, nullable
=False,
902 info
=dict(description
="A numeric ID"))
903 identifier
= Column(Unicode(8), nullable
=False,
904 info
=dict(description
="An identifier", format
='identifier'))
906 class Pokedex(TableBase
, UnofficiallyNamed
):
907 u
"""A collection of Pokémon species ordered in a particular way
909 __tablename__
= 'pokedexes'
910 __singlename__
= 'pokedex'
911 id = Column(Integer
, primary_key
=True, nullable
=False,
912 info
=dict(description
="A numeric ID"))
913 region_id
= Column(Integer
, ForeignKey('regions.id'), nullable
=True,
914 info
=dict(description
=u
"ID of the region this Pokédex is used in, or None if it's global"))
915 identifier
= Column(Unicode(16), nullable
=False,
916 info
=dict(description
=u
"An identifier", format
='identifier'))
917 description
= ProseColumn(Unicode(512), plural
='descriptions', nullable
=False,
918 info
=dict(description
=u
"A longer description of the Pokédex", format
='plaintext'))
920 class Pokemon(TableBase
, OfficiallyNamed
):
921 u
"""A species of Pokémon. The core to this whole mess.
923 __tablename__
= 'pokemon'
924 __singlename__
= 'pokemon'
925 id = Column(Integer
, primary_key
=True, nullable
=False,
926 info
=dict(description
=u
"A numeric ID"))
927 identifier
= Column(Unicode(20), nullable
=False,
928 info
=dict(description
=u
"An identifier", format
='identifier'))
929 generation_id
= Column(Integer
, ForeignKey('generations.id'),
930 info
=dict(description
=u
"ID of the generation this species first appeared in"))
931 evolution_chain_id
= Column(Integer
, ForeignKey('evolution_chains.id'),
932 info
=dict(description
=u
"ID of the species' evolution chain (a.k.a. family)"))
933 height
= Column(Integer
, nullable
=False,
934 info
=dict(description
=u
"The height of the Pokémon, in decimeters (tenths of a meter)"))
935 weight
= Column(Integer
, nullable
=False,
936 info
=dict(description
=u
"The weight of the Pokémon, in tenths of a kilogram (decigrams)"))
937 species
= TextColumn(Unicode(16), nullable
=False, plural
='species_names',
938 info
=dict(description
=u
'The short flavor text, such as "Seed" or "Lizard"; usually affixed with the word "Pokémon"',
939 official
=True, format
='plaintext'))
940 color_id
= Column(Integer
, ForeignKey('pokemon_colors.id'), nullable
=False,
941 info
=dict(description
=u
"ID of this Pokémon's Pokédex color, as used for a gimmick search function in the games."))
942 pokemon_shape_id
= Column(Integer
, ForeignKey('pokemon_shapes.id'), nullable
=True,
943 info
=dict(description
=u
"ID of this Pokémon's body shape, as used for a gimmick search function in the games."))
944 habitat_id
= Column(Integer
, ForeignKey('pokemon_habitats.id'), nullable
=True,
945 info
=dict(description
=u
"ID of this Pokémon's habitat, as used for a gimmick search function in the games."))
946 gender_rate
= Column(Integer
, nullable
=False,
947 info
=dict(description
=u
"The chance of this Pokémon being female, in eighths; or -1 for genderless"))
948 capture_rate
= Column(Integer
, nullable
=False,
949 info
=dict(description
=u
"The base capture rate; up to 255"))
950 base_experience
= Column(Integer
, nullable
=False,
951 info
=dict(description
=u
"The base EXP gained when defeating this Pokémon")) # XXX: Is this correct?
952 base_happiness
= Column(Integer
, nullable
=False,
953 info
=dict(description
=u
"The tameness when caught by a normal ball"))
954 is_baby
= Column(Boolean
, nullable
=False,
955 info
=dict(description
=u
"True iff the Pokémon is a baby, i.e. a lowest-stage Pokémon that cannot breed but whose evolved form can."))
956 hatch_counter
= Column(Integer
, nullable
=False,
957 info
=dict(description
=u
"Initial hatch counter: one must walk 255 × (hatch_counter + 1) steps before this Pokémon's egg hatches, unless utilizing bonuses like Flame Body's"))
958 has_gender_differences
= Column(Boolean
, nullable
=False,
959 info
=dict(description
=u
"Set iff the species exhibits enough sexual dimorphism to have separate sets of sprites in Gen IV and beyond."))
960 order
= Column(Integer
, nullable
=False, index
=True,
961 info
=dict(description
=u
"Order for sorting. Almost national order, except families and forms are grouped together."))
963 ### Stuff to handle alternate Pokémon forms
967 u
"""Returns the Pokémon's form, using its default form as fallback."""
969 return self
.unique_form
or self
.default_form
972 def is_base_form(self
):
973 u
"""Returns True iff the Pokémon is the base form for its species,
977 return self
.unique_form
is None or self
.unique_form
.is_default
981 u
"""Returns the Pokémon's form name if it represents a particular form
982 and that form has a name, or None otherwise.
985 # If self.unique_form is None, the short-circuit "and" will go ahead
986 # and return that. Otherwise, it'll return the form's name, which may
988 return self
.unique_form
and self
.unique_form
.name
992 u
"""Returns the Pokémon's name, including its form if applicable."""
995 return u
'{0} {1}'.format(self
.form_name
, self
.name
)
1000 def normal_form(self
):
1001 u
"""Returns the normal form for this Pokémon; i.e., this will return
1002 regular Deoxys when called on any Deoxys form.
1005 if self
.unique_form
:
1006 return self
.unique_form
.form_base_pokemon
1011 def stat(self
, stat_name
):
1012 u
"""Returns a PokemonStat record for the given stat name (or Stat row
1013 object). Uses the normal has-many machinery, so all the stats are
1016 if isinstance(stat_name
, Stat
):
1017 stat_name
= stat_name
.name
1019 for pokemon_stat
in self
.stats
:
1020 if pokemon_stat
.stat
.name
== stat_name
:
1023 raise KeyError(u
'No stat named %s' % stat_name
)
1026 def better_damage_class(self
):
1027 u
"""Returns the MoveDamageClass that this Pokémon is best suited for,
1028 based on its attack stats.
1030 If the attack stats are about equal (within 5), returns None. The
1031 value None, not the damage class called 'None'.
1033 phys
= self
.stat(u
'Attack')
1034 spec
= self
.stat(u
'Special Attack')
1036 diff
= phys
.base_stat
- spec
.base_stat
1039 return phys
.stat
.damage_class
1041 return spec
.stat
.damage_class
1045 class PokemonAbility(TableBase
):
1046 u
"""Maps an ability to a Pokémon that can have it
1048 __tablename__
= 'pokemon_abilities'
1049 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1050 info
=dict(description
=u
"ID of the Pokémon"))
1051 ability_id
= Column(Integer
, ForeignKey('abilities.id'), nullable
=False,
1052 info
=dict(description
=u
"ID of the ability"))
1053 # XXX having both a method and a slot is kind of gross. "slot" is a
1054 # misnomer, anyway: duplicate abilities don't appear in slot 2.
1055 # Probably should replace that with "order".
1056 is_dream
= Column(Boolean
, nullable
=False, index
=True,
1057 info
=dict(description
=u
"Whether this is a Dream World ability"))
1058 slot
= Column(Integer
, primary_key
=True, nullable
=False, autoincrement
=False,
1059 info
=dict(description
=u
"The ability slot, i.e. 1 or 2 for gen. IV"))
1061 class PokemonColor(TableBase
, OfficiallyNamed
):
1062 u
"""The "Pokédex color" of a Pokémon species. Usually based on the Pokémon's color.
1064 __tablename__
= 'pokemon_colors'
1065 __singlename__
= 'pokemon_color'
1066 id = Column(Integer
, primary_key
=True, nullable
=False, autoincrement
=False,
1067 info
=dict(description
=u
"ID of the Pokémon"))
1068 identifier
= Column(Unicode(6), nullable
=False,
1069 info
=dict(description
=u
"An identifier", format
='identifier'))
1071 class PokemonDexNumber(TableBase
):
1072 u
"""The number of a Pokémon in a particular Pokédex (e.g. Jigglypuff is #138 in Hoenn's 'dex)
1074 __tablename__
= 'pokemon_dex_numbers'
1075 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1076 info
=dict(description
=u
"ID of the Pokémon"))
1077 pokedex_id
= Column(Integer
, ForeignKey('pokedexes.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1078 info
=dict(description
=u
"ID of the Pokédex"))
1079 pokedex_number
= Column(Integer
, nullable
=False,
1080 info
=dict(description
=u
"Number of the Pokémon in that the Pokédex"))
1082 class PokemonEggGroup(TableBase
):
1083 u
"""Maps an Egg group to a Pokémon; each Pokémon belongs to one or two egg groups
1085 __tablename__
= 'pokemon_egg_groups'
1086 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1087 info
=dict(description
=u
"ID of the Pokémon"))
1088 egg_group_id
= Column(Integer
, ForeignKey('egg_groups.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1089 info
=dict(description
=u
"ID of the egg group"))
1091 class PokemonEvolution(TableBase
):
1092 u
"""A required action ("trigger") and the conditions under which the trigger
1093 must occur to cause a Pokémon to evolve.
1095 Any condition may be null if it does not apply for a particular Pokémon.
1097 __tablename__
= 'pokemon_evolution'
1098 from_pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), nullable
=False,
1099 info
=dict(description
=u
"The ID of the pre-evolution Pokémon."))
1100 to_pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1101 info
=dict(description
=u
"The ID of the post-evolution Pokémon."))
1102 evolution_trigger_id
= Column(Integer
, ForeignKey('evolution_triggers.id'), nullable
=False,
1103 info
=dict(description
=u
"The ID of the evolution trigger."))
1104 trigger_item_id
= Column(Integer
, ForeignKey('items.id'), nullable
=True,
1105 info
=dict(description
=u
"The ID of the item that must be used on the Pokémon."))
1106 minimum_level
= Column(Integer
, nullable
=True,
1107 info
=dict(description
=u
"The minimum level for the Pokémon."))
1108 gender
= Column(Enum('male', 'female', name
='pokemon_evolution_gender'), nullable
=True,
1109 info
=dict(description
=u
"The Pokémon's required gender, or None if gender doesn't matter"))
1110 location_id
= Column(Integer
, ForeignKey('locations.id'), nullable
=True,
1111 info
=dict(description
=u
"The ID of the location the evolution must be triggered at."))
1112 held_item_id
= Column(Integer
, ForeignKey('items.id'), nullable
=True,
1113 info
=dict(description
=u
"The ID of the item the Pokémon must hold."))
1114 time_of_day
= Column(Enum('day', 'night', name
='pokemon_evolution_time_of_day'), nullable
=True,
1115 info
=dict(description
=u
"The required time of day."))
1116 known_move_id
= Column(Integer
, ForeignKey('moves.id'), nullable
=True,
1117 info
=dict(description
=u
"The ID of the move the Pokémon must know."))
1118 minimum_happiness
= Column(Integer
, nullable
=True,
1119 info
=dict(description
=u
"The minimum happiness value the Pokémon must have."))
1120 minimum_beauty
= Column(Integer
, nullable
=True,
1121 info
=dict(description
=u
"The minimum Beauty value the Pokémon must have."))
1122 relative_physical_stats
= Column(Integer
, nullable
=True,
1123 info
=dict(description
=u
"The required relation between the Pokémon's Attack and Defense stats, as sgn(atk-def)."))
1124 party_pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), nullable
=True,
1125 info
=dict(description
=u
"The ID of the Pokémon that must be present in the party."))
1126 trade_pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), nullable
=True,
1127 info
=dict(description
=u
"The ID of the Pokémon for which this Pokémon must be traded."))
1129 class PokemonFlavorText(TableBase
, LanguageSpecific
):
1130 u
"""In-game Pokédex descrption of a Pokémon.
1132 __tablename__
= 'pokemon_flavor_text'
1133 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1134 info
=dict(description
=u
"ID of the Pokémon"))
1135 version_id
= Column(Integer
, ForeignKey('versions.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1136 info
=dict(description
=u
"ID of the version that has this flavor text"))
1137 flavor_text
= Column(Unicode(255), nullable
=False,
1138 info
=dict(description
=u
"ID of the version that has this flavor text", official
=True, format
='gametext'))
1140 class PokemonForm(TableBase
, OfficiallyNamed
):
1141 u
"""An individual form of a Pokémon.
1143 Pokémon that do not have separate forms are still given a single row to
1144 represent their single form.
1146 __tablename__
= 'pokemon_forms'
1147 __singlename__
= 'pokemon_form'
1148 id = Column(Integer
, primary_key
=True, nullable
=False,
1149 info
=dict(description
=u
'A unique ID for this form.'))
1150 identifier
= Column(Unicode(16), nullable
=True,
1151 info
=dict(description
=u
"An identifier", format
='identifier'))
1152 form_base_pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), nullable
=False, autoincrement
=False,
1153 info
=dict(description
=u
'The ID of the base Pokémon for this form.'))
1154 unique_pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), autoincrement
=False,
1155 info
=dict(description
=u
'The ID of a Pokémon that represents specifically this form, for Pokémon with functionally-different forms like Wormadam.'))
1156 introduced_in_version_group_id
= Column(Integer
, ForeignKey('version_groups.id'), autoincrement
=False,
1157 info
=dict(description
=u
'The ID of the version group in which this form first appeared.'))
1158 is_default
= Column(Boolean
, nullable
=False,
1159 info
=dict(description
=u
'Set for exactly one form used as the default for each species.'))
1160 order
= Column(Integer
, nullable
=False, autoincrement
=False,
1161 info
=dict(description
=u
'The order in which forms should be sorted. Multiple forms may have equal order, in which case they should fall back on sorting by name.'))
1165 u
"""Returns the Pokémon for this form, using the form base as fallback.
1168 return self
.unique_pokemon
or self
.form_base_pokemon
1171 def full_name(self
):
1172 u
"""Returns the full name of this form, e.g. "Plant Cloak"."""
1176 elif self
.form_group
and self
.form_group
.term
:
1177 return u
'{0} {1}'.format(self
.name
, self
.form_group
.term
)
1182 def pokemon_name(self
):
1183 u
"""Returns the name of this Pokémon with this form, e.g. "Plant
1188 return u
'{0} {1}'.format(self
.name
, self
.form_base_pokemon
.name
)
1190 return self
.form_base_pokemon
.name
1192 class PokemonFormGroup(TableBase
):
1193 u
"""Information about a Pokémon's forms as a group."""
1194 __tablename__
= 'pokemon_form_groups'
1195 __singlename__
= 'pokemon_form_group'
1196 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1197 info
=dict(description
=u
"ID of the base form Pokémon"))
1198 term
= ProseColumn(Unicode(16), plural
='terms', nullable
=True,
1199 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'))
1200 is_battle_only
= Column(Boolean
, nullable
=False,
1201 info
=dict(description
=u
"Set iff the forms only change in battle"))
1202 description
= ProseColumn(markdown
.MarkdownColumn(1024), plural
='descriptions', nullable
=False,
1203 info
=dict(description
=u
"Description of how the forms work", format
='markdown'))
1204 PokemonFormGroup
.id = PokemonFormGroup
.pokemon_id
1206 class PokemonFormPokeathlonStat(TableBase
):
1207 u
"""A Pokémon form's performance in one Pokéathlon stat."""
1208 __tablename__
= 'pokemon_form_pokeathlon_stats'
1209 pokemon_form_id
= Column(Integer
, ForeignKey('pokemon_forms.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1210 info
=dict(description
=u
'The ID of the Pokémon form.'))
1211 pokeathlon_stat_id
= Column(Integer
, ForeignKey('pokeathlon_stats.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1212 info
=dict(description
=u
'The ID of the Pokéathlon stat.'))
1213 minimum_stat
= Column(Integer
, nullable
=False, autoincrement
=False,
1214 info
=dict(description
=u
'The minimum value for this stat for this Pokémon form.'))
1215 base_stat
= Column(Integer
, nullable
=False, autoincrement
=False,
1216 info
=dict(description
=u
'The default value for this stat for this Pokémon form.'))
1217 maximum_stat
= Column(Integer
, nullable
=False, autoincrement
=False,
1218 info
=dict(description
=u
'The maximum value for this stat for this Pokémon form.'))
1220 class PokemonHabitat(TableBase
, OfficiallyNamed
):
1221 u
"""The habitat of a Pokémon, as given in the FireRed/LeafGreen version Pokédex
1223 __tablename__
= 'pokemon_habitats'
1224 __singlename__
= 'pokemon_habitat'
1225 id = Column(Integer
, primary_key
=True, nullable
=False, autoincrement
=False,
1226 info
=dict(description
=u
"A numeric ID"))
1227 identifier
= Column(Unicode(16), nullable
=False,
1228 info
=dict(description
=u
"An identifier", format
='identifier'))
1230 class PokemonInternalID(TableBase
):
1231 u
"""The number of a Pokémon a game uses internally
1233 __tablename__
= 'pokemon_internal_ids'
1234 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, autoincrement
=False, nullable
=False,
1235 info
=dict(description
=u
"Database ID of the Pokémon"))
1236 generation_id
= Column(Integer
, ForeignKey('generations.id'), primary_key
=True, autoincrement
=False, nullable
=False,
1237 info
=dict(description
=u
"Database ID of the generation"))
1238 internal_id
= Column(Integer
, nullable
=False,
1239 info
=dict(description
=u
"Internal ID the generation's games use for the Pokémon"))
1241 class PokemonItem(TableBase
):
1242 u
"""Record of an item a Pokémon can hold in the wild
1244 __tablename__
= 'pokemon_items'
1245 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1246 info
=dict(description
=u
"ID of the Pokémon"))
1247 version_id
= Column(Integer
, ForeignKey('versions.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1248 info
=dict(description
=u
"ID of the version this applies to"))
1249 item_id
= Column(Integer
, ForeignKey('items.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1250 info
=dict(description
=u
"ID of the item"))
1251 rarity
= Column(Integer
, nullable
=False,
1252 info
=dict(description
=u
"Chance of the Pokémon holding the item, in percent"))
1254 class PokemonMove(TableBase
):
1255 u
"""Record of a move a Pokémon can learn
1257 __tablename__
= 'pokemon_moves'
1258 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), nullable
=False, index
=True,
1259 info
=dict(description
=u
"ID of the Pokémon"))
1260 version_group_id
= Column(Integer
, ForeignKey('version_groups.id'), nullable
=False, index
=True,
1261 info
=dict(description
=u
"ID of the version group this applies to"))
1262 move_id
= Column(Integer
, ForeignKey('moves.id'), nullable
=False, index
=True,
1263 info
=dict(description
=u
"ID of the move"))
1264 pokemon_move_method_id
= Column(Integer
, ForeignKey('pokemon_move_methods.id'), nullable
=False, index
=True,
1265 info
=dict(description
=u
"ID of the method this move is learned by"))
1266 level
= Column(Integer
, nullable
=True, index
=True,
1267 info
=dict(description
=u
"Level the move is learned at, if applicable"))
1268 order
= Column(Integer
, nullable
=True,
1269 info
=dict(description
=u
"A sort key to produce the correct ordering when all else is equal")) # XXX: This needs a better description
1272 PrimaryKeyConstraint('pokemon_id', 'version_group_id', 'move_id', 'pokemon_move_method_id', 'level'),
1276 class PokemonMoveMethod(TableBase
, UnofficiallyNamed
):
1277 u
"""A method a move can be learned by, such as "Level up" or "Tutor".
1279 __tablename__
= 'pokemon_move_methods'
1280 __singlename__
= 'pokemon_move_method'
1281 id = Column(Integer
, primary_key
=True, nullable
=False, autoincrement
=False,
1282 info
=dict(description
=u
"A numeric ID"))
1283 identifier
= Column(Unicode(64), nullable
=False,
1284 info
=dict(description
=u
"An identifier", format
='identifier'))
1285 description
= ProseColumn(Unicode(255), plural
='descriptions', nullable
=False,
1286 info
=dict(description
=u
"A detailed description of how the method works", format
='plaintext'))
1288 class PokemonShape(TableBase
, UnofficiallyNamed
):
1289 u
"""The shape of a Pokémon's body, as used in generation IV Pokédexes.
1291 __tablename__
= 'pokemon_shapes'
1292 __singlename__
= 'pokemon_shape'
1293 id = Column(Integer
, primary_key
=True, nullable
=False,
1294 info
=dict(description
=u
"A numeric ID"))
1295 identifier
= Column(Unicode(24), nullable
=False,
1296 info
=dict(description
=u
"An identifier", format
='identifier'))
1297 awesome_name
= ProseColumn(Unicode(16), plural
='awesome_names', nullable
=False,
1298 info
=dict(description
=u
"A splendiferous name of the body shape", format
='plaintext'))
1300 class PokemonStat(TableBase
):
1301 u
"""A stat value of a Pokémon
1303 __tablename__
= 'pokemon_stats'
1304 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1305 info
=dict(description
=u
"ID of the Pokémon"))
1306 stat_id
= Column(Integer
, ForeignKey('stats.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1307 info
=dict(description
=u
"ID of the stat"))
1308 base_stat
= Column(Integer
, nullable
=False,
1309 info
=dict(description
=u
"The base stat"))
1310 effort
= Column(Integer
, nullable
=False,
1311 info
=dict(description
=u
"The effort increase in this stat gained when this Pokémon is defeated"))
1313 class PokemonType(TableBase
):
1314 u
"""Maps a type to a Pokémon. Each Pokémon has 1 or 2 types.
1316 __tablename__
= 'pokemon_types'
1317 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1318 info
=dict(description
=u
"ID of the Pokémon"))
1319 type_id
= Column(Integer
, ForeignKey('types.id'), nullable
=False,
1320 info
=dict(description
=u
"ID of the type"))
1321 slot
= Column(Integer
, primary_key
=True, nullable
=False, autoincrement
=False,
1322 info
=dict(description
=u
"The type's slot, 1 or 2, used to sort types if there are two of them"))
1324 class Region(TableBase
, OfficiallyNamed
):
1325 u
"""Major areas of the world: Kanto, Johto, etc.
1327 __tablename__
= 'regions'
1328 __singlename__
= 'region'
1329 id = Column(Integer
, primary_key
=True, nullable
=False,
1330 info
=dict(description
=u
"A numeric ID"))
1331 identifier
= Column(Unicode(16), nullable
=False,
1332 info
=dict(description
=u
"An identifier", format
='identifier'))
1334 class Stat(TableBase
, OfficiallyNamed
):
1335 u
"""A Stat, such as Attack or Speed
1337 __tablename__
= 'stats'
1338 __singlename__
= 'stat'
1339 id = Column(Integer
, primary_key
=True, nullable
=False,
1340 info
=dict(description
=u
"A numeric ID"))
1341 damage_class_id
= Column(Integer
, ForeignKey('move_damage_classes.id'), nullable
=True,
1342 info
=dict(description
=u
"For offensive and defensive stats, the damage this stat relates to; otherwise None (the NULL value)"))
1343 identifier
= Column(Unicode(16), nullable
=False,
1344 info
=dict(description
=u
"An identifier", format
='identifier'))
1346 class StatHint(TableBase
):
1347 u
"""Flavor text for genes that appears in a Pokémon's summary. Sometimes
1348 called "characteristics".
1350 __tablename__
= 'stat_hints'
1351 __singlename__
= 'stat_hint'
1352 id = Column(Integer
, primary_key
=True, nullable
=False,
1353 info
=dict(description
=u
"A numeric ID"))
1354 stat_id
= Column(Integer
, ForeignKey('stats.id'), nullable
=False,
1355 info
=dict(description
=u
"ID of the highest stat"))
1356 gene_mod_5
= Column(Integer
, nullable
=False, index
=True,
1357 info
=dict(description
=u
"Value of the highest stat modulo 5"))
1358 text
= TextColumn(Unicode(24), plural
='texts', nullable
=False, index
=True, unique
=True,
1359 info
=dict(description
=u
"The text displayed", official
=True, format
='plaintext'))
1361 class SuperContestCombo(TableBase
):
1362 u
"""Combo of two moves in a Super Contest.
1364 __tablename__
= 'super_contest_combos'
1365 first_move_id
= Column(Integer
, ForeignKey('moves.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1366 info
=dict(description
=u
"The ID of the first move in the combo."))
1367 second_move_id
= Column(Integer
, ForeignKey('moves.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1368 info
=dict(description
=u
"The ID of the second and last move."))
1370 class SuperContestEffect(TableBase
):
1371 u
"""An effect a move can have when used in the Super Contest
1373 __tablename__
= 'super_contest_effects'
1374 __singlename__
= 'super_contest_effect'
1375 id = Column(Integer
, primary_key
=True, nullable
=False,
1376 info
=dict(description
=u
"This effect's unique ID."))
1377 appeal
= Column(SmallInteger
, nullable
=False,
1378 info
=dict(description
=u
"The number of hearts the user gains."))
1379 flavor_text
= ProseColumn(Unicode(64), plural
='flavor_texts', nullable
=False,
1380 info
=dict(description
=u
"A description of the effect.", format
='plaintext'))
1382 class TypeEfficacy(TableBase
):
1383 u
"""The damage multiplier used when a move of a particular type damages a
1384 Pokémon of a particular other type.
1386 __tablename__
= 'type_efficacy'
1387 damage_type_id
= Column(Integer
, ForeignKey('types.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1388 info
=dict(description
=u
"The ID of the damaging type."))
1389 target_type_id
= Column(Integer
, ForeignKey('types.id'), primary_key
=True, nullable
=False, autoincrement
=False,
1390 info
=dict(description
=u
"The ID of the defending Pokémon's type."))
1391 damage_factor
= Column(Integer
, nullable
=False,
1392 info
=dict(description
=u
"The multiplier, as a percentage of damage inflicted."))
1394 class Type(TableBase
, OfficiallyNamed
):
1395 u
"""Any of the elemental types Pokémon and moves can have."""
1396 __tablename__
= 'types'
1397 __singlename__
= 'type'
1398 id = Column(Integer
, primary_key
=True, nullable
=False,
1399 info
=dict(description
=u
"A unique ID for this type."))
1400 identifier
= Column(Unicode(8), nullable
=False,
1401 info
=dict(description
=u
"An identifier", format
='identifier'))
1402 generation_id
= Column(Integer
, ForeignKey('generations.id'), nullable
=False,
1403 info
=dict(description
=u
"The ID of the generation this type first appeared in."))
1404 damage_class_id
= Column(Integer
, ForeignKey('move_damage_classes.id'), nullable
=True,
1405 info
=dict(description
=u
"The ID of the damage class this type's moves had before Generation IV, null if not applicable (e.g. ???)."))
1407 class VersionGroup(TableBase
):
1408 u
"""A group of versions, containing either two paired versions (such as Red
1409 and Blue) or a single game (such as Yellow.)
1411 __tablename__
= 'version_groups'
1412 id = Column(Integer
, primary_key
=True, nullable
=False,
1413 info
=dict(description
=u
"This version group's unique ID."))
1414 generation_id
= Column(Integer
, ForeignKey('generations.id'), nullable
=False,
1415 info
=dict(description
=u
"The ID of the generation the games in this group belong to."))
1416 pokedex_id
= Column(Integer
, ForeignKey('pokedexes.id'), nullable
=False,
1417 info
=dict(description
=u
"The ID of the regional Pokédex used in this version group."))
1419 class VersionGroupRegion(TableBase
):
1420 u
"""Maps a version group to a region that appears in it."""
1421 __tablename__
= 'version_group_regions'
1422 version_group_id
= Column(Integer
, ForeignKey('version_groups.id'), primary_key
=True, nullable
=False,
1423 info
=dict(description
=u
"The ID of the version group."))
1424 region_id
= Column(Integer
, ForeignKey('regions.id'), primary_key
=True, nullable
=False,
1425 info
=dict(description
=u
"The ID of the region."))
1427 class Version(TableBase
, OfficiallyNamed
):
1428 u
"""An individual main-series Pokémon game."""
1429 __tablename__
= 'versions'
1430 __singlename__
= 'version'
1431 id = Column(Integer
, primary_key
=True, nullable
=False,
1432 info
=dict(description
=u
"A unique ID for this version."))
1433 version_group_id
= Column(Integer
, ForeignKey('version_groups.id'), nullable
=False,
1434 info
=dict(description
=u
"The ID of the version group this game belongs to."))
1435 identifier
= Column(Unicode(32), nullable
=False,
1436 info
=dict(description
=u
'And identifier', format
='identifier'))
1439 ### Relations down here, to avoid ordering problems
1440 Ability
.changelog
= relation(AbilityChangelog
,
1441 order_by
=AbilityChangelog
.changed_in_version_group_id
.desc(),
1444 Ability
.flavor_text
= relation(AbilityFlavorText
, order_by
=AbilityFlavorText
.version_group_id
, backref
='ability')
1445 Ability
.generation
= relation(Generation
, backref
='abilities')
1446 Ability
.all_pokemon
= relation(Pokemon
,
1447 secondary
=PokemonAbility
.__table__
,
1448 order_by
=Pokemon
.order
,
1449 back_populates
='all_abilities',
1451 Ability
.pokemon
= relation(Pokemon
,
1452 secondary
=PokemonAbility
.__table__
,
1454 PokemonAbility
.ability_id
== Ability
.id,
1455 PokemonAbility
.is_dream
== False
1457 order_by
=Pokemon
.order
,
1458 back_populates
='abilities',
1460 Ability
.dream_pokemon
= relation(Pokemon
,
1461 secondary
=PokemonAbility
.__table__
,
1463 PokemonAbility
.ability_id
== Ability
.id,
1464 PokemonAbility
.is_dream
== True
1466 order_by
=Pokemon
.order
,
1467 back_populates
='dream_ability',
1470 AbilityChangelog
.changed_in
= relation(VersionGroup
, backref
='ability_changelog')
1472 AbilityFlavorText
.version_group
= relation(VersionGroup
)
1474 Berry
.berry_firmness
= relation(BerryFirmness
, backref
='berries')
1475 Berry
.firmness
= association_proxy('berry_firmness', 'name')
1476 Berry
.flavors
= relation(BerryFlavor
, order_by
=BerryFlavor
.contest_type_id
, backref
='berry')
1477 Berry
.natural_gift_type
= relation(Type
)
1479 BerryFlavor
.contest_type
= relation(ContestType
)
1481 ContestCombo
.first
= relation(Move
, primaryjoin
=ContestCombo
.first_move_id
==Move
.id,
1482 backref
='contest_combo_first')
1483 ContestCombo
.second
= relation(Move
, primaryjoin
=ContestCombo
.second_move_id
==Move
.id,
1484 backref
='contest_combo_second')
1486 Encounter
.location_area
= relation(LocationArea
, backref
='encounters')
1487 Encounter
.pokemon
= relation(Pokemon
, backref
='encounters')
1488 Encounter
.version
= relation(Version
, backref
='encounters')
1489 Encounter
.slot
= relation(EncounterSlot
, backref
='encounters')
1491 EncounterConditionValue
.condition
= relation(EncounterCondition
, backref
='values')
1493 Encounter
.condition_value_map
= relation(EncounterConditionValueMap
, backref
='encounter')
1494 Encounter
.condition_values
= association_proxy('condition_value_map', 'condition_value')
1495 EncounterConditionValueMap
.condition_value
= relation(EncounterConditionValue
,
1496 backref
='encounter_map')
1498 EncounterSlot
.terrain
= relation(EncounterTerrain
, backref
='slots')
1499 EncounterSlot
.version_group
= relation(VersionGroup
)
1501 EvolutionChain
.growth_rate
= relation(GrowthRate
, backref
='evolution_chains')
1502 EvolutionChain
.baby_trigger_item
= relation(Item
, backref
='evolution_chains')
1503 EvolutionChain
.pokemon
= relation(Pokemon
, order_by
=Pokemon
.order
, back_populates
='evolution_chain')
1505 Experience
.growth_rate
= relation(GrowthRate
, backref
='experience_table')
1507 Generation
.canonical_pokedex
= relation(Pokedex
, backref
='canonical_for_generation')
1508 Generation
.versions
= relation(Version
, secondary
=VersionGroup
.__table__
)
1509 Generation
.main_region
= relation(Region
)
1511 GrowthRate
.max_experience_obj
= relation(Experience
, primaryjoin
=and_(Experience
.growth_rate_id
== GrowthRate
.id, Experience
.level
== 100), uselist
=False)
1512 GrowthRate
.max_experience
= association_proxy('max_experience_obj', 'experience')
1514 Item
.berry
= relation(Berry
, uselist
=False, backref
='item')
1515 Item
.flags
= relation(ItemFlag
, secondary
=ItemFlagMap
.__table__
)
1516 Item
.flavor_text
= relation(ItemFlavorText
, order_by
=ItemFlavorText
.version_group_id
.asc(), backref
='item')
1517 Item
.fling_effect
= relation(ItemFlingEffect
, backref
='items')
1518 Item
.machines
= relation(Machine
, order_by
=Machine
.version_group_id
.asc())
1519 Item
.category
= relation(ItemCategory
)
1520 Item
.pocket
= association_proxy('category', 'pocket')
1522 ItemCategory
.items
= relation(Item
, order_by
=Item
.identifier
)
1523 ItemCategory
.pocket
= relation(ItemPocket
)
1525 ItemFlavorText
.version_group
= relation(VersionGroup
)
1527 ItemInternalID
.item
= relation(Item
, backref
='internal_ids')
1528 ItemInternalID
.generation
= relation(Generation
)
1530 ItemPocket
.categories
= relation(ItemCategory
, order_by
=ItemCategory
.identifier
)
1532 Location
.region
= relation(Region
, backref
='locations')
1534 LocationArea
.location
= relation(Location
, backref
='areas')
1536 LocationInternalID
.location
= relation(Location
, backref
='internal_ids')
1537 LocationInternalID
.generation
= relation(Generation
)
1539 Machine
.item
= relation(Item
)
1540 Machine
.version_group
= relation(VersionGroup
)
1542 Move
.changelog
= relation(MoveChangelog
,
1543 order_by
=MoveChangelog
.changed_in_version_group_id
.desc(),
1546 Move
.contest_effect
= relation(ContestEffect
, backref
='moves')
1547 Move
.contest_combo_next
= association_proxy('contest_combo_first', 'second')
1548 Move
.contest_combo_prev
= association_proxy('contest_combo_second', 'first')
1549 Move
.contest_type
= relation(ContestType
, backref
='moves')
1550 Move
.damage_class
= relation(MoveDamageClass
, backref
='moves')
1551 Move
.flags
= association_proxy('move_flags', 'flag')
1552 Move
.flavor_text
= relation(MoveFlavorText
, order_by
=MoveFlavorText
.version_group_id
, backref
='move')
1553 Move
.generation
= relation(Generation
, backref
='moves')
1554 Move
.machines
= relation(Machine
, backref
='move')
1555 Move
.meta
= relation(MoveMeta
, uselist
=False, backref
='move')
1556 Move
.meta_stat_changes
= relation(MoveMetaStatChange
)
1557 Move
.move_effect
= relation(MoveEffect
, backref
='moves')
1558 Move
.move_flags
= relation(MoveFlag
, backref
='move')
1559 Move
.super_contest_effect
= relation(SuperContestEffect
, backref
='moves')
1560 Move
.super_contest_combo_next
= association_proxy('super_contest_combo_first', 'second')
1561 Move
.super_contest_combo_prev
= association_proxy('super_contest_combo_second', 'first')
1562 Move
.target
= relation(MoveTarget
, backref
='moves')
1563 Move
.type = relation(Type
, back_populates
='moves')
1565 Move
.effect
= markdown
.MoveEffectProperty('effect')
1566 Move
.effects
= markdown
.MoveEffectsProperty('effect')
1567 Move
.short_effect
= markdown
.MoveEffectProperty('short_effect')
1568 Move
.short_effects
= markdown
.MoveEffectsProperty('short_effect')
1570 MoveChangelog
.changed_in
= relation(VersionGroup
, backref
='move_changelog')
1571 MoveChangelog
.move_effect
= relation(MoveEffect
, backref
='move_changelog')
1572 MoveChangelog
.type = relation(Type
, backref
='move_changelog')
1574 MoveChangelog
.effect
= markdown
.MoveEffectProperty('effect')
1575 MoveChangelog
.effects
= markdown
.MoveEffectsProperty('effect')
1576 MoveChangelog
.short_effect
= markdown
.MoveEffectProperty('short_effect')
1577 MoveChangelog
.short_effects
= markdown
.MoveEffectsProperty('short_effect')
1579 MoveEffect
.category_map
= relation(MoveEffectCategoryMap
)
1580 MoveEffect
.categories
= association_proxy('category_map', 'category')
1581 MoveEffect
.changelog
= relation(MoveEffectChangelog
,
1582 order_by
=MoveEffectChangelog
.changed_in_version_group_id
.desc(),
1583 backref
='move_effect',
1585 MoveEffectCategoryMap
.category
= relation(MoveEffectCategory
)
1587 MoveEffectChangelog
.changed_in
= relation(VersionGroup
, backref
='move_effect_changelog')
1589 MoveFlag
.flag
= relation(MoveFlagType
)
1591 MoveFlavorText
.version_group
= relation(VersionGroup
)
1593 MoveMeta
.category
= relation(MoveMetaCategory
, backref
='move_meta')
1594 MoveMeta
.ailment
= relation(MoveMetaAilment
, backref
='move_meta')
1596 MoveMetaStatChange
.stat
= relation(Stat
, backref
='move_meta_stat_changes')
1598 Nature
.decreased_stat
= relation(Stat
, primaryjoin
=Nature
.decreased_stat_id
==Stat
.id,
1599 backref
='decreasing_natures')
1600 Nature
.increased_stat
= relation(Stat
, primaryjoin
=Nature
.increased_stat_id
==Stat
.id,
1601 backref
='increasing_natures')
1602 Nature
.hates_flavor
= relation(ContestType
, primaryjoin
=Nature
.hates_flavor_id
==ContestType
.id,
1603 backref
='hating_natures')
1604 Nature
.likes_flavor
= relation(ContestType
, primaryjoin
=Nature
.likes_flavor_id
==ContestType
.id,
1605 backref
='liking_natures')
1606 Nature
.battle_style_preferences
= relation(NatureBattleStylePreference
,
1607 order_by
=NatureBattleStylePreference
.move_battle_style_id
,
1609 Nature
.pokeathlon_effects
= relation(NaturePokeathlonStat
, order_by
=NaturePokeathlonStat
.pokeathlon_stat_id
)
1611 NatureBattleStylePreference
.battle_style
= relation(MoveBattleStyle
, backref
='nature_preferences')
1613 NaturePokeathlonStat
.pokeathlon_stat
= relation(PokeathlonStat
, backref
='nature_effects')
1615 Pokedex
.region
= relation(Region
, backref
='pokedexes')
1616 Pokedex
.version_groups
= relation(VersionGroup
, order_by
=VersionGroup
.id, back_populates
='pokedex')
1618 Pokemon
.all_abilities
= relation(Ability
,
1619 secondary
=PokemonAbility
.__table__
,
1620 order_by
=PokemonAbility
.slot
,
1622 Pokemon
.abilities
= relation(Ability
,
1623 secondary
=PokemonAbility
.__table__
,
1625 Pokemon
.id == PokemonAbility
.pokemon_id
,
1626 PokemonAbility
.is_dream
== False,
1628 order_by
=PokemonAbility
.slot
,
1630 Pokemon
.dream_ability
= relation(Ability
,
1631 secondary
=PokemonAbility
.__table__
,
1633 Pokemon
.id == PokemonAbility
.pokemon_id
,
1634 PokemonAbility
.is_dream
== True,
1638 Pokemon
.pokemon_color
= relation(PokemonColor
, backref
='pokemon')
1639 Pokemon
.color
= association_proxy('pokemon_color', 'name')
1640 Pokemon
.dex_numbers
= relation(PokemonDexNumber
, order_by
=PokemonDexNumber
.pokedex_id
.asc(), backref
='pokemon')
1641 Pokemon
.egg_groups
= relation(EggGroup
, secondary
=PokemonEggGroup
.__table__
,
1642 order_by
=PokemonEggGroup
.egg_group_id
,
1643 backref
=backref('pokemon', order_by
=Pokemon
.order
))
1644 Pokemon
.evolution_chain
= relation(EvolutionChain
, back_populates
='pokemon')
1645 Pokemon
.child_pokemon
= relation(Pokemon
,
1646 primaryjoin
=Pokemon
.id==PokemonEvolution
.from_pokemon_id
,
1647 secondary
=PokemonEvolution
.__table__
,
1648 secondaryjoin
=PokemonEvolution
.to_pokemon_id
==Pokemon
.id,
1649 backref
=backref('parent_pokemon', uselist
=False),
1651 Pokemon
.flavor_text
= relation(PokemonFlavorText
, order_by
=PokemonFlavorText
.version_id
.asc(), backref
='pokemon')
1652 Pokemon
.forms
= relation(PokemonForm
, primaryjoin
=Pokemon
.id==PokemonForm
.form_base_pokemon_id
,
1653 order_by
=(PokemonForm
.order
.asc(), PokemonForm
.identifier
.asc()))
1654 Pokemon
.default_form
= relation(PokemonForm
,
1655 primaryjoin
=and_(Pokemon
.id==PokemonForm
.form_base_pokemon_id
, PokemonForm
.is_default
==True),
1658 Pokemon
.pokemon_habitat
= relation(PokemonHabitat
, backref
='pokemon')
1659 Pokemon
.habitat
= association_proxy('pokemon_habitat', 'name')
1660 Pokemon
.items
= relation(PokemonItem
, backref
='pokemon')
1661 Pokemon
.generation
= relation(Generation
, backref
='pokemon')
1662 Pokemon
.shape
= relation(PokemonShape
, backref
='pokemon')
1663 Pokemon
.stats
= relation(PokemonStat
, backref
='pokemon', order_by
=PokemonStat
.stat_id
.asc())
1664 Pokemon
.types
= relation(Type
, secondary
=PokemonType
.__table__
,
1665 order_by
=PokemonType
.slot
.asc(),
1666 back_populates
='pokemon')
1668 PokemonDexNumber
.pokedex
= relation(Pokedex
)
1670 PokemonEvolution
.from_pokemon
= relation(Pokemon
,
1671 primaryjoin
=PokemonEvolution
.from_pokemon_id
==Pokemon
.id,
1672 backref
='child_evolutions',
1674 PokemonEvolution
.to_pokemon
= relation(Pokemon
,
1675 primaryjoin
=PokemonEvolution
.to_pokemon_id
==Pokemon
.id,
1676 backref
=backref('parent_evolution', uselist
=False),
1678 PokemonEvolution
.child_evolutions
= relation(PokemonEvolution
,
1679 primaryjoin
=PokemonEvolution
.from_pokemon_id
==PokemonEvolution
.to_pokemon_id
,
1680 foreign_keys
=[PokemonEvolution
.to_pokemon_id
],
1681 backref
=backref('parent_evolution',
1682 remote_side
=[PokemonEvolution
.from_pokemon_id
],
1686 PokemonEvolution
.trigger
= relation(EvolutionTrigger
, backref
='evolutions')
1687 PokemonEvolution
.trigger_item
= relation(Item
,
1688 primaryjoin
=PokemonEvolution
.trigger_item_id
==Item
.id,
1689 backref
='triggered_evolutions',
1691 PokemonEvolution
.held_item
= relation(Item
,
1692 primaryjoin
=PokemonEvolution
.held_item_id
==Item
.id,
1693 backref
='required_for_evolutions',
1695 PokemonEvolution
.location
= relation(Location
, backref
='triggered_evolutions')
1696 PokemonEvolution
.known_move
= relation(Move
, backref
='triggered_evolutions')
1697 PokemonEvolution
.party_pokemon
= relation(Pokemon
,
1698 primaryjoin
=PokemonEvolution
.party_pokemon_id
==Pokemon
.id,
1699 backref
='triggered_evolutions',
1701 PokemonEvolution
.trade_pokemon
= relation(Pokemon
,
1702 primaryjoin
=PokemonEvolution
.trade_pokemon_id
==Pokemon
.id,
1705 PokemonFlavorText
.version
= relation(Version
)
1707 PokemonForm
.form_base_pokemon
= relation(Pokemon
, primaryjoin
=PokemonForm
.form_base_pokemon_id
==Pokemon
.id)
1708 PokemonForm
.unique_pokemon
= relation(Pokemon
, backref
=backref('unique_form', uselist
=False),
1709 primaryjoin
=PokemonForm
.unique_pokemon_id
==Pokemon
.id)
1710 PokemonForm
.version_group
= relation(VersionGroup
)
1711 PokemonForm
.form_group
= association_proxy('form_base_pokemon', 'form_group')
1712 PokemonForm
.pokeathlon_stats
= relation(PokemonFormPokeathlonStat
,
1713 order_by
=PokemonFormPokeathlonStat
.pokeathlon_stat_id
,
1714 backref
='pokemon_form')
1716 PokemonFormGroup
.pokemon
= relation(Pokemon
, backref
=backref('form_group',
1719 PokemonFormPokeathlonStat
.pokeathlon_stat
= relation(PokeathlonStat
)
1721 PokemonItem
.item
= relation(Item
, backref
='pokemon')
1722 PokemonItem
.version
= relation(Version
)
1724 PokemonMove
.pokemon
= relation(Pokemon
, backref
='pokemon_moves')
1725 PokemonMove
.version_group
= relation(VersionGroup
)
1726 PokemonMove
.machine
= relation(Machine
, backref
='pokemon_moves',
1727 primaryjoin
=and_(Machine
.version_group_id
==PokemonMove
.version_group_id
,
1728 Machine
.move_id
==PokemonMove
.move_id
),
1729 foreign_keys
=[Machine
.version_group_id
, Machine
.move_id
],
1731 PokemonMove
.move
= relation(Move
, backref
='pokemon_moves')
1732 PokemonMove
.method
= relation(PokemonMoveMethod
)
1734 PokemonStat
.stat
= relation(Stat
)
1736 # This is technically a has-many; Generation.main_region_id -> Region.id
1737 Region
.generation
= relation(Generation
, uselist
=False)
1738 Region
.version_group_regions
= relation(VersionGroupRegion
, backref
='region',
1739 order_by
='VersionGroupRegion.version_group_id')
1740 Region
.version_groups
= association_proxy('version_group_regions', 'version_group')
1742 Stat
.damage_class
= relation(MoveDamageClass
, backref
='stats')
1744 StatHint
.stat
= relation(Stat
, backref
='hints')
1746 SuperContestCombo
.first
= relation(Move
, primaryjoin
=SuperContestCombo
.first_move_id
==Move
.id,
1747 backref
='super_contest_combo_first')
1748 SuperContestCombo
.second
= relation(Move
, primaryjoin
=SuperContestCombo
.second_move_id
==Move
.id,
1749 backref
='super_contest_combo_second')
1751 Type
.damage_efficacies
= relation(TypeEfficacy
,
1753 ==TypeEfficacy
.damage_type_id
,
1754 backref
='damage_type')
1755 Type
.target_efficacies
= relation(TypeEfficacy
,
1757 ==TypeEfficacy
.target_type_id
,
1758 backref
='target_type')
1760 Type
.generation
= relation(Generation
, backref
='types')
1761 Type
.damage_class
= relation(MoveDamageClass
, backref
='types')
1762 Type
.pokemon
= relation(Pokemon
, secondary
=PokemonType
.__table__
,
1763 order_by
=Pokemon
.order
,
1764 back_populates
='types')
1765 Type
.moves
= relation(Move
, back_populates
='type', order_by
=Move
.id)
1767 Version
.version_group
= relation(VersionGroup
, back_populates
='versions')
1768 Version
.generation
= association_proxy('version_group', 'generation')
1770 VersionGroup
.versions
= relation(Version
, order_by
=Version
.id, back_populates
='version_group')
1771 VersionGroup
.generation
= relation(Generation
, backref
='version_groups')
1772 VersionGroup
.version_group_regions
= relation(VersionGroupRegion
, backref
='version_group')
1773 VersionGroup
.regions
= association_proxy('version_group_regions', 'region')
1774 VersionGroup
.pokedex
= relation(Pokedex
, back_populates
='version_groups')
1778 for table
in list(table_classes
):
1779 if issubclass(table
, OfficiallyNamed
):
1781 info
=dict(description
="The name", format
='plaintext', official
=True)
1782 elif issubclass(table
, UnofficiallyNamed
):
1784 info
=dict(description
="The name", format
='plaintext', official
=False)
1787 table
.name
= cls(Unicode(class_mapper(table
).c
.identifier
.type.length
),
1788 plural
='names', nullable
=False, info
=info
)
1790 ### Add text/prose tables
1792 def makeTextTable(object_table
, name_plural
, name_singular
, columns
, lazy
):
1793 # With "Language", we'd have two language_id. So, rename one to 'lang'
1794 safe_name
= object_table
.__singlename__
1795 if safe_name
== 'language':
1798 tablename
= object_table
.__singlename__
+ '_' + name_plural
1799 singlename
= object_table
.__singlename__
+ '_' + name_singular
1801 class Strings(object):
1802 __tablename__
= tablename
1803 __singlename__
= singlename
1805 for name
, plural
, column
in columns
:
1808 table
= Table(tablename
, metadata
,
1809 Column(safe_name
+ '_id', Integer
, ForeignKey(object_table
.id),
1810 primary_key
=True, nullable
=False),
1811 Column('language_id', Integer
, ForeignKey(Language
.id),
1812 primary_key
=True, nullable
=False),
1813 *(column
for name
, plural
, column
in columns
)
1816 mapper(Strings
, table
,
1818 "object_id": synonym(safe_name
+ '_id'),
1819 "language": relation(
1821 primaryjoin
=table
.c
.language_id
== Language
.id,
1826 # The relation to the object
1827 setattr(object_table
, name_plural
, relation(
1829 primaryjoin
=(object_table
.id == Strings
.object_id
),
1831 collection_class
=attribute_mapped_collection('language'),
1834 Strings
.object = getattr(Strings
, safe_name
)
1836 # Link the tables themselves, so we can get to them
1837 Strings
.object_table
= object_table
1838 setattr(object_table
, name_singular
+ '_table', Strings
)
1840 for colname
, pluralname
, column
in columns
:
1841 # Provide a relation with all the names, and an English accessor
1842 # for backwards compatibility
1843 def scope(colname
, pluralname
, column
):
1844 def get_strings(self
):
1846 (l
, getattr(t
, colname
))
1847 for l
, t
in getattr(self
, name_plural
).items()
1850 def get_english_string(self
):
1852 return get_strings(self
)['en']
1854 raise AttributeError(colname
)
1856 setattr(object_table
, pluralname
, property(get_strings
))
1857 setattr(object_table
, colname
, property(get_english_string
))
1858 scope(colname
, pluralname
, column
)
1860 if colname
== 'name':
1861 object_table
.name_table
= Strings
1865 for table
in list(table_classes
):
1866 # Find all the language-specific columns, keeping them in the order they
1869 for colname
in dir(table
):
1870 column
= getattr(table
, colname
)
1871 if isinstance(column
, LanguageSpecificColumn
):
1872 all_columns
.append((colname
, column
))
1873 all_columns
.sort(key
=lambda pair
: pair
[1].order
)
1875 # Break them into text and prose columns
1878 for colname
, column
in all_columns
:
1879 spec
= colname
, column
.plural
, column
.makeSAColumn()
1880 if isinstance(column
, TextColumn
):
1881 text_columns
.append(spec
)
1882 elif isinstance(column
, ProseColumn
):
1883 prose_columns
.append(spec
)
1885 if (text_columns
or prose_columns
) and issubclass(table
, LanguageSpecific
):
1886 raise AssertionError("Language-specific table %s shouldn't have explicit language-specific columns" % table
)
1889 string_table
= makeTextTable(table
, 'texts', 'text', text_columns
, lazy
=False)
1891 string_table
= makeTextTable(table
, 'prose', 'prose', prose_columns
, lazy
=True)
1893 ### Add language relations
1894 for table
in list(table_classes
):
1895 if issubclass(table
, LanguageSpecific
):
1896 table
.language
= relation(Language
, primaryjoin
=table
.language_id
== Language
.id)