API

dectate.commit(*apps)

Commit one or more app classes

A commit causes the configuration actions to be performed. The resulting configuration information is stored under the .config class attribute of each App subclass supplied.

This function may safely be invoked multiple times – each time the known configuration is recommitted.

Parameters:*apps – one or more App subclasses to perform configuration actions on.
dectate.autocommit()

Automatically commit all App subclasses.

Dectate keeps track of all App subclasses that have been imported. You can automatically commit configuration for all of them.

Deprecated: use the explicit App.commit() method instead. Since App.commit() is defined to commit all dependent applications that are needed this makes it more explicit than this one.

dectate.topological_sort(l, get_depends)

Topological sort

Given a list of items that depend on each other, sort so that dependencies come before the dependent items. Dependency graph must be a DAG.

Parameters:
  • l – a list of items to sort
  • get_depends – a function that given an item gives other items that this item depends on. This item will be sorted after the items it depends on.
Returns:

the list sorted topologically.

class dectate.App

A configurable application object.

Subclass this in your framework and add directives using the App.directive() decorator.

Set the logger_name class attribute to the logging prefix that Dectate should log to. By default it is "dectate.directive".

classmethod commit()

Commit this class and any depending on it.

This is intended to be overridden by subclasses if committing the class also commits other classes automatically, such as in the case in Morepath when one app is mounted into another. In such case it should return an iterable of all committed classes.

Returns:an iterable of committed classes
classmethod directive(name)

Decorator to register a new directive with this application class.

You use this as a class decorator for a dectate.Action or a dectate.Composite subclass:

@MyApp.directive('my_directive')
class FooAction(dectate.Action):
    ...

This needs to be executed before the directive is used and thus might introduce import dependency issues unlike normal Dectate configuration, so beware! An easy way to make sure that all directives are installed before you use them is to make sure you define them in the same module as where you define the App subclass that has them.

Parameters:name – the name of the directive to register.
Returns:a directive that when called installs the directive method on the class.
classmethod is_committed()

True if this app class was ever committed.

Returns:bool that is True when the app was committed before.
classmethod private_action_class(action_class)

Register a private action class.

In some cases action classes can be an implementation detail, for instance in the implementation of a Composite action.

In this case you don’t want the action class to be known but not have a directive.

This function may be used as a decorator like this:

@App.private_action_class
class MyActionClass(dectate.Action):
    ...
Parameters:action_class – the dectate.Action subclass to register.
Returns:the :class`dectate.Action` class that was registered.
config = <dectate.app.Config object>

Config object that contains the configuration after commit.

This is installed when the class object is initialized, so during import-time when you use the class statement and subclass dectate.App, but is only filled after you commit the configuration.

This keeps the final configuration result after commit. It is a very dumb object that has no methods and is just a container for attributes that contain the real configuration.

dectate = <dectate.config.Configurable object>

A dectate Configurable instance is installed here.

This is installed when the class object is initialized, so during import-time when you use the class statement and subclass dectate.App.

This keeps tracks of the registrations done by using directives as long as committed configurations.

logger_name = 'dectate.directive'

The prefix to use for directive debug logging.

class dectate.Action

A configuration action.

Base class of configuration actions.

A configuration action is performed for an object (typically a function or a class object) and affects one or more configuration objects.

Actions can conflict with each other based on their identifier and discriminators. Actions can override each other based on their identifier. Actions can only be in conflict with actions of the same action class or actions with the same action_group.

static after(**kw)

Do setup just after actions in a group are performed.

Can be implemented as a static method by the Action subclass.

Parameters:**kw – a dictionary of configuration objects as specified by the config class attribute.
static before(**kw)

Do setup just before actions in a group are performed.

Can be implemented as a static method by the Action subclass.

Parameters:**kw – a dictionary of configuration objects as specified by the config class attribute.
discriminators(**kw)

Returns an iterable of immutables to detect conflicts.

Can be implemented by the Action subclass.

Used for additional configuration conflict detection.

Parameters:**kw – a dictionary of configuration objects as specified by the config class attribute.
Returns:an iterable of immutable values.
filter_get_value(name)

A function to get the filter value.

Takes two arguments, action and name. Should return the value on the filter.

This function is called if the name cannot be determined by looking for the attribute directly using Action.filter_name.

The function should return NOT_FOUND if no value with that name can be found.

For example if the filter values are stored on key_dict:

def filter_get_value(self, name):
    return self.key_dict.get(name, dectate.NOT_FOUND)
Parameters:name – the name of the filter.
Returns:the value to filter on.
get_value_for_filter(name)

Get value. Takes into account filter_name, filter_get_value

Used by the query system. You can override it if your action has a different way storing values altogether.

Parameters:name – the filter name to get the value for.
Returns:the value to filter on.
identifier(**kw)

Returns an immutable that uniquely identifies this config.

Needs to be implemented by the Action subclass.

Used for overrides and conflict detection.

If two actions in the same group have the same identifier in the same configurable, those two actions are in conflict and a ConflictError is raised during commit().

If an action in an extending configurable has the same identifier as the configurable being extended, that action overrides the original one in the extending configurable.

Parameters:**kw – a dictionary of configuration objects as specified by the config class attribute.
Returns:an immutable value uniquely identifying this action.
perform(obj, **kw)

Do whatever configuration is needed for obj.

Needs to be implemented by the Action subclass.

Raise a DirectiveError to indicate that the action cannot be performed due to incorrect configuration.

Parameters:
  • obj – the object that the action should be performed for. Typically a function or a class object.
  • **kw – a dictionary of configuration objects as specified by the config class attribute.
code_info

Info about where in the source code the action was invoked.

Is an instance of CodeInfo.

Can be None if action does not have an associated directive but was created manually.

config = {}

Describe configuration.

A dict mapping configuration names to factory functions. The resulting configuration objects are passed into Action.identifier(), Action.discriminators(), Action.perform(), and Action.before() and Action.after().

After commit completes, the configured objects are found as attributes on App.config.

depends = []

List of other action classes to be executed before this one.

The depends class attribute contains a list of other action classes that need to be executed before this one is. Actions which depend on another will be executed after those actions are executed.

Omit if you don’t care about the order.

filter_compare = {}

Map of names used in query filter to comparison functions.

If for instance you want to be able check whether the value of model on the action is a subclass of the value provided in the filter, you can provide it here:

filter_compare = {
    'model': issubclass
}

The default filter compare is an equality comparison.

filter_convert = {}

Map of names to convert functions.

The query tool that can be generated for a Dectate-based application uses this information to parse filter input into actual objects. If omitted it defaults to passing through the string unchanged.

A conversion function takes a string as input and outputs a Python object. The conversion function may raise ValueError if the conversion failed.

A useful conversion function is provided that can be used to refer to an object in a module using a dotted name: convert_dotted_name().

filter_name = {}

Map of names used in query filter to attribute names.

If for instance you want to be able to filter the attribute _foo using foo in the query, you can map foo to _foo:

filter_name = {
   'foo': '_foo'
}

If a filter name is omitted the filter name is assumed to be the same as the attribute name.

group_class = None

Action class to group with.

This class attribute can be supplied with the class of another action that this action should be grouped with. Only actions in the same group can be in conflict. Actions in the same group share the config and before and after of the action class indicated by group_class.

By default an action only groups with others of its same class.

class dectate.Composite

A composite configuration action.

Base class of composite actions.

Composite actions are very simple: implement the action method and return a iterable of actions in there.

actions(obj)

Specify a iterable of actions to perform for obj.

The iteratable should yield action, obj tuples, where action is an instance of class Action or Composite and obj is the object to perform the action with.

Needs to be implemented by the Composite subclass.

Parameters:obj – the obj that the composite action was performed on.
Returns:iterable of action, obj tuples.
code_info

Info about where in the source code the action was invoked.

Is an instance of CodeInfo.

Can be None if action does not have an associated directive but was created manually.

filter_convert = {}

Map of names to convert functions.

The query tool that can be generated for a Dectate-based application uses this information to parse filter input into actual objects. If omitted it defaults to passing through the string unchanged.

A conversion function takes a string as input and outputs a Python object. The conversion function may raise ValueError if the conversion failed.

A useful conversion function is provided that can be used to refer to an object in a module using a dotted name: convert_dotted_name().

query_classes = []

A list of actual action classes that this composite can generate.

This is to allow the querying of composites. If the list if empty (the default) the query system refuses to query the composite. Note that if actions of the same action class can also be generated in another way they are in the same query result.

class dectate.Query(*action_classes)

An object representing a query.

A query can be chained with Query.filter(), Query.attrs(), Query.obj().

Param:*action_classes: one or more action classes to query for. Can be instances of Action or Composite. Can also be strings indicating directive names, in which case they are looked up on the app class before execution.
attrs(*names)

Extract attributes from resulting actions.

The list of attribute names indicates which keys to include in the dictionary. Obeys Action.filter_name and Action.filter_get_value.

Param:*names: list of names to extract.
Returns:iterable of dictionaries.
filter(**kw)

Filter this query by keyword arguments.

The keyword arguments are matched with attributes on the action. Action.filter_name is used to map keyword name to attribute name, by default they are the same. Action.filter_get_value() can also be implemented for more complicated attribute access as a fallback.

By default the keyword argument values are matched by equality, but you can override this using Action.filter_compare.

Can be chained again with a new filter.

Parameters:**kw – keyword arguments to match against.
Returns:iterable of (action, obj).
obj()

Get objects from results.

Throws away actions in the results and return an iterable of objects.

Returns:iterable of decorated objects.
dectate.query_tool(app_classes)

Command-line query tool for dectate.

Uses command-line arguments to do the query and prints the results.

usage: decq [-h] [–app APP] directive <filter>

Query all directives named foo in given app classes:

$ decq foo

Query directives foo with name attribute set to alpha:

$ decq foo name=alpha

Query directives foo specifically in given app:

$ decq --app=myproject.App foo
Parameters:app_classes – a list of App subclasses to query by default.
dectate.auto_query_tool()

Command-line query tool for dectate.

Like query_tool(), but automatically uses all found app classes as the default, like autocommit().

Deprecated: use query_tool(App.commit() instead.

dectate.query_app(app_class, directive, **filters)

Query a single app with raw filters.

This function is especially useful for writing unit tests that test the conversion behavior.

Parameters:
  • app_class – a App subclass to query.
  • directive – name of directive to query.
  • **filters – raw (unconverted) filter values.
Returns:

iterable of action, obj tuples.

dectate.convert_dotted_name(s)

Convert input string to an object in a module.

Takes a dotted name: pkg.module.attr gets attr from module module which is in package pkg.

To refer to builtin objects such as int or object, in Python 2 prefix with __builtin__., so __builtin__.int or __builtin__.None. In Python 3 use builtins. as the prefix, so builtins.int and builtins.None.

Raises ValueError if it cannot be imported.

dectate.convert_bool(s)

Convert input string to boolean.

Input string must either be True or False.

dectate.NOT_FOUND = <dectate.config.NotFound object>

Sentinel value returned if filter value cannot be found on action.

class dectate.CodeInfo(path, lineno, sourceline)

Information about where code was invoked.

The path attribute gives the path to the Python module that the code was invoked in.

The lineno attribute gives the linenumber in that file.

The sourceline attribute contains the actual source line that did the invocation.

exception dectate.ConfigError

Raised when configuration is bad.

exception dectate.ConflictError(actions)

Bases: dectate.error.ConfigError

Raised when there is a conflict in configuration.

Describes where in the code directives are in conflict.

exception dectate.DirectiveError

Bases: dectate.error.ConfigError

Can be raised by user when there directive cannot be performed.

Raise it in Action.perform() with a message describing what the problem is:

raise DirectiveError("name should be a string, not None")

This is automatically converted by Dectate to a DirectiveReportError.

exception dectate.DirectiveReportError(message, code_info)

Bases: dectate.error.ConfigError

Raised when there’s a problem with a directive.

Describes where in the code the problem occurred.

exception dectate.TopologicalSortError

Bases: exceptions.ValueError

Raised if dependencies cannot be sorted topologically.

This is due to circular dependencies.