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 parser
.add_option('-S', '--safe', dest
='safe', default
=False, action
='store_true',
126 help="Do not use backend-specific optimalizations.")
127 options
, tables
= parser
.parse_args(list(args
))
129 if not options
.engine_uri
:
130 print "WARNING: You're reloading the default database, but not the lookup index. They"
131 print " might get out of sync, and pokedex commands may not work correctly!"
132 print "To fix this, run `pokedex reindex` when this command finishes. Or, just use"
133 print "`pokedex setup` to do both at once."
136 session
= get_session(options
)
137 get_csv_directory(options
)
139 pokedex
.db
.load
.load(session
, directory
=options
.directory
,
140 drop_tables
=options
.drop_tables
,
142 verbose
=options
.verbose
,
145 def command_reindex(*args
):
146 parser
= get_parser(verbose
=True)
147 options
, _
= parser
.parse_args(list(args
))
149 session
= get_session(options
)
150 lookup
= get_lookup(options
, session
=session
, recreate
=True)
152 print "Recreated lookup index."
155 def command_setup(*args
):
156 parser
= get_parser(verbose
=False)
157 options
, _
= parser
.parse_args(list(args
))
159 options
.directory
= None
161 session
= get_session(options
)
162 get_csv_directory(options
)
163 pokedex
.db
.load
.load(session
, directory
=None, drop_tables
=True,
164 verbose
=options
.verbose
,
167 lookup
= get_lookup(options
, session
=session
, recreate
=True)
169 print "Recreated lookup index."
172 def command_status(*args
):
173 parser
= get_parser(verbose
=True)
174 options
, _
= parser
.parse_args(list(args
))
175 options
.verbose
= True
176 options
.directory
= None
178 # Database, and a lame check for whether it's been inited at least once
179 session
= get_session(options
)
180 print " - OK! Connected successfully."
182 if pokedex
.db
.tables
.Pokemon
.__table__
.exists(session
.bind
):
183 print " - OK! Database seems to contain some data."
185 print " - WARNING: Database appears to be empty."
187 # CSV; simple checks that the dir exists
188 csvdir
= get_csv_directory(options
)
189 if not os
.path
.exists(csvdir
):
190 print " - ERROR: No such directory!"
191 elif not os
.path
.isdir(csvdir
):
192 print " - ERROR: Not a directory!"
194 print " - OK! Directory exists."
196 if os
.access(csvdir
, os
.R_OK
):
197 print " - OK! Can read from directory."
199 print " - ERROR: Can't read from directory!"
201 if os
.access(csvdir
, os
.W_OK
):
202 print " - OK! Can write to directory."
204 print " - WARNING: Can't write to directory! " \
205 "`dump` will not work. You may need to sudo."
207 # Index; the PokedexLookup constructor covers most tests and will
208 # cheerfully bomb if they fail
209 lookup
= get_lookup(options
, recreate
=False)
210 print " - OK! Opened successfully."
213 ### User-facing commands
215 def command_lookup(*args
):
216 parser
= get_parser(verbose
=False)
217 options
, words
= parser
.parse_args(list(args
))
219 name
= u
' '.join(words
)
221 session
= get_session(options
)
222 lookup
= get_lookup(options
, session
=session
, recreate
=False)
224 results
= lookup
.lookup(name
)
227 elif results
[0].exact
:
230 print "Fuzzy-matched:"
232 for result
in results
:
233 if hasattr(result
.object, 'full_name'):
234 name
= result
.object.full_name
236 name
= result
.object.name
238 print "%s: %s" %
(result
.object.__tablename__
, name
),
240 print "(%s in %s)" %
(result
.name
, result
.language
)
246 print u
"""pokedex -- a command-line Pokédex interface
247 usage: pokedex {command} [options...]
248 Run `pokedex setup` first, or nothing will work!
249 See http://bugs.veekun.com/projects/pokedex/wiki/CLI for more documentation.
252 help Displays this message.
253 lookup [thing] Look up something in the Pokédex.
256 load Load Pokédex data into a database from CSV files.
257 dump Dump Pokédex data from a database into CSV files.
258 reindex Rebuilds the lookup index from the database.
259 setup Combines load and reindex.
260 status No effect, but prints which engine, index, and csv
261 directory would be used for other commands.
264 -e|--engine=URI By default, all commands try to use a SQLite database
265 in the pokedex install directory. Use this option (or
266 a POKEDEX_DB_ENGINE environment variable) to specify an
268 -i|--index=DIR By default, all commands try to put the lookup index in
269 the pokedex install directory. Use this option (or a
270 POKEDEX_INDEX_DIR environment variable) to specify an
272 -q|--quiet Don't print system output. This is the default for
273 non-system commands and setup.
274 -v|--verbose Print system output. This is the default for system
275 commands, except setup.
278 -d|--directory=DIR By default, load and dump will use the CSV files in the
279 pokedex install directory. Use this option to specify
280 a different directory.
281 -D|--drop-tables With load, drop all tables before loading data.
283 Additionally, load and dump accept a list of table names (possibly with
284 wildcards) and/or csv fileames as an argument list.
285 """.encode(sys
.getdefaultencoding(), 'replace')