ab5e6b81ead5be32373057c509989eb0efa3b1fe
1 """Provides simple functions for common queries
3 These include identifier- and name-based lookup, filtering out base forms
4 of pokemon, ordering by name, and getting canonical "pokedex" lists (i.e.
5 ordered and without cruft like alternate pokemon forms or Shadow moves)
8 from sqlalchemy
.orm
import aliased
10 from pokedex
.db
import tables
14 def get(session
, table
, identifier
=None, name
=None, id=None,
15 form_identifier
=None, form_name
=None, language
=None, is_pokemon
=None):
16 """Get one object from the database.
18 session: The session to use (from pokedex.db.connect())
19 table: The table to select from (such as pokedex.db.tables.Move)
21 identifier: Identifier of the object
22 name: The name of the object
23 id: The ID number of the object
24 form_identifier: For pokemon, identifier of the form
25 form_name: For pokemon, name of the form
27 language: A Language to use for name and form_name
28 is_pokemon: If true, specifies that the table should be treated as a
29 pokemon table (handling forms specially). If None and table is the
30 (unaliased) Pokemon, it is set to True. Otherwise, the pokemon forms
33 All conditions must match, so it's not a good idea to specify more than one
34 of identifier/name/id at once.
36 If zero or more than one objects matching the criteria are found, the
37 appropriate SQLAlchemy exception is raised.
38 Exception: for pokemon, selects the form base unless form_* is given.
41 if is_pokemon
is None:
42 is_pokemon
= (table
is tables
.Pokemon
)
44 query
= session
.query(table
)
46 if identifier
is not None:
47 query
= query
.filter_by(identifier
=identifier
)
50 query
= filter_name(query
, table
, name
, language
)
53 query
= query
.filter_by(id=id)
55 if form_identifier
is not None or form_name
is not None:
57 query
= query
.join(table
.unique_form
)
58 if form_identifier
is not None:
59 query
= query
.filter(tables
.PokemonForm
.identifier
==
61 if form_name
is not None:
62 query
= filter_name(query
, table
, form_name
, language
)
65 "form_identifier and form_name only make sense for pokemon")
67 query
= filter_base_forms(query
)
73 def filter_name(query
, table
, name
, language
):
74 """Filter a query by name, return the resulting query
76 query: The query to filter
77 table: The table of named objects
78 name: The name to look for. May be a tuple of alternatives.
79 language: The language for "name", or None for the session default
82 query
= query
.filter(table
.name
== name
)
84 names_table
= table
.names_table
85 query
= query
.join(names_table
)
86 query
= query
.filter(names_table
.foreign_id
== table
.id)
87 query
= query
.filter(names_table
.local_language_id
== language
.id)
88 if isinstance(name
, tuple):
89 query
= query
.filter(names_table
.name
in name
)
91 query
= query
.filter(names_table
.name
== name
)
94 def filter_base_forms(query
):
95 """Filter only base forms of pokemon, and return the resulting query
97 query
= query
.filter(tables
.Pokemon
.forms
.any())
100 def order_by_name(query
, table
, language
=None, *extra_languages
):
101 """Order a query by name.
103 query: The query to order
104 table: Table of the named objects
105 language: The language to order names by. If None, use the
107 extra_languages: Extra languages to order by, should the translations for
108 `language` be incomplete (or ambiguous).
110 Uses the identifier as a fallback ordering.
113 query
= query
.outerjoin(table
.names_local
)
114 query
= query
.order_by(table
.names_table
.name
)
116 extra_languages
= (language
, ) + extra_languages
117 for language
in extra_languages
:
118 names_table
= aliased(table
.names_table
)
119 query
= query
.outerjoin(names_table
)
120 query
= query
.filter(names_table
.foreign_id
== table
.id)
121 query
= query
.filter(names_table
.local_language_id
== language
.id)
122 query
= query
.order_by(names_table
.name
)
123 query
= query
.order_by(table
.identifier
)
127 def get_all(session
, table
, order
=_name
):
128 """Shortcut to get an ordered query from table.
130 session: The session to use
131 table: The table to select from
132 order: A clause to order by, or None for no ordering.
133 The default is to order by name; this can also be specified explicitly
134 with the table's name property (e.g. tables.Pokemon.name). Be aware
135 that the query's order_by will not order by name this way.
137 query
= session
.query(table
)
138 if order
is table
.name
or order
is _name
:
139 query
= order_by_name(query
, table
)
140 elif order
is not None:
141 query
= query
.order_by(order
)
146 def pokemon(session
, order
=tables
.Pokemon
.id):
147 """Return a query for all base form pokemon, ordered by id by default
149 See get_all for the session and order arguments (but note the default for
150 pokemon is to order by id).
152 query
= get_all(session
, tables
.Pokemon
, order
=order
)
153 query
= query
.filter(tables
.Pokemon
.forms
.any())
156 def moves(session
, order
=_name
):
157 """Return a query for moves in the mainline games (i.e. no Shadow moves)
159 See get_all for the session and order arguments.
161 return get_all(session
, tables
.Move
, order
=order
).filter(tables
.Move
.id < 10000)
163 def types(session
, order
=_name
):
164 """Return a query for sane types (i.e. not ???, Shadow)
166 See get_all for the session and order arguments.
168 return get_all(session
, tables
.Type
, order
=order
).filter(tables
.Type
.id < 10000)
170 def items(session
, order
=_name
):
171 """Return a query for items
173 See get_all for the session and order arguments.
175 return get_all(session
, tables
.Item
, order
=order
)