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
)
142 def command_reindex(*args
):
143 parser
= get_parser(verbose
=True)
144 options
, _
= parser
.parse_args(list(args
))
146 session
= get_session(options
)
147 lookup
= get_lookup(options
, session
=session
, recreate
=True)
149 print "Recreated lookup index."
152 def command_setup(*args
):
153 parser
= get_parser(verbose
=False)
154 options
, _
= parser
.parse_args(list(args
))
156 options
.directory
= None
158 session
= get_session(options
)
159 get_csv_directory(options
)
160 pokedex
.db
.load
.load(session
, directory
=None, drop_tables
=True,
161 verbose
=options
.verbose
)
163 lookup
= get_lookup(options
, session
=session
, recreate
=True)
165 print "Recreated lookup index."
168 def command_status(*args
):
169 parser
= get_parser(verbose
=True)
170 options
, _
= parser
.parse_args(list(args
))
171 options
.verbose
= True
172 options
.directory
= None
174 # Database, and a lame check for whether it's been inited at least once
175 session
= get_session(options
)
176 print " - OK! Connected successfully."
178 if pokedex
.db
.tables
.Pokemon
.__table__
.exists(session
.bind
):
179 print " - OK! Database seems to contain some data."
181 print " - WARNING: Database appears to be empty."
183 # CSV; simple checks that the dir exists
184 csvdir
= get_csv_directory(options
)
185 if not os
.path
.exists(csvdir
):
186 print " - ERROR: No such directory!"
187 elif not os
.path
.isdir(csvdir
):
188 print " - ERROR: Not a directory!"
190 print " - OK! Directory exists."
192 if os
.access(csvdir
, os
.R_OK
):
193 print " - OK! Can read from directory."
195 print " - ERROR: Can't read from directory!"
197 if os
.access(csvdir
, os
.W_OK
):
198 print " - OK! Can write to directory."
200 print " - WARNING: Can't write to directory! " \
201 "`dump` will not work. You may need to sudo."
203 # Index; the PokedexLookup constructor covers most tests and will
204 # cheerfully bomb if they fail
205 lookup
= get_lookup(options
, recreate
=False)
206 print " - OK! Opened successfully."
209 ### User-facing commands
211 def command_lookup(*args
):
212 parser
= get_parser(verbose
=False)
213 options
, words
= parser
.parse_args(list(args
))
215 name
= u
' '.join(words
)
217 session
= get_session(options
)
218 lookup
= get_lookup(options
, session
=session
, recreate
=False)
220 results
= lookup
.lookup(name
)
223 elif results
[0].exact
:
226 print "Fuzzy-matched:"
228 for result
in results
:
229 if hasattr(result
.object, 'full_name'):
230 name
= result
.object.full_name
232 name
= result
.object.name
234 print "%s: %s" %
(result
.object.__tablename__
, name
),
236 print "(%s in %s)" %
(result
.name
, result
.language
)
242 print u
"""pokedex -- a command-line Pokédex interface
243 usage: pokedex {command} [options...]
244 Run `pokedex setup` first, or nothing will work!
245 See http://bugs.veekun.com/projects/pokedex/wiki/CLI for more documentation.
248 help Displays this message.
249 lookup [thing] Look up something in the Pokédex.
252 load Load Pokédex data into a database from CSV files.
253 dump Dump Pokédex data from a database into CSV files.
254 reindex Rebuilds the lookup index from the database.
255 setup Combines load and reindex.
256 status No effect, but prints which engine, index, and csv
257 directory would be used for other commands.
260 -e|--engine=URI By default, all commands try to use a SQLite database
261 in the pokedex install directory. Use this option (or
262 a POKEDEX_DB_ENGINE environment variable) to specify an
264 -i|--index=DIR By default, all commands try to put the lookup index in
265 the pokedex install directory. Use this option (or a
266 POKEDEX_INDEX_DIR environment variable) to specify an
268 -q|--quiet Don't print system output. This is the default for
269 non-system commands and setup.
270 -v|--verbose Print system output. This is the default for system
271 commands, except setup.
274 -d|--directory=DIR By default, load and dump will use the CSV files in the
275 pokedex install directory. Use this option to specify
276 a different directory.
277 -D|--drop-tables With load, drop all tables before loading data.
279 Additionally, load and dump accept a list of table names (possibly with
280 wildcards) and/or csv fileames as an argument list.
281 """.encode(sys
.getdefaultencoding(), 'replace')