2 from optparse
import OptionParser
6 # XXX importing pokedex.whatever should not import all these
9 import pokedex
.db
.tables
11 from pokedex
import defaults
14 if len(sys
.argv
) <= 1:
20 # XXX there must be a better way to get Unicode argv
21 # XXX this doesn't work on Windows durp
22 enc
= sys
.stdin
.encoding
or 'utf8'
23 args
= [_
.decode(enc
) for _
in args
]
25 # Find the command as a function in this file
26 func
= globals().get("command_%s" % command
, None)
33 def get_parser(verbose
=True):
34 """Returns an OptionParser prepopulated with the global options.
36 `verbose` is whether or not the options should be verbose by default.
38 parser
= OptionParser()
39 parser
.add_option('-e', '--engine', dest
='engine_uri', default
=None)
40 parser
.add_option('-i', '--index', dest
='index_dir', default
=None)
41 parser
.add_option('-q', '--quiet', dest
='verbose', default
=verbose
, action
='store_false')
42 parser
.add_option('-v', '--verbose', dest
='verbose', default
=verbose
, action
='store_true')
45 def get_session(options
):
46 """Given a parsed options object, connects to the database and returns a
50 engine_uri
= options
.engine_uri
51 got_from
= 'command line'
53 if engine_uri
is None:
54 engine_uri
, got_from
= defaults
.get_default_db_uri_with_origin()
56 session
= pokedex
.db
.connect(engine_uri
)
59 print "Connected to database %(engine)s (from %(got_from)s)" \
60 % dict
(engine
=session
.bind
.url
, got_from
=got_from
)
64 def get_lookup(options
, session
=None, recreate
=False):
65 """Given a parsed options object, opens the whoosh index and returns a
69 if recreate
and not session
:
70 raise ValueError("get_lookup() needs an explicit session to regen the index")
72 index_dir
= options
.index_dir
73 got_from
= 'command line'
76 index_dir
, got_from
= defaults
.get_default_index_dir_with_origin()
79 print "Opened lookup index %(index_dir)s (from %(got_from)s)" \
80 % dict
(index_dir
=index_dir
, got_from
=got_from
)
82 lookup
= pokedex
.lookup
.PokedexLookup(index_dir
, session
=session
)
85 lookup
.rebuild_index()
89 def get_csv_directory(options
):
90 """Prints and returns the csv directory we're about to use."""
92 if not options
.verbose
:
95 csvdir
= options
.directory
96 got_from
= 'command line'
99 csvdir
, got_from
= defaults
.get_default_csv_dir_with_origin()
101 print "Using CSV directory %(csvdir)s (from %(got_from)s)" \
102 % dict
(csvdir
=csvdir
, got_from
=got_from
)
107 ### Plumbing commands
109 def command_dump(*args
):
110 parser
= get_parser(verbose
=True)
111 parser
.add_option('-d', '--directory', dest
='directory', default
=None)
112 options
, tables
= parser
.parse_args(list(args
))
114 session
= get_session(options
)
115 get_csv_directory(options
)
117 pokedex
.db
.load
.dump(session
, directory
=options
.directory
,
119 verbose
=options
.verbose
)
121 def command_load(*args
):
122 parser
= get_parser(verbose
=True)
123 parser
.add_option('-d', '--directory', dest
='directory', default
=None)
124 parser
.add_option('-D', '--drop-tables', dest
='drop_tables', default
=False, action
='store_true')
125 options
, tables
= parser
.parse_args(list(args
))
127 if not options
.engine_uri
:
128 print "WARNING: You're reloading the default database, but not the lookup index. They"
129 print " might get out of sync, and pokedex commands may not work correctly!"
130 print "To fix this, run `pokedex reindex` when this command finishes. Or, just use"
131 print "`pokedex setup` to do both at once."
134 session
= get_session(options
)
135 get_csv_directory(options
)
137 pokedex
.db
.load
.load(session
, directory
=options
.directory
,
138 drop_tables
=options
.drop_tables
,
140 verbose
=options
.verbose
,
143 def command_reindex(*args
):
144 parser
= get_parser(verbose
=True)
145 options
, _
= parser
.parse_args(list(args
))
147 session
= get_session(options
)
148 lookup
= get_lookup(options
, session
=session
, recreate
=True)
150 print "Recreated lookup index."
153 def command_setup(*args
):
154 parser
= get_parser(verbose
=False)
155 options
, _
= parser
.parse_args(list(args
))
157 options
.directory
= None
159 session
= get_session(options
)
160 get_csv_directory(options
)
161 pokedex
.db
.load
.load(session
, directory
=None, drop_tables
=True,
162 verbose
=options
.verbose
,
165 lookup
= get_lookup(options
, session
=session
, recreate
=True)
167 print "Recreated lookup index."
170 def command_status(*args
):
171 parser
= get_parser(verbose
=True)
172 options
, _
= parser
.parse_args(list(args
))
173 options
.verbose
= True
174 options
.directory
= None
176 # Database, and a lame check for whether it's been inited at least once
177 session
= get_session(options
)
178 print " - OK! Connected successfully."
180 if pokedex
.db
.tables
.Pokemon
.__table__
.exists(session
.bind
):
181 print " - OK! Database seems to contain some data."
183 print " - WARNING: Database appears to be empty."
185 # CSV; simple checks that the dir exists
186 csvdir
= get_csv_directory(options
)
187 if not os
.path
.exists(csvdir
):
188 print " - ERROR: No such directory!"
189 elif not os
.path
.isdir(csvdir
):
190 print " - ERROR: Not a directory!"
192 print " - OK! Directory exists."
194 if os
.access(csvdir
, os
.R_OK
):
195 print " - OK! Can read from directory."
197 print " - ERROR: Can't read from directory!"
199 if os
.access(csvdir
, os
.W_OK
):
200 print " - OK! Can write to directory."
202 print " - WARNING: Can't write to directory! " \
203 "`dump` will not work. You may need to sudo."
205 # Index; the PokedexLookup constructor covers most tests and will
206 # cheerfully bomb if they fail
207 lookup
= get_lookup(options
, recreate
=False)
208 print " - OK! Opened successfully."
211 ### User-facing commands
213 def command_lookup(*args
):
214 parser
= get_parser(verbose
=False)
215 options
, words
= parser
.parse_args(list(args
))
217 name
= u
' '.join(words
)
219 session
= get_session(options
)
220 lookup
= get_lookup(options
, session
=session
, recreate
=False)
222 results
= lookup
.lookup(name
)
225 elif results
[0].exact
:
228 print "Fuzzy-matched:"
230 for result
in results
:
231 if hasattr(result
.object, 'full_name'):
232 name
= result
.object.full_name
234 name
= result
.object.name
236 print "%s: %s" %
(result
.object.__tablename__
, name
),
238 print "(%s in %s)" %
(result
.name
, result
.language
)
244 print u
"""pokedex -- a command-line Pokédex interface
245 usage: pokedex {command} [options...]
246 Run `pokedex setup` first, or nothing will work!
247 See http://bugs.veekun.com/projects/pokedex/wiki/CLI for more documentation.
250 help Displays this message.
251 lookup [thing] Look up something in the Pokédex.
254 load Load Pokédex data into a database from CSV files.
255 dump Dump Pokédex data from a database into CSV files.
256 reindex Rebuilds the lookup index from the database.
257 setup Combines load and reindex.
258 status No effect, but prints which engine, index, and csv
259 directory would be used for other commands.
262 -e|--engine=URI By default, all commands try to use a SQLite database
263 in the pokedex install directory. Use this option (or
264 a POKEDEX_DB_ENGINE environment variable) to specify an
266 -i|--index=DIR By default, all commands try to put the lookup index in
267 the pokedex install directory. Use this option (or a
268 POKEDEX_INDEX_DIR environment variable) to specify an
270 -q|--quiet Don't print system output. This is the default for
271 non-system commands and setup.
272 -v|--verbose Print system output. This is the default for system
273 commands, except setup.
276 -d|--directory=DIR By default, load and dump will use the CSV files in the
277 pokedex install directory. Use this option to specify
278 a different directory.
279 -D|--drop-tables With load, drop all tables before loading data.
281 Additionally, load and dump accept a list of table names (possibly with
282 wildcards) and/or csv fileames as an argument list.
283 """.encode(sys
.getdefaultencoding(), 'replace')