mirror of
https://github.com/datafolklabs/cement.git
synced 2026-02-06 11:16:46 +00:00
Deprecate App.Meta.base_controller and Scrub App.Meta Options
- Resolves Issue #519 - Resolves Issue #522
This commit is contained in:
parent
18438aba81
commit
5cd8f952ec
@ -13,6 +13,7 @@ from ..core.handler import HandlerManager
|
||||
from ..core.hook import HookManager
|
||||
from ..utils.misc import is_true, minimal_logger
|
||||
from ..utils import fs, misc
|
||||
from ..ext.ext_argparse import ArgparseController as Controller
|
||||
|
||||
# The `imp` module is deprecated in favor of `importlib` in 3.4, but it
|
||||
# wasn't introduced until 3.1. Finally, reload is a builtin on Python < 3
|
||||
@ -442,17 +443,6 @@ class App(meta.MetaMixin):
|
||||
A handler class that implements the Cache interface.
|
||||
"""
|
||||
|
||||
base_controller = None
|
||||
"""
|
||||
This is the base application controller. If a controller is set,
|
||||
runtime operations are passed to the controller for command
|
||||
dispatch and argument parsing when ``App.run()`` is called.
|
||||
|
||||
Note that Cement will automatically set the ``base_controller`` to a
|
||||
registered controller whose label is ``base`` (only if
|
||||
``base_controller`` is not currently set).
|
||||
"""
|
||||
|
||||
extensions = []
|
||||
"""List of additional framework extensions to load."""
|
||||
|
||||
@ -920,7 +910,7 @@ class App(meta.MetaMixin):
|
||||
if self.controller:
|
||||
return_val = self.controller._dispatch()
|
||||
else:
|
||||
self._parse_args()
|
||||
self._parse_args() # pragma: nocover
|
||||
|
||||
LOG.debug('running post_run hook')
|
||||
for res in self.hook.run('post_run', self):
|
||||
@ -1200,20 +1190,19 @@ class App(meta.MetaMixin):
|
||||
self.catch_signal(signum)
|
||||
|
||||
def _resolve_handler(self, handler_type, handler_def, raise_error=True):
|
||||
meta_defaults = {}
|
||||
if type(handler_def) == str:
|
||||
_meta_label = "%s.%s" % (handler_type, handler_def)
|
||||
meta_defaults = self._meta.meta_defaults.get(_meta_label, {})
|
||||
elif hasattr(handler_def, 'Meta'):
|
||||
_meta_label = "%s.%s" % (handler_type, handler_def.Meta.label)
|
||||
meta_defaults = self._meta.meta_defaults.get(_meta_label, {})
|
||||
# meta_defaults = {}
|
||||
# if type(handler_def) == str:
|
||||
# _meta_label = "%s.%s" % (handler_type, handler_def)
|
||||
# meta_defaults = self._meta.meta_defaults.get(_meta_label, {})
|
||||
# elif hasattr(handler_def, 'Meta'):
|
||||
# _meta_label = "%s.%s" % (handler_type, handler_def.Meta.label)
|
||||
# meta_defaults = self._meta.meta_defaults.get(_meta_label, {})
|
||||
|
||||
han = self.handler.resolve(handler_type, handler_def,
|
||||
han = self.handler.resolve(handler_type,
|
||||
handler_def,
|
||||
raise_error=raise_error,
|
||||
meta_defaults=meta_defaults)
|
||||
if han is not None:
|
||||
han._setup(self)
|
||||
return han
|
||||
setup=True)
|
||||
return han
|
||||
|
||||
def _setup_extension_handler(self):
|
||||
LOG.debug("setting up %s.extension handler" % self._meta.label)
|
||||
@ -1527,21 +1516,22 @@ class App(meta.MetaMixin):
|
||||
def _setup_controllers(self):
|
||||
LOG.debug("setting up application controllers")
|
||||
|
||||
if self._meta.base_controller is not None:
|
||||
cntr = self._resolve_handler('controller',
|
||||
self._meta.base_controller)
|
||||
self.controller = cntr
|
||||
self._meta.base_controller = self.controller
|
||||
elif self._meta.base_controller is None:
|
||||
if self.handler.registered('controller', 'base'):
|
||||
self.controller = self._resolve_handler('controller', 'base')
|
||||
self._meta.base_controller = self.controller
|
||||
if self.handler.registered('controller', 'base'):
|
||||
self.controller = self._resolve_handler('controller', 'base')
|
||||
|
||||
# This is necessary for some backend usage
|
||||
if self._meta.base_controller is not None:
|
||||
if self._meta.base_controller._meta.label != 'base':
|
||||
raise exc.FrameworkError("Base controllers must have " +
|
||||
"a label of 'base'.")
|
||||
else:
|
||||
class DefaultBaseController(Controller):
|
||||
class Meta:
|
||||
label = 'base'
|
||||
|
||||
def _default(self):
|
||||
# don't enforce anything cause developer might not be
|
||||
# using controllers... if they are, they should define
|
||||
# a base controller.
|
||||
pass
|
||||
|
||||
self.handler.register(DefaultBaseController)
|
||||
self.controller = self._resolve_handler('controller', 'base')
|
||||
|
||||
def validate_config(self):
|
||||
"""
|
||||
@ -1702,6 +1692,5 @@ class TestApp(App):
|
||||
label = "app-%s" % misc.rando()[:12]
|
||||
config_files = []
|
||||
argv = []
|
||||
base_controller = None
|
||||
arguments = []
|
||||
exit_on_close = False
|
||||
|
||||
@ -335,7 +335,7 @@ class HandlerManager(object):
|
||||
to resolve the handler.
|
||||
meta_defaults (dict): Optional meta-data dictionary used as
|
||||
defaults to pass when instantiating uninstantiated handlers.
|
||||
See ``App.Meta.meta_defaults``.
|
||||
Use ``App.Meta.meta_defaults`` by default.
|
||||
setup (bool): Whether or not to call ``.setup()`` before return.
|
||||
Default: ``False``
|
||||
|
||||
@ -357,7 +357,18 @@ class HandlerManager(object):
|
||||
|
||||
"""
|
||||
raise_error = kwargs.get('raise_error', True)
|
||||
meta_defaults = kwargs.get('meta_defaults', {})
|
||||
meta_defaults = kwargs.get('meta_defaults', None)
|
||||
if meta_defaults is None:
|
||||
meta_defaults = {}
|
||||
if type(handler_def) == str:
|
||||
_meta_label = "%s.%s" % (interface, handler_def)
|
||||
meta_defaults = self.app._meta.meta_defaults.get(_meta_label,
|
||||
{})
|
||||
elif hasattr(handler_def, 'Meta'):
|
||||
_meta_label = "%s.%s" % (interface, handler_def.Meta.label)
|
||||
meta_defaults = self.app._meta.meta_defaults.get(_meta_label,
|
||||
{})
|
||||
|
||||
setup = kwargs.get('setup', False)
|
||||
han = None
|
||||
|
||||
|
||||
@ -339,8 +339,7 @@ class ArgparseController(ControllerHandler):
|
||||
if contr == self.__class__:
|
||||
continue
|
||||
|
||||
contr = contr()
|
||||
contr._setup(self.app)
|
||||
contr = self.app.handler.resolve('controller', contr, setup=True)
|
||||
unresolved_controllers.append(contr)
|
||||
|
||||
# treat self/base separately
|
||||
|
||||
@ -7,7 +7,7 @@ import os
|
||||
import inspect
|
||||
import yaml
|
||||
import shutil
|
||||
from .. import Controller, minimal_logger, shell, FrameworkError
|
||||
from .. import Controller, minimal_logger, shell
|
||||
from ..utils.version import VERSION, get_version
|
||||
|
||||
LOG = minimal_logger(__name__)
|
||||
@ -133,14 +133,6 @@ def setup_template_items(app):
|
||||
template_dirs = []
|
||||
template_items = []
|
||||
|
||||
# nothing will work without a base controller
|
||||
try:
|
||||
assert app._meta.base_controller is not None, \
|
||||
"The ext.generate extension requires an application base " + \
|
||||
"controller, but none is defined!"
|
||||
except AssertionError as e:
|
||||
raise FrameworkError(e.args[0])
|
||||
|
||||
# look in app template dirs
|
||||
for path in app._meta.template_dirs:
|
||||
subpath = os.path.join(path, 'generate')
|
||||
|
||||
@ -3,6 +3,7 @@ Cement scrub extension module.
|
||||
"""
|
||||
|
||||
import re
|
||||
from .. import Controller
|
||||
from ..utils.misc import minimal_logger
|
||||
|
||||
LOG = minimal_logger(__name__)
|
||||
@ -27,22 +28,39 @@ def extend_scrub(app):
|
||||
|
||||
app.extend('scrub', scrub)
|
||||
|
||||
if hasattr(app._meta, 'scrub_argument'):
|
||||
arg = app._meta.scrub_argument
|
||||
else:
|
||||
arg = ['--scrub']
|
||||
|
||||
if hasattr(app._meta, 'scrub_argument_help'):
|
||||
arg_help = app._meta.scrub_argument_help
|
||||
else:
|
||||
arg_help = 'obfuscate sensitive data from output'
|
||||
class ScrubController(Controller):
|
||||
"""
|
||||
Add embedded options to the base controller to support scrubbing output.
|
||||
"""
|
||||
|
||||
app.args.add_argument(*arg,
|
||||
help=arg_help,
|
||||
action='store_true',
|
||||
dest='scrub')
|
||||
class Meta:
|
||||
#: Controller label
|
||||
label = 'scrub'
|
||||
|
||||
#: Parent controller to stack ontop of
|
||||
stacked_on = 'base'
|
||||
|
||||
#: Stacking method
|
||||
stacked_type = 'embedded'
|
||||
|
||||
#: Command line argument options
|
||||
argument_options = ['--scrub']
|
||||
|
||||
#: Command line argument options help
|
||||
argument_help = 'obfuscate sensitive data from rendered output'
|
||||
|
||||
def _pre_argument_parsing(self):
|
||||
if self._meta.argument_options is not None:
|
||||
assert isinstance(self._meta.argument_options, list), \
|
||||
"ScrubController.Meta.argument_options must be a list"
|
||||
self.app.args.add_argument(*self._meta.argument_options,
|
||||
help=self._meta.argument_help,
|
||||
action='store_true',
|
||||
dest='scrub')
|
||||
|
||||
|
||||
def load(app):
|
||||
app.handler.register(ScrubController)
|
||||
app.hook.register('post_render', scrub_output)
|
||||
app.hook.register('pre_argument_parsing', extend_scrub)
|
||||
|
||||
@ -325,17 +325,6 @@ def test_config_files_is_none():
|
||||
assert f in app._meta.config_files
|
||||
|
||||
|
||||
def test_base_controller_label():
|
||||
class BogusBaseController(Controller):
|
||||
class Meta:
|
||||
label = 'bad_base_controller_label'
|
||||
|
||||
msg = "must have a label of 'base'"
|
||||
with pytest.raises(FrameworkError, match=msg):
|
||||
with TestApp(base_controller=BogusBaseController):
|
||||
pass
|
||||
|
||||
|
||||
def test_pargs():
|
||||
with TestApp(argv=['--debug']) as app:
|
||||
app.run()
|
||||
@ -483,7 +472,7 @@ def test_run_forever():
|
||||
def handler(signum, frame):
|
||||
raise AssertionError('It ran forever!')
|
||||
|
||||
app = TestApp(base_controller=MyController, argv=['run-it'])
|
||||
app = TestApp(handlers=[MyController], argv=['run-it'])
|
||||
|
||||
# set the signal handler and a 5-second alarm
|
||||
signal.signal(signal.SIGALRM, handler)
|
||||
|
||||
@ -575,7 +575,7 @@ def test_get_exposed_commands():
|
||||
def cmd2_two(self):
|
||||
pass
|
||||
|
||||
with TestApp(base_controller=MyController) as app:
|
||||
with TestApp(handlers=[MyController]) as app:
|
||||
app.run()
|
||||
assert 'cmd1' in app.controller._get_exposed_commands()
|
||||
assert 'cmd2-two' in app.controller._get_exposed_commands()
|
||||
@ -591,5 +591,5 @@ def test_coverage():
|
||||
def hidden(self):
|
||||
pass
|
||||
|
||||
with TestApp(base_controller=MyController) as app:
|
||||
with TestApp(handlers=[MyController]) as app:
|
||||
app.run()
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import os
|
||||
import re
|
||||
from unittest.mock import patch
|
||||
from cement import TestApp, Controller, FrameworkError
|
||||
from cement import TestApp, Controller
|
||||
from cement.utils import shell
|
||||
from cement.utils.test import raises
|
||||
|
||||
@ -54,14 +54,6 @@ def test_generate(tmp):
|
||||
app.run()
|
||||
|
||||
|
||||
def test_missing_base_controller(tmp):
|
||||
argv = ['generate', 'test1', tmp.dir, '--defaults']
|
||||
with TestApp(argv=argv, extensions=['jinja2', 'generate']) as app:
|
||||
msg = 'ext.generate extension requires an application base controller'
|
||||
with raises(FrameworkError, match=msg):
|
||||
app.run()
|
||||
|
||||
|
||||
def test_prompt(tmp):
|
||||
argv = ['generate', 'test1', tmp.dir]
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
|
||||
from cement import init_defaults
|
||||
from cement.utils.test import TestApp
|
||||
|
||||
|
||||
@ -22,11 +23,13 @@ def test_scrub():
|
||||
|
||||
|
||||
def test_argument():
|
||||
META = init_defaults('controller.scrub')
|
||||
META['controller.scrub']['argument_options'] = ['--not-scrub']
|
||||
META['controller.scrub']['argument_help'] = 'not scrub'
|
||||
|
||||
class MyScrubApp(ScrubApp):
|
||||
class Meta:
|
||||
scrub_argument = ['--not-scrub']
|
||||
scrub_argument_help = 'not scrub'
|
||||
meta_defaults = META
|
||||
|
||||
with MyScrubApp(argv=['--not-scrub']) as app:
|
||||
app.run()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user