123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- """
- The JSON Extension adds the :class:`JsonOutputHandler` to render
- output in pure JSON, as well as the :class:`JsonConfigHandler` that allows
- applications to use JSON configuration files as a drop-in replacement of
- the default :class:`cement.ext.ext_configparser.ConfigParserConfigHandler`.
- Requirements
- ------------
- * No external dependencies.
- Configuration
- -------------
- This extension does not honor any application configuration settings.
- Usage
- _____
- **myapp.conf**
- .. code-block:: json
- {
- "myapp": {
- "foo": "bar"
- }
- }
- **myapp.py**
- .. code-block:: python
- from cement.core.foundation import CementApp
- class MyApp(CementApp):
- class Meta:
- label = 'myapp'
- extensions = ['json']
- config_handler = 'json'
- # you probably don't want this to be json by default.. but you can
- # output_handler = 'json'
- with MyApp() as app:
- app.run()
- # create some data
- data = dict(foo=app.config.get('myapp', 'foo'))
- app.render(data)
- In general, you likely would not set ``output_handler`` to ``json``, but
- rather another type of output handler that display readable output to the
- end-user (i.e. Mustache, Genshi, or Tabulate). By default Cement
- adds the ``-o`` command line option to allow the end user to override the
- output handler. For example: passing ``-o json`` will override the default
- output handler and set it to ``JsonOutputHandler``.
- See ``CementApp.Meta.handler_override_options``.
- .. code-block:: console
- $ python myapp.py -o json
- {"foo": "bar"}
- """
- import sys
- import json
- from ..core import output, backend
- from ..utils.misc import minimal_logger
- from ..ext.ext_configparser import ConfigParserConfigHandler
- LOG = minimal_logger(__name__)
- def suppress_output_before_run(app):
- """
- This is a ``post_argument_parsing`` hook that suppresses console output if
- the ``JsonOutputHandler`` is triggered via command line.
- :param app: The application object.
- """
- if not hasattr(app.pargs, 'output_handler_override'):
- return
- elif app.pargs.output_handler_override == 'json':
- app._suppress_output()
- def unsuppress_output_before_render(app, data):
- """
- This is a ``pre_render`` that unsuppresses console output if
- the ``JsonOutputHandler`` is triggered via command line so that the JSON
- is the only thing in the output.
- :param app: The application object.
- """
- if not hasattr(app.pargs, 'output_handler_override'):
- return
- elif app.pargs.output_handler_override == 'json':
- app._unsuppress_output()
- def suppress_output_after_render(app, out_text):
- """
- This is a ``post_render`` hook that suppresses console output again after
- rendering, only if the ``JsonOutputHandler`` is triggered via command
- line.
- :param app: The application object.
- """
- if not hasattr(app.pargs, 'output_handler_override'):
- return
- elif app.pargs.output_handler_override == 'json':
- app._suppress_output()
- class JsonOutputHandler(output.CementOutputHandler):
- """
- This class implements the :ref:`IOutput <cement.core.output>`
- interface. It provides JSON output from a data dictionary using the
- `json <http://docs.python.org/library/json.html>`_ module of the standard
- library. Please see the developer documentation on
- :ref:`Output Handling <dev_output_handling>`.
- This handler forces Cement to suppress console output until
- ``app.render`` is called (keeping the output pure JSON). If
- troubleshooting issues, you will need to pass the ``--debug`` option in
- order to unsuppress output and see what's happening.
- """
- class Meta:
- """Handler meta-data"""
- interface = output.IOutput
- """The interface this class implements."""
- label = 'json'
- """The string identifier of this handler."""
- #: Whether or not to include ``json`` as an available to choice
- #: to override the ``output_handler`` via command line options.
- overridable = True
- def __init__(self, *args, **kw):
- super(JsonOutputHandler, self).__init__(*args, **kw)
- def render(self, data_dict, **kw):
- """
- Take a data dictionary and render it as Json output. Note that the
- template option is received here per the interface, however this
- handler just ignores it.
- :param data_dict: The data dictionary to render.
- :param template: This option is completely ignored.
- :returns: A JSON encoded string.
- :rtype: ``str``
- """
- LOG.debug("rendering output as Json via %s" % self.__module__)
- return json.dumps(data_dict)
- class JsonConfigHandler(ConfigParserConfigHandler):
- """
- This class implements the :ref:`IConfig <cement.core.config>`
- interface, and provides the same functionality of
- :ref:`ConfigParserConfigHandler <cement.ext.ext_configparser>`
- but with JSON configuration files.
- """
- class Meta:
- """Handler meta-data."""
- label = 'json'
- def __init__(self, *args, **kw):
- super(JsonConfigHandler, self).__init__(*args, **kw)
- def _parse_file(self, file_path):
- """
- Parse JSON configuration file settings from file_path, overwriting
- existing config settings. If the file does not exist, returns False.
- :param file_path: The file system path to the JSON configuration file.
- :returns: boolean
- """
- self.merge(json.load(open(file_path)))
- # FIX ME: Should check that file was read properly, however if not it
- # will likely raise an exception anyhow.
- return True
- def load(app):
- app.hook.register('post_argument_parsing', suppress_output_before_run)
- app.hook.register('pre_render', unsuppress_output_before_render)
- app.hook.register('post_render', suppress_output_after_render)
- app.handler.register(JsonOutputHandler)
- app.handler.register(JsonConfigHandler)
|