API¶
Application Object¶
-
class
groundwork.
App
(config_files=None, plugins=None, strict=False)¶ Application object for a groundwork app. Loads configurations, configures logs, initialises and activates plugins and provides managers.
- Performed steps during start up:
- load configuration
- configure logs
- get valid groundwork plugins
- activate configured plugins
Parameters: - config_files (list of str) – List of config files, which shall be loaded
- plugins (Plugin-Classes, based on
GwBasePattern
) – List of plugins, which shall be registered - strict – If true, Exceptions are thrown, if a plugin can not be initialised or activated.
-
_configure_logging
(logger_dict=None)¶ Configures the logging module with a given dictionary, which in most cases was loaded from a configuration file.
If no dictionary is provided, it falls back to a default configuration.
See Python docs for more information.
Parameters: logger_dict – dictionary for logger.
-
config
= None¶ Instance of
ConfigManager
. Used to load different configuration files and create a common configuration object.
-
log
= None¶ logging object for sending log messages. Example:
from groundwork import App my_app = App() my_app.log.debug("Send debug message") my_app.log.error("Send error....")
-
name
= None¶ Name of the application. Is configurable by parameter “APP_NAME” of a configuration file.
-
path
= None¶ Absolute application path. Is configurable by parameter “APP_PATH” of a configuration file. If not given, the current working directory is taken. The path is used to calculate absolute paths for tests, documentation and much more.
-
plugins
= None¶ Instance of
PluginManager
- Provides functions to load, activate and
-
signals
= None¶ Instance of
SignalsApplication
. Provides functions to register and fire
SignalsApplication¶
-
class
groundwork.signals.
SignalsApplication
(app)¶ Signal and Receiver management class on application level. This class is initialised once per groundwork application object.
Provides functions to register and send signals. And to connect receivers to signals.
Parameters: app (GwApp) – The groundwork application object -
connect
(receiver, signal, function, plugin, description='', sender=None)¶ Connect a receiver to a signal
Parameters: - receiver (str) – Name of the receiver
- signal (str) – Name of the signal. Must already be registered!
- function – Callable functions, which shall be executed, of signal is send.
- plugin – The plugin objects, which connects one of its functions to a signal.
- description – Description of the reason or use case, why this connection is needed. Used for documentation.
- sender – If set, only signals from this sender will be send to ths receiver.
-
disconnect
(receiver)¶ Disconnect a receiver from a signal. Signal and receiver must exist, otherwise an exception is thrown.
Parameters: receiver – Name of the receiver
-
get
(signal=None, plugin=None)¶ Get one or more signals.
Parameters: - signal (str) – Name of the signal
- plugin (GwBasePattern) – Plugin object, under which the signals where registered
-
get_receiver
(receiver=None, plugin=None)¶ Get one or more receivers.
Parameters: - receiver (str) – Name of the signal
- plugin (GwBasePattern) – Plugin object, under which the signals where registered
-
receivers
= None¶ Dictionary of registered receivers. Dictionary key is the registered receiver name. Value is an instance of
Receiver
.
-
register
(signal, plugin, description='')¶ Registers a new signal.
Parameters: - signal – Unique name of the signal
- plugin – Plugin, which registers the new signal
- description – Description of the reason or use case, why this signal is needed. Used for documentation.
-
send
(signal, plugin, **kwargs)¶ Sends a signal for the given plugin.
Parameters: - signal (str) – Name of the signal
- plugin (GwBasePattern) – Plugin object, under which the signals where registered
-
signals
= None¶ Dictionary of registered signals. Dictionary key is the registered signal name. Value is an instance of
Signal
.
-
unregister
(signal)¶ Unregisters an existing signal
Parameters: signal – Name of the signal
-
-
class
groundwork.signals.
Signal
(name, plugin, namespace, description='')¶ Groundwork signal class. Used to store name, description and plugin.
This information is mostly used to generated overviews about registered signals and their send history.
Parameters: - name (str) – Name of the signal
- namespace – Namespace of the signal. There is one per groundwork app.
- description (str) – Additional description for the signal
- plugin (GwBasePattern) – The plugin, which registered this signal
-
class
groundwork.signals.
Receiver
(name, signal, function, plugin, namespace, description='', sender=None)¶ Subscriber class, which stores information for documentation purposes.
Parameters: - name (str) – Name of the Subscriber
- signal (str) – Signal name(s)
- namespace – Namespace of the signal. There is one per groundwork app.
- function – Callable function, which gets executed, if signal is sent.
- plugin (GwBasePattern) – Plugin object, which registered the subscriber
- description (str) – Additional description about the subscriber.
Configuration¶
ConfigManager¶
-
class
groundwork.configuration.configmanager.
ConfigManager
(config_files=[])¶ Loads different configuration files and sets their attributes as attributes of its own instance.
A configuration file must be an importable python file.
Only uppercase attributes are loaded. Everything else is ignored. Example:
import os APP_NAME = "My APP" # Is used APP_PATH = os.path.abspath(".") # Is used app_test = "test" # Is NOT used MY_OWN_VAR = "nice" # Is used
Config¶
-
class
groundwork.configuration.configmanager.
Config
¶ Stores all configuration parameters and handles access to it.
- Example::
import groundwork my_app = groundwork.App(config_files=[“my_config.py”]) param = my_app.config.get(“MY_PARAM”, default=”Not set”)
my_app.config.set(“MY_PARAM_2, value=12345) param_2 = my_app.config.get(“MY_PARAM_2”)
-
get
(name, default=None)¶ Returns an existing configuration parameter. If not available, the default value is used.
Parameters: - name – Name of the configuration parameter
- default – Default value, if parameter is not set
-
set
(name, value, overwrite=False)¶ Sets a new value for a given configuration parameter.
If it already exists, an Exception is thrown. To overwrite an existing value, set overwrite to True.
Parameters: - name – Unique name of the parameter
- value – Value of the configuration parameter
- overwrite (boolean) – If true, an existing parameter of name gets overwritten without warning or exception.
PluginManagers¶
The pluginmanager module cares about the management of plugin status and their changes between status.
There are two manager classes for managing plugin related objects.
- PluginManager: Cares about initialised Plugins, which can be activated and deactivated.
- PluginClassManager: Cares about plugin classes, which are used to create plugins.
A plugin class can be reused for several plugins. The only thing to care about is the naming of a plugin. This plugin name must be unique inside a groundwork app and can be set during plugin initialisation/activation.
PluginManager¶
-
class
groundwork.pluginmanager.
PluginManager
(app)¶ PluginManager for searching, initialising, activating and deactivating groundwork plugins.
-
_register_initialisation
(plugin_instance)¶ Internal functions to perform registration actions after plugin load was successful.
-
activate
(plugins=[])¶ Activates given plugins.
This calls mainly plugin.activate() and plugins register needed resources like commands, signals or documents.
If given plugins have not been initialised, this is also done via
_load()
.Parameters: plugins (list of strings) – List of plugin names
-
classes
= None¶ Instance of
PluginClassManager
. Handles the registration of plugin classes, which can be used to create new plugins during runtime.
-
deactivate
(plugins=[])¶ Deactivates given plugins.
A given plugin must be activated, otherwise it is ignored and no action takes place (no signals are fired, no deactivate functions are called.)
A deactivated plugin is still loaded and initialised and can be reactivated by calling
activate()
again. It is also still registered in thePluginManager
and can be requested viaget()
.Parameters: plugins (list of strings) – List of plugin names
-
exist
(name)¶ Returns True if plugin exists. :param name: plugin name :return: boolean
-
get
(name=None)¶ Returns the plugin object with the given name. Or if a name is not given, the complete plugin dictionary is returned.
Parameters: name – Name of a plugin Returns: None, single plugin or dictionary of plugins
-
initialise
(clazz, name=None)¶
-
initialise_by_names
(plugins=None)¶ Initialises given plugins, but does not activate them.
This is needed to import and configure libraries, which are imported by used patterns, like GwFlask.
After this action, all needed python modules are imported and configured. Also the groundwork application object is ready and contains functions and objects, which were added by patterns, like app.commands from GwCommandsPattern.
The class of a given plugin must already be registered in the
PluginClassManager
.Parameters: plugins (list of strings) – List of plugin names
-
is_active
(name)¶ Returns True if plugin exists and is active. If plugin does not exist, it returns None
Parameters: name – plugin name Returns: boolean or None
-
PluginClassManager¶
-
class
groundwork.pluginmanager.
PluginClassManager
(app)¶ Manages the plugin classes, which can be used to initialise and activate new plugins.
Loads all plugin classes from entry_point “groundwork.plugin” automatically during own initialisation. Provides functions to register new plugin classes during runtime.
-
_get_plugins_by_entry_points
()¶ Registers plugin classes, which are in sys.path and have an entry_point called ‘groundwork.plugin’. :return: dict of plugin classes
-
exist
(name)¶ Returns True if plugin class exists. :param name: plugin name :return: boolean
-
get
(name=None)¶ Returns the plugin class object with the given name. Or if a name is not given, the complete plugin dictionary is returned.
Parameters: name – Name of a plugin Returns: None, single plugin or dictionary of plugins
-
register
(classes=[])¶ Registers new plugins.
The registration only creates a new entry for a plugin inside the _classes dictionary. It does not activate or even initialise the plugin.
A plugin must be a class, which inherits directly or indirectly from GwBasePattern.
Parameters: classes (list) – List of plugin classes
-
register_class
(clazz, name=None, entrypoint_name=None, distribution_path=None, distribution_key=None, distribution_version=None)¶
-
Plugin Patterns¶
GwBasePattern¶
gw_base_pattern provides all basic classes and functions, which are needed by any kind of groundwork plugin or pattern.
It mostly cares about the correct activation and deactivation. Including sending signals to inform other patterns or plugins about status changes of a plugin.
-
class
groundwork.patterns.gw_base_pattern.
GwBasePattern
(app, name=None, *args, **kwargs)¶ Base pattern class for all plugins and patterns.
Usage:
from groundwork.patterns import GwBasePattern class MyPlugin(GwBasePattern): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def activate(): self.signals.register("MySignal", "My description about signal) def deactivate(): self.signals.unregister("MySignal")
Parameters: - app (
groundwork.App
.) – groundwork application object, for which the plugin shall be initialised. - name – Unique name. Normally set by plugin.
-
activate
()¶ Must be overwritten by the plugin class itself.
-
app
= None¶ groundwork application instance. Access it inside a plugin via
self.app
.
-
deactivate
()¶ Must be overwritten by the plugin class itself.
-
log
= None¶ A logger, especially created for this plugin. Usage inside a plugin:
self.log.warn("WARNING!!")
.The logger name is the same as the plugin name. Therefor it is possible to configure the application logging to show log messages of a specif plugin only. See Logging
-
needed_plugins
= None¶ Variable for storing dependencies to other plugins. Tuple must contains needed plugin names. needed_plugins = (“MyPlugin”, “MyPlugin2)
-
signals
= None¶ Instance of
SignalsPlugin
. Provides functions to register and manage signals and retrievers.All action takes place in the context of this plugin. For instance a
self.signals.get()
will return signals of this plugin only. To get all signals of an application, please useself.app.signals.get()
.
- app (
-
class
groundwork.patterns.gw_base_pattern.
SignalsPlugin
(plugin)¶ Signal and Receiver management class on plugin level. This class gets initiated once per plugin.
Mostly delegates function calls to the
groundwork.signals.SignalListApplication
instance on application level.Parameters: plugin (GwBasePattern) – The plugin, which wants to use signals -
connect
(receiver, signal, function, description, sender=None)¶ Connect a receiver to a signal
Parameters: - receiver (str) – Name of the receiver
- signal (str) – Name of the signal. Must already be registered!
- function – Callable functions, which shall be executed, of signal is send.
- description – Description of the reason or use case, why this connection is needed. Used for documentation.
-
disconnect
(receiver)¶ Disconnect a receiver from a signal. Receiver must exist, otherwise an exception is thrown.
Parameters: receiver – Name of the receiver
-
get
(signal=None)¶ Returns a single signal or a dictionary of signals for this plugin.
-
get_receiver
(receiver=None)¶ Returns a single receiver or a dictionary of receivers for this plugin.
-
register
(signal, description)¶ Registers a new signal. Only registered signals are allowed to be send.
Parameters: - signal – Unique name of the signal
- description – Description of the reason or use case, why this signal is needed. Used for documentation.
-
send
(signal, **kwargs)¶ Sends a signal for the given plugin.
Parameters: signal (str) – Name of the signal
-
GwCommandPattern¶
-
class
groundwork.patterns.gw_commands_pattern.
GwCommandsPattern
(*args, **kwargs)¶ Bases:
groundwork.patterns.gw_base_pattern.GwBasePattern
Adds a commandline interface to a groundwork app and allows plugins to register own commands.
The functionality is based on click: http://click.pocoo.org/5/
- To register command parameters, you have to create instances of click.Option or click.Argument manually and
- add them to the register-parameter “params”
Example
from groundwork import GwCommandsPattern from click import Option class MyPlugin(GwCommandsPattern) def activate(self): self.commands.register(command="my_command", description="Help for my command", params=[Option(("--test", "-t"), help="Some dummy text")]) def my_command(self, my_test): print("Command executed! my_test=%s" % my_test)
For a complete list of configurable options, please take a look into the related click documentation of Option and Argument
Starting the command line interface
Groundwork does not start automatically the command line interface. This step must be done by the application developer. Example
from groundwork import GwApp gw_app = GwApp(plugins=["MyCommandPlugin"]) gw_app.activate(plugins=["MyCommandPlugin"]) gw_app.commands.start_cli()
-
activate
()¶ Must be overwritten by the plugin class itself.
-
commands
= None¶ Instance of
CommandsListPlugin
. Provides functions to register and manage commands for a command line interface.
-
deactivate
()¶ Must be overwritten by the plugin class itself.
-
GwCommandsPattern.
commands
-
class
groundwork.patterns.gw_commands_pattern.
CommandsListPlugin
(plugin)¶ -
get
(name=None)¶ Returns commands, which can be filtered by name.
Parameters: name (str) – name of the command Returns: None, single command or dict of commands
-
register
(command, description, function, params=[])¶ Registers a new command for a plugin.
Parameters: - command – Name of the command
- description – Description of the command. Is used as help message on cli
- function – function reference, which gets invoked if command gets called.
- params – list of click options and arguments
Returns: command object
-
unregister
(command)¶ Unregisters an existing command, so that this command is no longer available on the command line interface. This function is mainly used during plugin deactivation.
Parameters: command – Name of the command
-
-
class
groundwork.patterns.gw_commands_pattern.
CommandsListApplication
(app)¶ -
get
(name=None, plugin=None)¶ Returns commands, which can be filtered by name or plugin.
Parameters: - name (str) – name of the command
- plugin (instance of GwBasePattern) – plugin object, which registers the commands
Returns: None, single command or dict of commands
-
register
(command, description, function, params=[], plugin=None)¶ Registers a new command, which can be used on a command line interface (cli).
Parameters: - command – Name of the command
- description – Description of the command. Is used as help message on cli
- function – function reference, which gets invoked if command gets called.
- params – list of click options and arguments
- plugin – the plugin, which registered this command
Returns: command object
-
start_cli
(*args, **kwargs)¶ Start the command line interface for the application.
Parameters: - args – arguments
- kwargs – keyword arguments
Returns: none
-
unregister
(command)¶ Unregisters an existing command, so that this command is no longer available on the command line interface.
This function is mainly used during plugin deactivation.
Parameters: command – Name of the command
-
GwDocumentsPattern¶
-
class
groundwork.patterns.gw_documents_pattern.
GwDocumentsPattern
(*args, **kwargs)¶ Bases:
groundwork.patterns.gw_base_pattern.GwBasePattern
Documents can be collected by other Plugins to present their content inside user documentation, online help, console output or whatever.
Please see Documents for more details.
-
activate
()¶ Must be overwritten by the plugin class itself.
-
deactivate
()¶ Must be overwritten by the plugin class itself.
-
documents
= None¶ Stores an instance of
DocumentsListPlugin
-
-
class
groundwork.patterns.gw_documents_pattern.
DocumentsListPlugin
(plugin)¶ Stores and handles documents.
These documents are used for real-time and offline documentation of a groundwork application.
The content of a document must be string, which is can contain jinja and rst syntax.
Plugins, which want to generate a documentation out of all documents, must render this content (jinja render_template) and transform the rst by the own (e.g. by using rst2html).
Please see Documents for more details.
-
get
(name=None)¶
-
register
(name, content, description=None)¶ Register a new document.
Parameters: - content (str) – Content of this document. Jinja and rst are supported.
- name – Unique name of the document for documentation purposes.
- description – Short description of this document
-
unregister
(document)¶
-
-
class
groundwork.patterns.gw_documents_pattern.
DocumentsListApplication
(app)¶ -
get
(document=None, plugin=None)¶ Get one or more documents.
Parameters: - document (str) – Name of the document
- plugin (GwBasePattern) – Plugin object, under which the document was registered
-
register
(name, content, plugin, description=None)¶ Registers a new document.
Parameters: - content (str) – Content of the document
- name – Unique name of the document for documentation purposes.
- plugin (GwBasePattern) – Plugin object, under which the documents where registered
-
unregister
(document)¶ Unregisters an existing document, so that this document is no longer available.
This function is mainly used during plugin deactivation.
Parameters: document – Name of the document
-
GwThreadsPattern¶
-
class
groundwork.patterns.gw_threads_pattern.
GwThreadsPattern
(*args, **kwargs)¶ Bases:
groundwork.patterns.gw_base_pattern.GwBasePattern
Threads can be created and started to perform tasks in the background and in parallel to the main application.
Please see Threads for more details.
-
activate
()¶ Must be overwritten by the plugin class itself.
-
deactivate
()¶ Must be overwritten by the plugin class itself.
-
threads
= None¶ Stores an instance of
ThreadsListPlugin
-
-
class
groundwork.patterns.gw_threads_pattern.
ThreadsListPlugin
(plugin)¶ Stores and handles threads.
Please see Threads for more details.
-
get
(name=None)¶
-
register
(name, function, description=None)¶ Register a new thread.
Parameters: - function (function) – Function, which gets called for the new thread
- name – Unique name of the thread for documentation purposes.
- description – Short description of the thread
-
unregister
(thread)¶
-
-
class
groundwork.patterns.gw_threads_pattern.
ThreadsListApplication
(app)¶ -
get
(thread=None, plugin=None)¶ Get one or more threads.
Parameters: - thread (str) – Name of the thread
- plugin (GwBasePattern) – Plugin object, under which the thread was registered
-
register
(name, function, plugin, description=None)¶ Registers a new document.
Parameters: - function (function) – Function, which gets called for the new thread
- name – Unique name of the thread for documentation purposes.
- plugin (GwBasePattern) – Plugin object, under which the threads where registered
- description – Short description of the thread
-
unregister
(thread)¶ Unregisters an existing thread, so that this thread is no longer available.
This function is mainly used during plugin deactivation.
Parameters: thread – Name of the thread
-
-
class
groundwork.patterns.gw_threads_pattern.
Thread
(name, function, plugin, description=None)¶ Groundwork thread class. Used to store name, function and plugin.
This information is mostly used to generated overviews about registered threads.
Parameters: - name (str) – Name of the thread
- function (function) – Function, which gets called inside the thread
- plugin (GwBasePattern) – The plugin, which registered this thread
- description – short description of this thread
-
response
= None¶ Stores the function return value, if thread has finished
-
run
(**kwargs)¶ Runs the thread
Parameters: kwargs – dictionary of keyword arguments Returns:
-
running
= None¶ True, if thread is running. Otherwise its False.
-
thread
= None¶ Thread base class. Type is threading.Thread
-
time_end
= None¶ datetime object of the ending moment
-
time_start
= None¶ datetime object of the starting moment
GwRecipePattern¶
Groundwork recipe pattern.
Provides function to register, get and build recipes.
Recipes are used create directories and files based on a given template and some user input. It is mostly used to speed up the set up of new python packages, groundwork applications or projects.
Based on cookiecutter: https://github.com/audreyr/cookiecutter/
-
class
groundwork.patterns.gw_recipes_pattern.
GwRecipesPattern
(*args, **kwargs)¶ -
activate
()¶ Must be overwritten by the plugin class itself.
-
deactivate
()¶ Must be overwritten by the plugin class itself.
-
recipes
= None¶ Stores an instance of
RecipesListPlugin
-
-
class
groundwork.patterns.gw_recipes_pattern.
RecipesListPlugin
(plugin)¶ Cares about the recipe management on plugin level. Allows to register, get and build recipes in the context of the current plugin.
Parameters: plugin – plugin, which shall be used as contxt. -
build
(recipe)¶ Builds a recipe
Parameters: recipe – Name of the recipe to build.
-
get
(name=None)¶ Gets a list of all recipes, which are registered by the current plugin. If a name is provided, only the requested recipe is returned or None.
Param: name: Name of the recipe
-
register
(name, path, description, final_words=None)¶ Registers a new recipe in the context of the current plugin.
Parameters: - name – Name of the recipe
- path – Absolute path of the recipe folder
- description – A meaningful description of the recipe
- final_words – A string, which gets printed after the recipe was build.
-
unregister
(recipe)¶ Unregister a recipe of the current plugin.
Parameters: recipe – Name of the recipe.
-
-
class
groundwork.patterns.gw_recipes_pattern.
RecipesListApplication
(app)¶ Cares about the recipe management on application level. Allows to register, get and build recipes.
Parameters: app – groundwork application instance -
build
(recipe, plugin=None)¶ Execute a recipe and creates new folder and files.
Parameters: - recipe – Name of the recipe
- plugin – Name of the plugin, to which the recipe must belong.
-
get
(recipe=None, plugin=None)¶ Get one or more recipes.
Parameters: - recipe (str) – Name of the recipe
- plugin (GwBasePattern) – Plugin object, under which the recipe was registered
-
register
(name, path, plugin, description=None, final_words=None)¶ Registers a new recipe.
-
unregister
(recipe)¶ Unregisters an existing recipe, so that this recipe is no longer available.
This function is mainly used during plugin deactivation.
Parameters: recipe – Name of the recipe
-
-
class
groundwork.patterns.gw_recipes_pattern.
Recipe
(name, path, plugin, description='', final_words='')¶ A recipe is an existing folder, which will be handled by the underlying cookiecutter library as template folder.
Parameters: - name – Name of the recipe
- path – Absolute path to the recipe folder
- plugin – Plugin which registers the recipe
- description – Meaningful description of the recipe
- final_words – String, which gets printed after a recipe was successfully build.
-
build
(output_dir=None, **kwargs)¶ Buildes the recipe and creates needed folder and files. May ask the user for some parameter inputs.
Parameters: output_dir – Path, where the recipe shall be build. Default is the current working directory Returns: location of the installed recipe
Plugins¶
GwDocumentsInfo¶
-
class
groundwork.plugins.gw_documents_info.
GwDocumentsInfo
(*args, **kwargs)¶ Bases:
groundwork.patterns.gw_commands_pattern.GwCommandsPattern
,groundwork.patterns.gw_documents_pattern.GwDocumentsPattern
Provides a little documentation viewer for all registered documents. Accessible via app doc.
Presents also an overview about all registered documents of an application. Accessible via app doc_list.
GwPluginInfo¶
-
class
groundwork.plugins.gw_plugins_info.
GwPluginsInfo
(*args, **kwargs)¶ Bases:
groundwork.patterns.gw_commands_pattern.GwCommandsPattern
,groundwork.patterns.gw_documents_pattern.GwDocumentsPattern
Collects information about plugins, which are registered at the current application.
Collected information are accessible via command line or via a generated document during documentation generation (Additional plugin needed)
GwSignalInfo¶
-
class
groundwork.plugins.gw_signals_info.
GwSignalsInfo
(*args, **kwargs)¶ Bases:
groundwork.patterns.gw_commands_pattern.GwCommandsPattern
,groundwork.patterns.gw_documents_pattern.GwDocumentsPattern
GwCommandslInfo¶
-
class
groundwork.plugins.gw_commands_info.
GwCommandsInfo
(*args, **kwargs)¶ Bases:
groundwork.patterns.gw_documents_pattern.GwDocumentsPattern
,groundwork.patterns.gw_commands_pattern.GwCommandsPattern
Provides documents for giving an overview about registered commands.
GwRecipesBuilder¶
-
class
groundwork.plugins.gw_recipes_builder.
GwRecipesBuilder
(*args, **kwargs)¶ Bases:
groundwork.patterns.gw_commands_pattern.GwCommandsPattern
,groundwork.patterns.gw_recipes_pattern.GwRecipesPattern
Provides commands for listing and building recipes via command line interface.
Provided commands:
- recipe_list
- recipe_build
Provides also the recipe gw_package, which can be used to setup a groundwork related python package. Content of the package:
- setup.py: Preconfigured and ready to use.
- groundwork package structure: Directories for applications, patterns, plugins and recipes.
- Simple, runnable example of a groundwork application and plugins.
- usable test, supported by py.test and tox.
- expandable documentation, supported by sphinx and the groundwork sphinx template.
- .gitignore
This code is hardly based on Cookiecutter’s main.py file: https://github.com/audreyr/cookiecutter/blob/master/cookiecutter/main.py