Mercurial > piecrust2
comparison piecrust/commands/base.py @ 3:f485ba500df3
Gigantic change to basically make PieCrust 2 vaguely functional.
- Serving works, with debug window.
- Baking works, multi-threading, with dependency handling.
- Various things not implemented yet.
| author | Ludovic Chabant <ludovic@chabant.com> |
|---|---|
| date | Sun, 10 Aug 2014 23:43:16 -0700 |
| parents | aaa8fb7c8918 |
| children | c8c522dacfea |
comparison
equal
deleted
inserted
replaced
| 2:40fa08b261b9 | 3:f485ba500df3 |
|---|---|
| 1 import logging | 1 import logging |
| 2 import functools | |
| 2 from piecrust.pathutil import SiteNotFoundError | 3 from piecrust.pathutil import SiteNotFoundError |
| 3 | 4 |
| 4 | 5 |
| 5 logger = logging.getLogger(__name__) | 6 logger = logging.getLogger(__name__) |
| 6 | 7 |
| 7 | 8 |
| 8 class CommandContext(object): | 9 class CommandContext(object): |
| 9 def __init__(self, app, args): | 10 def __init__(self, app, args): |
| 10 self.app = app | 11 self.app = app |
| 11 self.args = args | 12 self.args = args |
| 13 self.result = 0 | |
| 12 | 14 |
| 13 | 15 |
| 14 class ChefCommand(object): | 16 class ChefCommand(object): |
| 15 def __init__(self): | 17 def __init__(self): |
| 16 self.name = '__unknown__' | 18 self.name = '__unknown__' |
| 17 self.description = '__unknown__' | 19 self.description = '__unknown__' |
| 18 self.requires_website = True | 20 self.requires_website = True |
| 19 | 21 |
| 20 def setupParser(self, parser): | 22 def setupParser(self, parser, app): |
| 21 raise NotImplementedError() | 23 raise NotImplementedError() |
| 22 | 24 |
| 23 def run(self, ctx): | 25 def run(self, ctx): |
| 24 raise NotImplementedError() | 26 raise NotImplementedError() |
| 25 | 27 |
| 26 def _runFromChef(self, app, res): | 28 def _runFromChef(self, app, res): |
| 27 if app.root is None and self.requires_website: | 29 if app.root_dir is None and self.requires_website: |
| 28 raise SiteNotFoundError() | 30 raise SiteNotFoundError() |
| 29 self.run(CommandContext(app, res)) | 31 ctx = CommandContext(app, res) |
| 32 self.run(ctx) | |
| 33 return ctx.result | |
| 30 | 34 |
| 35 | |
| 36 class ExtendableChefCommand(ChefCommand): | |
| 37 def __init__(self): | |
| 38 super(ExtendableChefCommand, self).__init__() | |
| 39 self._extensions = None | |
| 40 | |
| 41 def setupParser(self, parser, app): | |
| 42 self._loadExtensions(app) | |
| 43 subparsers = parser.add_subparsers() | |
| 44 for e in self._extensions: | |
| 45 p = subparsers.add_parser(e.name, help=e.description) | |
| 46 e.setupParser(p, app) | |
| 47 p.set_defaults(func=e._runFromChef) | |
| 48 | |
| 49 def _loadExtensions(self, app): | |
| 50 if self._extensions is not None: | |
| 51 return | |
| 52 self._extensions = [] | |
| 53 for e in app.plugin_loader.getCommandExtensions(): | |
| 54 if e.command_name == self.name and e.supports(app): | |
| 55 self._extensions.append(e) | |
| 56 | |
| 57 | |
| 58 class ChefCommandExtension(ChefCommand): | |
| 59 def __init__(self): | |
| 60 super(ChefCommandExtension, self).__init__() | |
| 61 self.command_name = '__unknown__' | |
| 62 | |
| 63 def supports(self, app): | |
| 64 return True | |
| 65 | |
| 66 | |
| 67 class _WrappedCommand(ChefCommand): | |
| 68 def __init__(self, func, name, description): | |
| 69 super(_WrappedCommand, self).__init__() | |
| 70 self.func = func | |
| 71 self.name = name | |
| 72 self.description = description | |
| 73 | |
| 74 def run(self, ctx): | |
| 75 self.func(ctx) | |
| 76 | |
| 77 | |
| 78 def simple_command(f, name, description=None): | |
| 79 @functools.wraps(f) | |
| 80 def wrapper(*args, **kwargs): | |
| 81 return f(*args, **kwargs) | |
| 82 cmd = _WrappedCommand(f, name, description) | |
| 83 f.__command_class__ = cmd | |
| 84 return wrapper | |
| 85 | |
| 86 | |
| 87 def get_func_command(f): | |
| 88 return getattr(f, '__command_class__') | |
| 89 |
