Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Pass database object to all the commands. |
---|---|
Timelines: | family | ancestors | descendants | both | dev |
Files: | files | file ages | folders |
SHA1: |
1a510a86e620067e9be65e612d2ad7f6 |
User & Date: | mvnathan 2014-09-19 04:57:48.639 |
Context
2014-09-19
| ||
07:28 | Generalized Morg so it's no longer task-specific. Rather, it aspires to be a general hierarchical list manager and, by default, its predefined properties set it up to manage shopping lists and TODO lists. check-in: d74ecb0949 user: mvnathan tags: dev | |
04:57 | Pass database object to all the commands. check-in: 1a510a86e6 user: mvnathan tags: dev | |
04:20 | Updated documentation about watermarking. check-in: ea1817df1f user: mvnathan tags: dev | |
Changes
Changes to py/morg.py.
︙ | ︙ | |||
86 87 88 89 90 91 92 | try: args = morglib.args.parse(sys.argv[1:], str(version())) morglib.log.init(args.debug_level, args.log_file) logger.info('starting Morg') morglib.args.dump(args) logger.info('opening database {}'.format(args.tasks_file)) | | | | | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | try: args = morglib.args.parse(sys.argv[1:], str(version())) morglib.log.init(args.debug_level, args.log_file) logger.info('starting Morg') morglib.args.dump(args) logger.info('opening database {}'.format(args.tasks_file)) db = morglib.db(args.tasks_file, morglib.properties.defaults) if (args.command): morglib.interpreter.execute(args.command[0], args.command, db) else: morglib.command.repl(morglib.interpreter, db) except morglib.args.args_error, e: sys.stderr.write('{}: {}\n'. format(os.path.basename(sys.argv[0]), e)) sys.exit(2) except morglib.error, e: |
︙ | ︙ |
Changes to py/morglib/__init__.py.
︙ | ︙ | |||
50 51 52 53 54 55 56 | importlib.import_module(full_name) # Pull in exception base class and alias it so clients can use it simply # as morglib.error instead of the fully qualified and hideously verbose # form morglib.morg_error.error_base, which is quite a handful. from morg_error import error_base as error | | | | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | importlib.import_module(full_name) # Pull in exception base class and alias it so clients can use it simply # as morglib.error instead of the fully qualified and hideously verbose # form morglib.morg_error.error_base, which is quite a handful. from morg_error import error_base as error # Expose morglib.database.database simply as morglib.db from database import database as db #------------------------------- EXPORTS -------------------------------- __all__ = ['args', 'command', 'database', 'log', |
︙ | ︙ |
Changes to py/morglib/command.py.
︙ | ︙ | |||
56 57 58 59 60 61 62 63 64 65 66 | All Morg commands should derive from this class and implement the <tt>__call__</tt> method, which will be passed a list of strings containing the command-line used to invoke that command. The first member of this list will be the command name itself; the remaining elements are the command-line arguments. To automate help processing, each command should be able to handle a <tt>--help</tt> option. ''' | > > > > | > | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | All Morg commands should derive from this class and implement the <tt>__call__</tt> method, which will be passed a list of strings containing the command-line used to invoke that command. The first member of this list will be the command name itself; the remaining elements are the command-line arguments. In addition to the command-line arguments, each command's <tt>__call__</tt> method will receive a database object, which it can use to search and/or manipulate the tasks database as required. To automate help processing, each command should be able to handle a <tt>--help</tt> option. ''' def __call__(self, argv, db): '''Execute command. @param argv (string list) Arguments provided via command-line. @param db (morglib.database) Interface object for tasks database. The call method acts as the means to execute commands. In this base class, we simply raise an exception to indicate that a subclass has failed to implement the desired functionality. ''' raise unimplemented_cmd(argv[0]) |
︙ | ︙ | |||
138 139 140 141 142 143 144 | '''Return an iterator over the keys.''' return self._dispatch_table.iterkeys() def iteritems(self): '''Return an iterator over the key-value pairs.''' return self._dispatch_table.iteritems() | | > | | | 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | '''Return an iterator over the keys.''' return self._dispatch_table.iterkeys() def iteritems(self): '''Return an iterator over the key-value pairs.''' return self._dispatch_table.iteritems() def execute(self, key, args, db): '''Execute specified command. @param key (string) Command name. @param args (string list) Command-line arguments. @param db (morglib.database) Tasks database interface object. ''' try: logger.debug('executing command: {}'.format(args)) f = self[key] f(args, db) except KeyError: logger.debug('unable to find command {}'.format(key)) potential_completions = filter(lambda k: k.startswith(key), self._dispatch_table) n = len(potential_completions) logger.debug('found {} potential completions'.format(n)) if (n <= 0): raise unknown_cmd(key) elif (n == 1): k = potential_completions[0] f = self[k] logger.debug('{} is a unique prefix for {}'.format(key, k)) args = [k] + args[1:] f(args, db) else: raise ambiguous_prefix(key, potential_completions) class unknown_cmd(morg_error.error_base): '''For reporting unknown commands.''' def __str__(self): return '{}: no such command'.format(self.message) |
︙ | ︙ | |||
188 189 190 191 192 193 194 | '''Interactive mode's main loop. This class implements a read-eval-print loop (i.e., a REPL) so that users can interact with Morg beyond the "one-liner" permitted by the invocation via command-line arguments. ''' | | > > > > > > > | 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | '''Interactive mode's main loop. This class implements a read-eval-print loop (i.e., a REPL) so that users can interact with Morg beyond the "one-liner" permitted by the invocation via command-line arguments. ''' def __init__(self, interpreter, db): '''Construct repl object. @param interpreter (dispatcher) For executing Morg commands. @param db (morglib.database) To pass to command objects. When instantiating the <tt>repl</tt> class, you should supply it with the <tt>morglib.interpreter</tt> so that this object knows how to interpret and execute the commands it receives interactively. Additionally, all Morg command objects have to be passed the tasks database so they can operate on it as required. Thus, you should also pass the database's interface object to this constructor. ''' cmd.Cmd.__init__(self) self.prompt = 'morg> ' self._interpreter = interpreter self._db = db # Helper function object to call the _dispatch_cmd() method, # passing it the command name plus the input line. class _dispatch: def __init__(self, cmd_name, repl_obj): self._cmd = cmd_name self._repl = repl_obj |
︙ | ︙ | |||
245 246 247 248 249 250 251 | simply splits the input line using shell-like syntax and then uses the morglib interpreter to execute the command. ''' try: args = shlex.split(line) if (args): | | | 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | simply splits the input line using shell-like syntax and then uses the morglib interpreter to execute the command. ''' try: args = shlex.split(line) if (args): self._interpreter.execute(args[0], args, self._db) except morg_error.error_base, e: logger.error(e) sys.stderr.write('{}\n'.format(e)) def default(self, line): '''How to deal with unrecognized input. |
︙ | ︙ |
Changes to py/morglib/exit.py.
︙ | ︙ | |||
36 37 38 39 40 41 42 | # Standard library import sys #---------------------------- EXIT COMMANDS ----------------------------- class exit(command.base): '''Command to exit Morg.''' | | > | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | # Standard library import sys #---------------------------- EXIT COMMANDS ----------------------------- class exit(command.base): '''Command to exit Morg.''' def __call__(self, argv, db): '''Execute exit command. @param argv (string list) Exit command-line. @param db (morglib.database) Tasks database. ''' if (len(argv) > 1 and argv[1] in ['-h', '--help']): print(_help()) else: sys.exit(0) |
︙ | ︙ |
Changes to py/morglib/help.py.
︙ | ︙ | |||
44 45 46 47 48 49 50 | #---------------------------- HELP COMMAND ------------------------------ class help(command.base): '''Command for printing help about other commands.''' def __init__(self): self._help = None | | > | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | #---------------------------- HELP COMMAND ------------------------------ class help(command.base): '''Command for printing help about other commands.''' def __init__(self): self._help = None def __call__(self, argv, db): '''Execute help command. @param argv (string list) Help command-line. @param db (morglib.database) Tasks database. Without any parameters, prints the list of available commands and some general comments. With a parameter, executes the specified command, passing it the --help option. Thus, all commands should implement --help to be able to print something useful when the user asks for help. |
︙ | ︙ | |||
73 74 75 76 77 78 79 | if (kmd.startswith('-')): # ignore any command-line options kmd = 'help' if (kmd is 'help'): if (self._help is None): self._help = _cache_help_text() print(self._help) else: | | | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | if (kmd.startswith('-')): # ignore any command-line options kmd = 'help' if (kmd is 'help'): if (self._help is None): self._help = _cache_help_text() print(self._help) else: morglib.interpreter.execute(kmd, [kmd, '--help'], db) def _cache_help_text(): prolog = 'The following commands are available:' commands = [] for k, c in morglib.interpreter.iteritems(): |
︙ | ︙ |
Changes to wiki/todo.wiki.
︙ | ︙ | |||
19 20 21 22 23 24 25 26 27 28 | * Create <tt>property_NNN</tt> tables on database init. * Implement sanity check on database initialization. * Update database constructor doc string. * Use the BETWEEN operator in property range constraints. * Implement a watermark class to ease verification and "Morgification." * The watermark table should be created and populated in a transaction. * Update doc strings to reflect recent changes about the watermark. <h2>PENDING</h2> | > < | 19 20 21 22 23 24 25 26 27 28 29 30 | * Create <tt>property_NNN</tt> tables on database init. * Implement sanity check on database initialization. * Update database constructor doc string. * Use the BETWEEN operator in property range constraints. * Implement a watermark class to ease verification and "Morgification." * The watermark table should be created and populated in a transaction. * Update doc strings to reflect recent changes about the watermark. * Pass database to all commands' <tt>__call__</tt> method. <h2>PENDING</h2> * Implement <tt>new</tt> command. |