mirror of
https://github.com/datafolklabs/cement.git
synced 2026-02-06 13:26:45 +00:00
Resolves Issue #275
This commit is contained in:
parent
77e78eab0b
commit
2d1cdf5d2d
@ -52,6 +52,8 @@ Features:
|
||||
that code.
|
||||
* :issue:`270` - Add support for multiple template_dirs
|
||||
* :issue:`274` - Add cement.core.interface.list function
|
||||
* :issue:`775` - Added `examples/` directory with working examples based
|
||||
on Examples section of the documentation.
|
||||
|
||||
Incompatible:
|
||||
|
||||
|
||||
@ -6,5 +6,4 @@
|
||||
.. automodule:: cement.core.arg
|
||||
:members:
|
||||
:undoc-members:
|
||||
:private-members:
|
||||
:show-inheritance:
|
||||
:show-inheritance:
|
||||
|
||||
@ -5,168 +5,145 @@ For larger, complex applications it is often very useful to have abstract
|
||||
base controllers that hold shared arguments and commands that a number of
|
||||
other controllers have in common. Note that in the example below, you can
|
||||
not override the Meta.arguments in a sub-class or you overwrite the shared
|
||||
arguments. That said, you can add any number of additional commands in the
|
||||
sub-class but still maintain the existing shared commands.
|
||||
arguments, but it is possible to `append` to them in order to maintain the
|
||||
defaults while having unique options/arguments for the sub-classed controller.
|
||||
As well, you can add any number of additional commands in the sub-class but
|
||||
still maintain the existing shared commands (or override them as necessary).
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from cement.core import foundation, controller, handler
|
||||
|
||||
class AbstractBaseController(controller.CementBaseController):
|
||||
from cement.core import foundation, handler
|
||||
from cement.core.controller import CementBaseController, expose
|
||||
|
||||
class AbstractBaseController(CementBaseController):
|
||||
"""
|
||||
This is an abstract base class that is useless on its own, but used
|
||||
by other classes to sub-class from and to share common commands and
|
||||
arguments.
|
||||
|
||||
arguments. This should not be confused with the `MyAppBaseController`
|
||||
used as the ``base_controller`` namespace.
|
||||
|
||||
"""
|
||||
class Meta:
|
||||
stacked_on = 'base'
|
||||
stacked_type = 'nested'
|
||||
arguments = [
|
||||
( ['-f', '--foo'], dict(help='notorious foo option')),
|
||||
]
|
||||
|
||||
|
||||
def _setup(self, base_app):
|
||||
"""
|
||||
Add a common object that is useful in multiple sub-classed
|
||||
controllers.
|
||||
|
||||
"""
|
||||
super(AbstractBaseController, self)._setup(base_app)
|
||||
self.my_shared_obj = dict()
|
||||
|
||||
@controller.expose(hide=True)
|
||||
|
||||
# add a common object that will be used in any sub-class
|
||||
self.reusable_dict = dict()
|
||||
|
||||
@expose(hide=True)
|
||||
def default(self):
|
||||
"""
|
||||
This command will be shared within all controllers that sub-class
|
||||
from here. It can also be overridden in the sub-class, but for
|
||||
this example we are making it dynamic.
|
||||
|
||||
|
||||
"""
|
||||
# do something with self.my_shared_obj here?
|
||||
print(self.my_shared_obj)
|
||||
|
||||
if 'some_key' in self.reusable_dict.keys():
|
||||
pass
|
||||
|
||||
# or do something with parsed args?
|
||||
if self.app.pargs.foo:
|
||||
print "Foo option was passed!"
|
||||
|
||||
print "Foo option was passed with value: %s" % self.app.pargs.foo
|
||||
|
||||
# or maybe do something dynamically
|
||||
if self._meta.label == 'controller1':
|
||||
# do something for controller1
|
||||
print("Inside Controller1.default()")
|
||||
else:
|
||||
# do something else
|
||||
print("Inside %s.default()" % self._meta.label.capitalize())
|
||||
|
||||
class MyBaseController(controller.CementBaseController):
|
||||
print("Inside %s.default()" % self.__class__.__name__)
|
||||
|
||||
class MyAppBaseController(CementBaseController):
|
||||
"""
|
||||
This is the application base controller, but we don't want to use our
|
||||
abstract base class here.
|
||||
|
||||
|
||||
"""
|
||||
class Meta:
|
||||
label = 'base'
|
||||
|
||||
@controller.expose(hide=True)
|
||||
|
||||
@expose(hide=True)
|
||||
def default(self):
|
||||
print("Inside MyBaseController.default()")
|
||||
|
||||
print("Inside MyAppBaseController.default()")
|
||||
|
||||
class Controller1(AbstractBaseController):
|
||||
"""
|
||||
This controller sub-classes from the abstract base class as to inherite
|
||||
shared arguments, and commands.
|
||||
|
||||
|
||||
"""
|
||||
class Meta:
|
||||
label = 'controller1'
|
||||
description = 'Controller1 Does Amazing Things'
|
||||
|
||||
@controller.expose()
|
||||
|
||||
@expose()
|
||||
def command1(self):
|
||||
print("Inside Controller1.command1()")
|
||||
|
||||
|
||||
class Controller2(AbstractBaseController):
|
||||
"""
|
||||
This controller also sub-classes from the abstract base class as to
|
||||
This controller also sub-classes from the abstract base class as to
|
||||
inherite shared arguments, and commands.
|
||||
|
||||
|
||||
"""
|
||||
class Meta:
|
||||
label = 'controller2'
|
||||
description = 'Controller2 Also Does Amazing Things'
|
||||
|
||||
@controller.expose()
|
||||
|
||||
@expose()
|
||||
def command2(self):
|
||||
print("Inside Controller2.command2()")
|
||||
|
||||
app = foundation.CementApp('myapp', base_controller=MyBaseController)
|
||||
|
||||
try:
|
||||
# register non-base controller handlers
|
||||
handler.register(Controller1)
|
||||
handler.register(Controller2)
|
||||
|
||||
app.setup()
|
||||
app.run()
|
||||
finally:
|
||||
app.close()
|
||||
|
||||
def main():
|
||||
app = foundation.CementApp('myapp')
|
||||
|
||||
try:
|
||||
# register controllers handlers
|
||||
handler.register(MyAppBaseController)
|
||||
handler.register(Controller1)
|
||||
handler.register(Controller2)
|
||||
|
||||
app.setup()
|
||||
app.run()
|
||||
finally:
|
||||
app.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
And:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ python test.py
|
||||
Inside MyBaseController.default()
|
||||
$ python myapp.py
|
||||
Inside MyAppBaseController.default()
|
||||
|
||||
|
||||
$ python test.py --help
|
||||
usage: test.py <CMD> -opt1 --opt2=VAL [arg1] [arg2] ...
|
||||
$ python myapp.py --help
|
||||
usage: myapp.py (sub-commands ...) [options ...] {arguments ...}
|
||||
|
||||
Base Controller
|
||||
|
||||
commands:
|
||||
|
||||
controller1
|
||||
Controller1 Does Amazing Things
|
||||
Controller1 Controller
|
||||
|
||||
controller2
|
||||
Controller2 Also Does Amazing Things
|
||||
Controller2 Controller
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
--debug toggle debug output
|
||||
--quiet suppress all output
|
||||
|
||||
|
||||
$ python test.py controller1 --help
|
||||
usage: test.py controller1 <CMD> -opt1 --opt2=VAL [arg1] [arg2] ...
|
||||
|
||||
Controller1 Does Amazing Things
|
||||
|
||||
commands:
|
||||
|
||||
command1
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
--debug toggle debug output
|
||||
--quiet suppress all output
|
||||
-f FOO, --foo FOO notorious foo option
|
||||
|
||||
|
||||
$ python test.py controller1 command1
|
||||
Inside Controller1.command1()
|
||||
|
||||
|
||||
$ python test.py controller2 command2
|
||||
Inside Controller2.command2()
|
||||
|
||||
|
||||
$ python test.py controller1 --foo=bar
|
||||
{}
|
||||
Foo option was passed!
|
||||
$ python myapp.py controller1
|
||||
Inside Controller1.default()
|
||||
|
||||
$ python myapp.py controller1 --foo=bar
|
||||
Foo option was passed with value: bar
|
||||
Inside Controller1.default()
|
||||
|
||||
$ python test.py controller2 --foo=bar
|
||||
{}
|
||||
Foo option was passed!
|
||||
$ python myapp.py controller2
|
||||
Inside Controller2.default()
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
Adding a --version Option to Your App
|
||||
=====================================
|
||||
Adding a Version Option to Your App
|
||||
===================================
|
||||
|
||||
Almost every app out there supports a ``--version`` option of some sort that
|
||||
provides the end user with version information. This is pretty important to
|
||||
@ -9,7 +9,7 @@ line, rather than option flags. For example:
|
||||
$ myapp some-command some-argument --foo=bar
|
||||
|
||||
|
||||
In the above, `some-command` would be the function under whatever controller
|
||||
In the above, ``some-command`` would be the function under whatever controller
|
||||
it is exposed from, and `some-argument` would be just an arbtrary argument.
|
||||
In most cases, the argument within the code is generic, but its uses vary.
|
||||
For example:
|
||||
@ -21,8 +21,8 @@ For example:
|
||||
$ myapp create-group admins
|
||||
|
||||
|
||||
In the above, the sub-commands are `create-user` and `create-group`, and in
|
||||
this use case they are under the same controller. The `argument` however
|
||||
In the above, the sub-commands are ``create-user`` and ``create-group``, and
|
||||
in this use case they are under the same controller. The ``argument`` however
|
||||
differs for each command, though it is passed to the app the same (the first
|
||||
positional argument, that is not a controller/command).
|
||||
|
||||
@ -47,16 +47,12 @@ Example
|
||||
label = 'second'
|
||||
stacked_type = 'nested'
|
||||
stacked_on = 'base'
|
||||
description = 'this is the second controller namespace'
|
||||
arguments = [
|
||||
(
|
||||
['-f', '--foo'],
|
||||
dict(help='Notorious foo option', action='store')
|
||||
),
|
||||
(
|
||||
['extra_arguments'],
|
||||
dict(action='store', nargs='*')
|
||||
),
|
||||
|
||||
(['-f', '--foo'],
|
||||
dict(help='the notorious foo option', action='store')),
|
||||
(['extra_arguments'],
|
||||
dict(action='store', nargs='*')),
|
||||
]
|
||||
|
||||
@expose()
|
||||
@ -8,7 +8,7 @@ The difficulty is that this auto-completion code must be maintained outside of
|
||||
Cement and your application code, and be implemented in the shell environment
|
||||
generally by use of an "RC" file, or similar means. This then must be updated
|
||||
anytime your application is modified (or atleast any time the
|
||||
sub-commands/controllers are modified).
|
||||
sub-commands/controllers/arguments are modified).
|
||||
|
||||
Note that, in the future, we would love to include some form of
|
||||
"BASH RC Generator" that will do this for you, however in the meantime the
|
||||
@ -23,8 +23,8 @@ sub-commands, that are implemented via nested-controllers.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from cement.core import foundation, handler
|
||||
from cement.core.controller import CementBaseController, expose
|
||||
from cement.core import foundation, controller, handler
|
||||
|
||||
class BaseController(CementBaseController):
|
||||
class Meta:
|
||||
@ -32,56 +32,52 @@ sub-commands, that are implemented via nested-controllers.
|
||||
|
||||
@expose()
|
||||
def base_cmd1(self):
|
||||
print("Inside BaseController.cmd1()")
|
||||
|
||||
@expose()
|
||||
def base_cmd2(self):
|
||||
print("Inside BaseController.cmd2()")
|
||||
print("Inside BaseController.base_cmd1()")
|
||||
|
||||
class EmbeddedController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'embedded'
|
||||
description = "Embedded with Base Namespace"
|
||||
description = "embedded with base namespace"
|
||||
stacked_on = 'base'
|
||||
stacked_type = 'embedded'
|
||||
|
||||
@expose()
|
||||
def embedded_cmd1(self):
|
||||
print("Inside EmbeddedController.cmd1()")
|
||||
def base_cmd2(self):
|
||||
print("Inside EmbeddedController.base_cmd2()")
|
||||
|
||||
@expose()
|
||||
def embedded_cmd2(self):
|
||||
print("Inside EmbeddedController.cmd2()")
|
||||
def embedded_cmd3(self):
|
||||
print("Inside EmbeddedController.embedded_cmd3()")
|
||||
|
||||
class SecondLevelController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'second'
|
||||
description = "Second Level Namespace After The Base"
|
||||
description = ''
|
||||
stacked_on = 'base'
|
||||
stacked_type = 'nested'
|
||||
|
||||
@expose()
|
||||
def second_cmd1(self):
|
||||
print("Inside SecondLevelController.cmd1()")
|
||||
def second_cmd4(self):
|
||||
print("Inside SecondLevelController.second_cmd4()")
|
||||
|
||||
@expose()
|
||||
def second_cmd2(self):
|
||||
print("Inside SecondLevelController.cmd2()")
|
||||
def second_cmd5(self):
|
||||
print("Inside SecondLevelController.second_cmd5()")
|
||||
|
||||
class ThirdLevelController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'third'
|
||||
description = "Third Level Namespace After The Second"
|
||||
description = ''
|
||||
stacked_on = 'second'
|
||||
stacked_type = 'nested'
|
||||
|
||||
@expose()
|
||||
def third_cmd1(self):
|
||||
print("Inside ThirdLevelController.cmd1()")
|
||||
def third_cmd6(self):
|
||||
print("Inside ThirdLevelController.third_cmd6()")
|
||||
|
||||
@expose()
|
||||
def third_cmd2(self):
|
||||
print("Inside ThirdLevelController.cmd2()")
|
||||
def third_cmd7(self):
|
||||
print("Inside ThirdLevelController.third_cmd7()")
|
||||
|
||||
class MyApp(foundation.CementApp):
|
||||
class Meta:
|
||||
@ -127,42 +123,30 @@ This looks like:
|
||||
|
||||
base-cmd2
|
||||
|
||||
embedded-cmd1
|
||||
|
||||
embedded-cmd2
|
||||
embedded-cmd3
|
||||
|
||||
second
|
||||
Second Level Namespace After The Base
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
--debug toggle debug output
|
||||
--quiet suppress all output
|
||||
|
||||
|
||||
$ python myapp.py second --help
|
||||
|
||||
Second Level Namespace After The Base
|
||||
|
||||
commands:
|
||||
|
||||
second-cmd1
|
||||
second-cmd4
|
||||
|
||||
second-cmd2
|
||||
second-cmd5
|
||||
|
||||
third
|
||||
Third Level Namespace After The Second
|
||||
|
||||
|
||||
$ python myapp.py second third --help
|
||||
|
||||
Third Level Namespace After The Second
|
||||
|
||||
commands:
|
||||
|
||||
third-cmd1
|
||||
third-cmd6
|
||||
|
||||
third-cmd7
|
||||
|
||||
third-cmd2
|
||||
|
||||
|
||||
For demonstration purposes, we are going to create a BASH alias here so that
|
||||
@ -196,6 +180,8 @@ example and is not intended to be copy and pasted:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
alias myapp="python ./myapp.py"
|
||||
|
||||
_myapp_complete()
|
||||
{
|
||||
local cur prev BASE_LEVEL
|
||||
@ -207,7 +193,7 @@ example and is not intended to be copy and pasted:
|
||||
# SETUP THE BASE LEVEL (everything after "myapp")
|
||||
if [ $COMP_CWORD -eq 1 ]; then
|
||||
COMPREPLY=( $(compgen \
|
||||
-W "base-cmd1 base-cmd2 embedded-cmd1 embedded-cmd2 second" \
|
||||
-W "base-cmd1 base-cmd2 embedded-cmd3 second" \
|
||||
-- $cur) )
|
||||
|
||||
|
||||
@ -218,7 +204,7 @@ example and is not intended to be copy and pasted:
|
||||
# HANDLE EVERYTHING AFTER THE SECOND LEVEL NAMESPACE
|
||||
"second")
|
||||
COMPREPLY=( $(compgen \
|
||||
-W "second-cmd1 second-cmd2 third" \
|
||||
-W "second-cmd4 second-cmd5 third" \
|
||||
-- $cur) )
|
||||
;;
|
||||
|
||||
@ -240,7 +226,7 @@ example and is not intended to be copy and pasted:
|
||||
# HANDLE EVERYTHING AFTER THE THIRD LEVEL NAMESPACE
|
||||
"third")
|
||||
COMPREPLY=( $(compgen \
|
||||
-W "third-cmd1 third-cmd2" \
|
||||
-W "third-cmd6 third-cmd7" \
|
||||
-- $cur) )
|
||||
;;
|
||||
|
||||
@ -262,6 +248,7 @@ example and is not intended to be copy and pasted:
|
||||
complete -F _myapp_complete myapp
|
||||
|
||||
|
||||
|
||||
You would then "source" the RC file:
|
||||
|
||||
.. code-block:: bash
|
||||
@ -270,7 +257,7 @@ You would then "source" the RC file:
|
||||
|
||||
|
||||
In the "real world" you would probably put this in a system wide location
|
||||
such at `/etc/profile.d` or similar (in a production deployment).
|
||||
such at ``/etc/profile.d`` or similar (in a production deployment).
|
||||
|
||||
Finally, this is what it looks like:
|
||||
|
||||
@ -278,13 +265,13 @@ Finally, this is what it looks like:
|
||||
|
||||
# show all sub-commands at the base level
|
||||
$ myapp [tab] [tab]
|
||||
base-cmd1 base-cmd2 embedded-cmd1 embedded-cmd2 second
|
||||
base-cmd1 base-cmd2 embedded-cmd3 second
|
||||
|
||||
# auto-complete a partial matching sub-command
|
||||
$ myapp base [tab]
|
||||
|
||||
$ myapp base-cmd [tab] [tab]
|
||||
base-cmd1 base-cmd2
|
||||
base-cmd1 base-cmd2
|
||||
|
||||
# auto-complete a full matching sub-command
|
||||
$ myapp sec [tab]
|
||||
@ -293,9 +280,9 @@ Finally, this is what it looks like:
|
||||
|
||||
# show all sub-commands under the second namespace
|
||||
$ myapp second [tab] [tab]
|
||||
second-cmd1 second-cmd2 third
|
||||
second-cmd4 second-cmd5 third
|
||||
|
||||
# show all sub-commands under the third namespace
|
||||
$ myapp second third [tab] [tab]
|
||||
third-cmd1 third-cmd2
|
||||
third-cmd6 third-cmd7
|
||||
|
||||
|
||||
@ -26,26 +26,29 @@ and a 'hosts' controller and we want to have a 'list' sub-command under both:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from cement.core import foundation, controller, handler
|
||||
from cement.core import foundation, handler
|
||||
from cement.core.controller import CementBaseController, expose
|
||||
|
||||
# define application controllers
|
||||
class MyAppBaseController(controller.CementBaseController):
|
||||
class MyAppBaseController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'base'
|
||||
|
||||
class UsersController(controller.CementBaseController):
|
||||
class UsersController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'users'
|
||||
description = "this is the users controller"
|
||||
stacked_on = 'base'
|
||||
stacked_type = 'nested'
|
||||
|
||||
class HostsController(controller.CementBaseController):
|
||||
class HostsController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'hosts'
|
||||
description = "this is the hosts controller"
|
||||
stacked_on = 'base'
|
||||
stacked_type = 'nested'
|
||||
|
||||
class UsersListController(controller.CementBaseController):
|
||||
class UsersListController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'users_list'
|
||||
description = 'list all available users'
|
||||
@ -54,56 +57,61 @@ and a 'hosts' controller and we want to have a 'list' sub-command under both:
|
||||
stacked_on = 'users'
|
||||
stacked_type = 'nested'
|
||||
|
||||
@controller.expose(hide=True)
|
||||
@expose(hide=True)
|
||||
def default(self):
|
||||
print "Inside UsersListController.default()"
|
||||
|
||||
class HostsListController(controller.CementBaseController):
|
||||
class HostsListController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'hosts_list'
|
||||
description = 'list all available hosts'
|
||||
aliases = ['list']
|
||||
aliases_only = True
|
||||
interface = controller.IController
|
||||
stacked_on = 'hosts'
|
||||
stacked_type = 'nested'
|
||||
|
||||
@controller.expose(hide=True)
|
||||
@expose(hide=True)
|
||||
def default(self):
|
||||
print "Inside HostsListController.default()"
|
||||
|
||||
try:
|
||||
# create the application
|
||||
app = foundation.CementApp('myapp')
|
||||
def main():
|
||||
try:
|
||||
# create the application
|
||||
app = foundation.CementApp('myapp')
|
||||
|
||||
# register non-base controllers
|
||||
handler.register(MyAppBaseController)
|
||||
handler.register(UsersController)
|
||||
handler.register(HostsController)
|
||||
handler.register(UsersListController)
|
||||
handler.register(HostsListController)
|
||||
# register non-base controllers
|
||||
handler.register(MyAppBaseController)
|
||||
handler.register(UsersController)
|
||||
handler.register(HostsController)
|
||||
handler.register(UsersListController)
|
||||
handler.register(HostsListController)
|
||||
|
||||
# setup the application
|
||||
app.setup()
|
||||
# setup the application
|
||||
app.setup()
|
||||
|
||||
app.run()
|
||||
finally:
|
||||
app.close()
|
||||
# run it
|
||||
app.run()
|
||||
finally:
|
||||
# close it
|
||||
app.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ myapp --help
|
||||
usage: myapp (sub-commands ...) [options ...] {arguments ...}
|
||||
$ python myapp.py --help
|
||||
usage: myapp.py (sub-commands ...) [options ...] {arguments ...}
|
||||
|
||||
Base Controller
|
||||
|
||||
commands:
|
||||
|
||||
hosts
|
||||
Hosts Controller
|
||||
this is the hosts controller
|
||||
|
||||
users
|
||||
Users Controller
|
||||
this is the users controller
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
@ -111,10 +119,10 @@ and a 'hosts' controller and we want to have a 'list' sub-command under both:
|
||||
--quiet suppress all output
|
||||
|
||||
|
||||
$ myapp users --help
|
||||
usage: myapp (sub-commands ...) [options ...] {arguments ...}
|
||||
$ python myapp.py users --help
|
||||
usage: myapp.py (sub-commands ...) [options ...] {arguments ...}
|
||||
|
||||
Users Controller
|
||||
this is the users controller
|
||||
|
||||
commands:
|
||||
|
||||
@ -127,25 +135,9 @@ and a 'hosts' controller and we want to have a 'list' sub-command under both:
|
||||
--quiet suppress all output
|
||||
|
||||
|
||||
$ myapp hosts --help
|
||||
usage: myapp (sub-commands ...) [options ...] {arguments ...}
|
||||
|
||||
Hosts Controller
|
||||
|
||||
commands:
|
||||
|
||||
list
|
||||
list all available hosts
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
--debug toggle debug output
|
||||
--quiet suppress all output
|
||||
|
||||
|
||||
$ myapp users list
|
||||
$ python myapp.py users list
|
||||
Inside UsersListController.default()
|
||||
|
||||
|
||||
$ myapp hosts list
|
||||
$ python myapp.py hosts list
|
||||
Inside HostsListController.default()
|
||||
|
||||
|
||||
@ -7,10 +7,10 @@ with Cement.
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
version_option
|
||||
app_version
|
||||
multiple_stacked_controllers
|
||||
abstract_base_controllers
|
||||
controllers_with_same_label
|
||||
bash_auto_completion
|
||||
handling_extra_arguments
|
||||
arbitrary_extra_arguments
|
||||
load_extensions_via_config
|
||||
|
||||
@ -23,6 +23,10 @@ before ``app.setup()`` completes (such as in early framework hooks).
|
||||
class Meta:
|
||||
label = 'myapp'
|
||||
|
||||
config_files = [
|
||||
'./myapp.conf',
|
||||
]
|
||||
|
||||
def validate_config(self):
|
||||
if 'extensions' in self.config.keys('myapp'):
|
||||
exts = self.config.get('myapp', 'extensions')
|
||||
@ -48,12 +52,16 @@ before ``app.setup()`` completes (such as in early framework hooks).
|
||||
# add to meta data
|
||||
self._meta.extensions.append(ext)
|
||||
|
||||
app = MyApp()
|
||||
try:
|
||||
app.setup()
|
||||
app.run()
|
||||
finally:
|
||||
app.close()
|
||||
def main():
|
||||
app = MyApp()
|
||||
try:
|
||||
app.setup()
|
||||
app.run()
|
||||
finally:
|
||||
app.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
**myapp.conf**
|
||||
|
||||
|
||||
@ -6,108 +6,104 @@ Multiple Stacked Controllers
|
||||
.. code-block:: python
|
||||
|
||||
from cement.core import foundation, controller, handler
|
||||
from cement.core.controller import CementBaseController, expose
|
||||
|
||||
# define application controllers
|
||||
class MyAppBaseController(controller.CementBaseController):
|
||||
class MyAppBaseController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'base'
|
||||
interface = controller.IController
|
||||
description = "My Application Does Amazing Things"
|
||||
description = "my application does amazing things"
|
||||
arguments = [
|
||||
(['--base-opt'], dict(help="option under base controller")),
|
||||
]
|
||||
|
||||
@controller.expose(help="base controller default command", hide=True)
|
||||
@expose(help="base controller default command", hide=True)
|
||||
def default(self):
|
||||
self.app.args.parse_args(['--help'])
|
||||
print "Inside MyAppBaseController.default()"
|
||||
|
||||
@controller.expose(help="another base controller command")
|
||||
@expose(help="another base controller command")
|
||||
def command1(self):
|
||||
print "Inside MyAppBaseController.command1()"
|
||||
|
||||
class SecondController(controller.CementBaseController):
|
||||
"""This controller commands are 'stacked' onto the base controller."""
|
||||
|
||||
class SecondController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'second_controller'
|
||||
interface = controller.IController
|
||||
stacked_on = 'base'
|
||||
stacked_on = 'base'
|
||||
stacked_type = 'nested'
|
||||
description = "My Application's Second Controller (stacked)"
|
||||
description = "this is the second controller (stacked/nested on base)"
|
||||
arguments = [
|
||||
(['--2nd-opt'], dict(help="another option under base controller")),
|
||||
]
|
||||
|
||||
@controller.expose(help="command under the base namespace", aliases=['asdfas'])
|
||||
@expose(help="second-controller default command", hide=True)
|
||||
def default(self):
|
||||
print "Inside SecondController.default()"
|
||||
|
||||
@expose(help="this is a command under the second-controller namespace")
|
||||
def command2(self):
|
||||
print "Inside SecondController.command2()"
|
||||
|
||||
class ThirdController(controller.CementBaseController):
|
||||
"""This controller commands are *not* 'stacked' onto the base controller."""
|
||||
|
||||
class ThirdController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'third_controller'
|
||||
interface = controller.IController
|
||||
stacked_on = 'second_controller'
|
||||
stacked_on = 'second_controller'
|
||||
stacked_type = 'embedded'
|
||||
description = "My Application's Third Controller (not-stacked)"
|
||||
description = "this controller is embedded in the second-controller"
|
||||
arguments = [
|
||||
(['--3rd-opt'], dict(help="an option only under 3rd controller")),
|
||||
]
|
||||
|
||||
@controller.expose(help="default command for third_controller", hide=True)
|
||||
def default(self):
|
||||
print "Inside ThirdController.default()"
|
||||
|
||||
@controller.expose(help="a command only under the 3rd namespace")
|
||||
@expose(help="another command under the second-controller namespace")
|
||||
def command3(self):
|
||||
print "Inside ThirdController.command3()"
|
||||
|
||||
|
||||
class FourthController(controller.CementBaseController):
|
||||
"""This controller commands are 'stacked' onto the 3rd controller."""
|
||||
|
||||
class FourthController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'fourth_controller'
|
||||
interface = controller.IController
|
||||
stacked_on = 'third_controller'
|
||||
stacked_on = 'second_controller'
|
||||
stacked_type = 'nested'
|
||||
description = "My Application's Fourth Controller (stacked)"
|
||||
description = "this controller is nested on the second-controller"
|
||||
arguments = [
|
||||
(['--4th-opt'], dict(help="an option only under 3rd controller")),
|
||||
]
|
||||
|
||||
@controller.expose(help="a command only under the 3rd namespace")
|
||||
@expose(help="a command only under the fourth-controller namespace")
|
||||
def command4(self):
|
||||
print "Inside FourthController.command4()"
|
||||
|
||||
try:
|
||||
# create the application
|
||||
app = foundation.CementApp('myapp')
|
||||
def main():
|
||||
try:
|
||||
# create the application
|
||||
app = foundation.CementApp('myapp')
|
||||
|
||||
# register non-base controllers
|
||||
handler.register(MyAppBaseController)
|
||||
handler.register(SecondController)
|
||||
handler.register(ThirdController)
|
||||
handler.register(FourthController)
|
||||
# register controllers
|
||||
handler.register(MyAppBaseController)
|
||||
handler.register(SecondController)
|
||||
handler.register(ThirdController)
|
||||
handler.register(FourthController)
|
||||
|
||||
# setup the application
|
||||
app.setup()
|
||||
# setup the application
|
||||
app.setup()
|
||||
|
||||
app.run()
|
||||
finally:
|
||||
app.close()
|
||||
# run the application
|
||||
app.run()
|
||||
finally:
|
||||
# close the application
|
||||
app.close()
|
||||
|
||||
In the `base` controller output of `--help` notice that the
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
|
||||
In the `base` controller output of `--help` notice that the
|
||||
`second-controller` is listed as a sub-command:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ python example.py --help
|
||||
usage: example.py (sub-commands ...) [options ...] {arguments ...}
|
||||
$ python myapp.py --help
|
||||
usage: myapp.py (sub-commands ...) [options ...] {arguments ...}
|
||||
|
||||
My Application Does Amazing Things
|
||||
my application does amazing things
|
||||
|
||||
commands:
|
||||
|
||||
@ -115,34 +111,40 @@ In the `base` controller output of `--help` notice that the
|
||||
another base controller command
|
||||
|
||||
second-controller
|
||||
My Application's Second Controller (stacked)
|
||||
this is the second controller (stacked/nested on base)
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
--debug toggle debug output
|
||||
--quiet suppress all output
|
||||
--base-opt BASE_OPT option under base controller
|
||||
|
||||
|
||||
$ python example.py command1
|
||||
|
||||
|
||||
$ python myapp.py
|
||||
Inside MyAppBaseController.default()
|
||||
|
||||
|
||||
$ python myapp.py command1
|
||||
Inside MyAppBaseController.command1()
|
||||
|
||||
$ python myapp.py second-controller
|
||||
Inside SecondController.default()
|
||||
|
||||
$ python example.py second-controller --help
|
||||
usage: example.py (sub-commands ...) [options ...] {arguments ...}
|
||||
$ python myapp.py second-controller --help
|
||||
usage: myapp.py (sub-commands ...) [options ...] {arguments ...}
|
||||
|
||||
My Application's Second Controller (stacked)
|
||||
this is the second controller (stacked/nested on base)
|
||||
|
||||
commands:
|
||||
|
||||
command2 (aliases: asdfas)
|
||||
command under the base namespace
|
||||
command2
|
||||
this is a command under the second-controller namespace
|
||||
|
||||
command3
|
||||
a command only under the 3rd namespace
|
||||
another command under the second-controller namespace
|
||||
|
||||
fourth-controller
|
||||
My Application's Fourth Controller (stacked)
|
||||
this controller is nested on the second-controller
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
@ -151,27 +153,28 @@ In the `base` controller output of `--help` notice that the
|
||||
--2nd-opt 2ND_OPT another option under base controller
|
||||
--3rd-opt 3RD_OPT an option only under 3rd controller
|
||||
|
||||
Under the `second-controller` you can see the commands and options from the
|
||||
|
||||
Under the `second-controller` you can see the commands and options from the
|
||||
second and third controllers. In this example, the `second-controller` is
|
||||
`nested` on the base controller, and the `third-controller` is `embedded`
|
||||
`nested` on the base controller, and the `third-controller` is `embedded`
|
||||
on the `second-controller`. Finally, we see that the `fourth-controller` is
|
||||
also `nested` on the `second-controller` creating a sub-sub-command.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ python example.py second-controller command3
|
||||
$ python myapp.py second-controller command3
|
||||
Inside ThirdController.command3()
|
||||
|
||||
|
||||
$ python example.py second-controller fourth-controller --help
|
||||
usage: example.py (sub-commands ...) [options ...] {arguments ...}
|
||||
$ python myapp.py second-controller fourth-controller --help
|
||||
usage: myapp.py (sub-commands ...) [options ...] {arguments ...}
|
||||
|
||||
My Application's Fourth Controller (stacked)
|
||||
this controller is nested on the second-controller
|
||||
|
||||
commands:
|
||||
|
||||
command4
|
||||
a command only under the 3rd namespace
|
||||
a command only under the fourth-controller namespace
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
@ -180,5 +183,5 @@ also `nested` on the `second-controller` creating a sub-sub-command.
|
||||
--4th-opt 4TH_OPT an option only under 3rd controller
|
||||
|
||||
|
||||
$ python example.py second-controller fourth-controller command4
|
||||
$ python myapp.py second-controller fourth-controller command4
|
||||
Inside FourthController.command4()
|
||||
|
||||
0
examples/__init__.py
Normal file
0
examples/__init__.py
Normal file
104
examples/abstract_base_controllers/myapp.py
Normal file
104
examples/abstract_base_controllers/myapp.py
Normal file
@ -0,0 +1,104 @@
|
||||
|
||||
from cement.core import foundation, handler
|
||||
from cement.core.controller import CementBaseController, expose
|
||||
|
||||
class AbstractBaseController(CementBaseController):
|
||||
"""
|
||||
This is an abstract base class that is useless on its own, but used
|
||||
by other classes to sub-class from and to share common commands and
|
||||
arguments. This should not be confused with the `MyAppBaseController`
|
||||
used as the ``base_controller`` namespace.
|
||||
|
||||
"""
|
||||
class Meta:
|
||||
stacked_on = 'base'
|
||||
stacked_type = 'nested'
|
||||
arguments = [
|
||||
( ['-f', '--foo'], dict(help='notorious foo option')),
|
||||
]
|
||||
|
||||
def _setup(self, base_app):
|
||||
super(AbstractBaseController, self)._setup(base_app)
|
||||
|
||||
# add a common object that will be used in any sub-class
|
||||
self.reusable_dict = dict()
|
||||
|
||||
@expose(hide=True)
|
||||
def default(self):
|
||||
"""
|
||||
This command will be shared within all controllers that sub-class
|
||||
from here. It can also be overridden in the sub-class, but for
|
||||
this example we are making it dynamic.
|
||||
|
||||
"""
|
||||
# do something with self.my_shared_obj here?
|
||||
if 'some_key' in self.reusable_dict.keys():
|
||||
pass
|
||||
|
||||
# or do something with parsed args?
|
||||
if self.app.pargs.foo:
|
||||
print "Foo option was passed with value: %s" % self.app.pargs.foo
|
||||
|
||||
# or maybe do something dynamically
|
||||
print("Inside %s.default()" % self.__class__.__name__)
|
||||
|
||||
class MyAppBaseController(CementBaseController):
|
||||
"""
|
||||
This is the application base controller, but we don't want to use our
|
||||
abstract base class here.
|
||||
|
||||
"""
|
||||
class Meta:
|
||||
label = 'base'
|
||||
|
||||
@expose(hide=True)
|
||||
def default(self):
|
||||
print("Inside MyAppBaseController.default()")
|
||||
|
||||
class Controller1(AbstractBaseController):
|
||||
"""
|
||||
This controller sub-classes from the abstract base class as to inherite
|
||||
shared arguments, and commands.
|
||||
|
||||
"""
|
||||
class Meta:
|
||||
label = 'controller1'
|
||||
|
||||
@expose()
|
||||
def command1(self):
|
||||
print("Inside Controller1.command1()")
|
||||
|
||||
class Controller2(AbstractBaseController):
|
||||
"""
|
||||
This controller also sub-classes from the abstract base class as to
|
||||
inherite shared arguments, and commands.
|
||||
|
||||
"""
|
||||
class Meta:
|
||||
label = 'controller2'
|
||||
|
||||
@expose()
|
||||
def command2(self):
|
||||
print("Inside Controller2.command2()")
|
||||
|
||||
def main():
|
||||
# create the app
|
||||
app = foundation.CementApp('myapp')
|
||||
|
||||
try:
|
||||
# register controllers
|
||||
handler.register(MyAppBaseController)
|
||||
handler.register(Controller1)
|
||||
handler.register(Controller2)
|
||||
|
||||
# setup the app
|
||||
app.setup()
|
||||
|
||||
# run it
|
||||
app.run()
|
||||
finally:
|
||||
# close it
|
||||
app.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
35
examples/app_version/myapp.py
Normal file
35
examples/app_version/myapp.py
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
from cement.core.foundation import CementApp
|
||||
from cement.core.controller import CementBaseController
|
||||
|
||||
VERSION = '0.9.1'
|
||||
|
||||
BANNER = """
|
||||
My Awesome Application v%s
|
||||
Copyright (c) 2014 John Doe Enterprises
|
||||
""" % VERSION
|
||||
|
||||
class MyBaseController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'base'
|
||||
description = 'MyApp Does Amazing Things'
|
||||
arguments = [
|
||||
(['-v', '--version'], dict(action='version', version=BANNER)),
|
||||
]
|
||||
|
||||
class MyApp(CementApp):
|
||||
class Meta:
|
||||
label = 'myapp'
|
||||
base_controller = MyBaseController
|
||||
|
||||
|
||||
def main():
|
||||
app = MyApp()
|
||||
try:
|
||||
app.setup()
|
||||
app.run()
|
||||
finally:
|
||||
app.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
48
examples/arbitrary_extra_arguments/myapp.py
Normal file
48
examples/arbitrary_extra_arguments/myapp.py
Normal file
@ -0,0 +1,48 @@
|
||||
|
||||
from cement.core.foundation import CementApp
|
||||
from cement.core.controller import CementBaseController, expose
|
||||
from cement.core import handler
|
||||
|
||||
class MyBaseController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'base'
|
||||
|
||||
class MySecondController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'second'
|
||||
stacked_type = 'nested'
|
||||
stacked_on = 'base'
|
||||
description = 'this is the second controller namespace'
|
||||
arguments = [
|
||||
(['-f', '--foo'],
|
||||
dict(help='the notorious foo option', action='store')),
|
||||
(['extra_arguments'],
|
||||
dict(action='store', nargs='*')),
|
||||
]
|
||||
|
||||
@expose()
|
||||
def cmd1(self):
|
||||
print "Inside MySecondController.cmd1()"
|
||||
|
||||
if self.app.pargs.extra_arguments:
|
||||
print "Extra Argument 0: %s" % self.app.pargs.extra_arguments[0]
|
||||
print "Extra Argument 1: %s" % self.app.pargs.extra_arguments[1]
|
||||
|
||||
|
||||
class MyApp(CementApp):
|
||||
class Meta:
|
||||
label = 'myapp'
|
||||
base_controller = MyBaseController
|
||||
|
||||
def main():
|
||||
app = MyApp()
|
||||
handler.register(MySecondController)
|
||||
|
||||
try:
|
||||
app.setup()
|
||||
app.run()
|
||||
finally:
|
||||
app.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
85
examples/bash_auto_completion/myapp.py
Normal file
85
examples/bash_auto_completion/myapp.py
Normal file
@ -0,0 +1,85 @@
|
||||
|
||||
from cement.core import foundation, controller, handler
|
||||
from cement.core.controller import CementBaseController, expose
|
||||
|
||||
class BaseController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'base'
|
||||
|
||||
@expose()
|
||||
def base_cmd1(self):
|
||||
print("Inside BaseController.base_cmd1()")
|
||||
|
||||
class EmbeddedController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'embedded'
|
||||
description = "embedded with base namespace"
|
||||
stacked_on = 'base'
|
||||
stacked_type = 'embedded'
|
||||
|
||||
@expose()
|
||||
def base_cmd2(self):
|
||||
print("Inside EmbeddedController.base_cmd2()")
|
||||
|
||||
@expose()
|
||||
def embedded_cmd3(self):
|
||||
print("Inside EmbeddedController.embedded_cmd3()")
|
||||
|
||||
class SecondLevelController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'second'
|
||||
description = ''
|
||||
stacked_on = 'base'
|
||||
stacked_type = 'nested'
|
||||
|
||||
@expose()
|
||||
def second_cmd4(self):
|
||||
print("Inside SecondLevelController.second_cmd4()")
|
||||
|
||||
@expose()
|
||||
def second_cmd5(self):
|
||||
print("Inside SecondLevelController.second_cmd5()")
|
||||
|
||||
class ThirdLevelController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'third'
|
||||
description = ''
|
||||
stacked_on = 'second'
|
||||
stacked_type = 'nested'
|
||||
|
||||
@expose()
|
||||
def third_cmd6(self):
|
||||
print("Inside ThirdLevelController.third_cmd6()")
|
||||
|
||||
@expose()
|
||||
def third_cmd7(self):
|
||||
print("Inside ThirdLevelController.third_cmd7()")
|
||||
|
||||
class MyApp(foundation.CementApp):
|
||||
class Meta:
|
||||
label = 'myapp'
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
# create the app
|
||||
app = MyApp()
|
||||
|
||||
# register controllers to the app
|
||||
handler.register(BaseController)
|
||||
handler.register(EmbeddedController)
|
||||
handler.register(SecondLevelController)
|
||||
handler.register(ThirdLevelController)
|
||||
|
||||
# setup the app
|
||||
app.setup()
|
||||
|
||||
# run the app
|
||||
app.run()
|
||||
|
||||
finally:
|
||||
# close the app
|
||||
app.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
66
examples/bash_auto_completion/myapp.rc
Normal file
66
examples/bash_auto_completion/myapp.rc
Normal file
@ -0,0 +1,66 @@
|
||||
alias myapp="python ./myapp.py"
|
||||
|
||||
_myapp_complete()
|
||||
{
|
||||
local cur prev BASE_LEVEL
|
||||
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
# SETUP THE BASE LEVEL (everything after "myapp")
|
||||
if [ $COMP_CWORD -eq 1 ]; then
|
||||
COMPREPLY=( $(compgen \
|
||||
-W "base-cmd1 base-cmd2 embedded-cmd3 second" \
|
||||
-- $cur) )
|
||||
|
||||
|
||||
# SETUP THE SECOND LEVEL (EVERYTHING AFTER "myapp second")
|
||||
elif [ $COMP_CWORD -eq 2 ]; then
|
||||
case "$prev" in
|
||||
|
||||
# HANDLE EVERYTHING AFTER THE SECOND LEVEL NAMESPACE
|
||||
"second")
|
||||
COMPREPLY=( $(compgen \
|
||||
-W "second-cmd4 second-cmd5 third" \
|
||||
-- $cur) )
|
||||
;;
|
||||
|
||||
# IF YOU HAD ANOTHER CONTROLLER, YOU'D HANDLE THAT HERE
|
||||
"some-other-controller")
|
||||
COMPREPLY=( $(compgen \
|
||||
-W "some-other-sub-command" \
|
||||
-- $cur) )
|
||||
;;
|
||||
|
||||
# EVERYTHING ELSE
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
# SETUP THE THIRD LEVEL (EVERYTHING AFTER "myapp second third")
|
||||
elif [ $COMP_CWORD -eq 3 ]; then
|
||||
case "$prev" in
|
||||
# HANDLE EVERYTHING AFTER THE THIRD LEVEL NAMESPACE
|
||||
"third")
|
||||
COMPREPLY=( $(compgen \
|
||||
-W "third-cmd6 third-cmd7" \
|
||||
-- $cur) )
|
||||
;;
|
||||
|
||||
# IF YOU HAD ANOTHER CONTROLLER, YOU'D HANDLE THAT HERE
|
||||
"some-other-controller")
|
||||
COMPREPLY=( $(compgen \
|
||||
-W "some-other-sub-command" \
|
||||
-- $cur) )
|
||||
;;
|
||||
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
return 0
|
||||
|
||||
} &&
|
||||
complete -F _myapp_complete myapp
|
||||
72
examples/controllers_with_same_label/myapp.py
Normal file
72
examples/controllers_with_same_label/myapp.py
Normal file
@ -0,0 +1,72 @@
|
||||
|
||||
from cement.core import foundation, handler
|
||||
from cement.core.controller import CementBaseController, expose
|
||||
|
||||
# define application controllers
|
||||
class MyAppBaseController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'base'
|
||||
|
||||
class UsersController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'users'
|
||||
description = "this is the users controller"
|
||||
stacked_on = 'base'
|
||||
stacked_type = 'nested'
|
||||
|
||||
class HostsController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'hosts'
|
||||
description = "this is the hosts controller"
|
||||
stacked_on = 'base'
|
||||
stacked_type = 'nested'
|
||||
|
||||
class UsersListController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'users_list'
|
||||
description = 'list all available users'
|
||||
aliases = ['list']
|
||||
aliases_only = True
|
||||
stacked_on = 'users'
|
||||
stacked_type = 'nested'
|
||||
|
||||
@expose(hide=True)
|
||||
def default(self):
|
||||
print "Inside UsersListController.default()"
|
||||
|
||||
class HostsListController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'hosts_list'
|
||||
description = 'list all available hosts'
|
||||
aliases = ['list']
|
||||
aliases_only = True
|
||||
stacked_on = 'hosts'
|
||||
stacked_type = 'nested'
|
||||
|
||||
@expose(hide=True)
|
||||
def default(self):
|
||||
print "Inside HostsListController.default()"
|
||||
|
||||
def main():
|
||||
try:
|
||||
# create the application
|
||||
app = foundation.CementApp('myapp')
|
||||
|
||||
# register non-base controllers
|
||||
handler.register(MyAppBaseController)
|
||||
handler.register(UsersController)
|
||||
handler.register(HostsController)
|
||||
handler.register(UsersListController)
|
||||
handler.register(HostsListController)
|
||||
|
||||
# setup the application
|
||||
app.setup()
|
||||
|
||||
# run it
|
||||
app.run()
|
||||
finally:
|
||||
# close it
|
||||
app.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
2
examples/load_extensions_via_config/myapp.conf
Normal file
2
examples/load_extensions_via_config/myapp.conf
Normal file
@ -0,0 +1,2 @@
|
||||
[myapp]
|
||||
extensions = json, yaml
|
||||
46
examples/load_extensions_via_config/myapp.py
Normal file
46
examples/load_extensions_via_config/myapp.py
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
from cement.core.foundation import CementApp
|
||||
|
||||
class MyApp(CementApp):
|
||||
class Meta:
|
||||
label = 'myapp'
|
||||
|
||||
config_files = [
|
||||
'./myapp.conf',
|
||||
]
|
||||
|
||||
def validate_config(self):
|
||||
if 'extensions' in self.config.keys('myapp'):
|
||||
exts = self.config.get('myapp', 'extensions')
|
||||
|
||||
# convert a comma-separated string to a list
|
||||
if type(exts) is str:
|
||||
ext_list = exts.split(',')
|
||||
|
||||
# clean up extra space if they had it inbetween commas
|
||||
ext_list = (x.strip() for x in ext_list)
|
||||
|
||||
# set the new extensions value in the config
|
||||
self.config.set('myapp', 'extensions', ext_list)
|
||||
|
||||
# otherwise, if it's a list (ConfigObj?)
|
||||
elif type(exts) is list:
|
||||
ext_list = exts
|
||||
|
||||
for ext in ext_list:
|
||||
# load the extension
|
||||
self.ext.load_extension(ext)
|
||||
|
||||
# add to meta data
|
||||
self._meta.extensions.append(ext)
|
||||
|
||||
def main():
|
||||
app = MyApp()
|
||||
try:
|
||||
app.setup()
|
||||
app.run()
|
||||
finally:
|
||||
app.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
89
examples/multiple_stacked_controllers/myapp.py
Normal file
89
examples/multiple_stacked_controllers/myapp.py
Normal file
@ -0,0 +1,89 @@
|
||||
|
||||
from cement.core import foundation, handler
|
||||
from cement.core.controller import CementBaseController, expose
|
||||
|
||||
# define application controllers
|
||||
class MyAppBaseController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'base'
|
||||
description = "my application does amazing things"
|
||||
arguments = [
|
||||
(['--base-opt'], dict(help="option under base controller")),
|
||||
]
|
||||
|
||||
@expose(help="base controller default command", hide=True)
|
||||
def default(self):
|
||||
print "Inside MyAppBaseController.default()"
|
||||
|
||||
@expose(help="another base controller command")
|
||||
def command1(self):
|
||||
print "Inside MyAppBaseController.command1()"
|
||||
|
||||
class SecondController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'second_controller'
|
||||
stacked_on = 'base'
|
||||
stacked_type = 'nested'
|
||||
description = "this is the second controller (stacked/nested on base)"
|
||||
arguments = [
|
||||
(['--2nd-opt'], dict(help="another option under base controller")),
|
||||
]
|
||||
|
||||
@expose(help="second-controller default command", hide=True)
|
||||
def default(self):
|
||||
print "Inside SecondController.default()"
|
||||
|
||||
@expose(help="this is a command under the second-controller namespace")
|
||||
def command2(self):
|
||||
print "Inside SecondController.command2()"
|
||||
|
||||
class ThirdController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'third_controller'
|
||||
stacked_on = 'second_controller'
|
||||
stacked_type = 'embedded'
|
||||
description = "this controller is embedded in the second-controller"
|
||||
arguments = [
|
||||
(['--3rd-opt'], dict(help="an option only under 3rd controller")),
|
||||
]
|
||||
|
||||
@expose(help="another command under the second-controller namespace")
|
||||
def command3(self):
|
||||
print "Inside ThirdController.command3()"
|
||||
|
||||
class FourthController(CementBaseController):
|
||||
class Meta:
|
||||
label = 'fourth_controller'
|
||||
stacked_on = 'second_controller'
|
||||
stacked_type = 'nested'
|
||||
description = "this controller is nested on the second-controller"
|
||||
arguments = [
|
||||
(['--4th-opt'], dict(help="an option only under 3rd controller")),
|
||||
]
|
||||
|
||||
@expose(help="a command only under the fourth-controller namespace")
|
||||
def command4(self):
|
||||
print "Inside FourthController.command4()"
|
||||
|
||||
def main():
|
||||
try:
|
||||
# create the application
|
||||
app = foundation.CementApp('myapp')
|
||||
|
||||
# register controllers
|
||||
handler.register(MyAppBaseController)
|
||||
handler.register(SecondController)
|
||||
handler.register(ThirdController)
|
||||
handler.register(FourthController)
|
||||
|
||||
# setup the application
|
||||
app.setup()
|
||||
|
||||
# run the application
|
||||
app.run()
|
||||
finally:
|
||||
# close the application
|
||||
app.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Loading…
Reference in New Issue
Block a user