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 eachApp
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.
topological_sort
(l, get_depends)¶ -
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
clean
()¶ A method that sets or restores the state of the class.
Normally Dectate only sets up configuration into the
config
attribute, but in some cases you may touch other aspects of the class during configuration time. You can override this classmethod to set up the state of the class in its pristine condition.
-
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
is_committed
()¶ True if this app class was ever committed.
Returns: bool that is True
when the app was committed before.
-
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 subclassdectate.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 subclassdectate.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.
-
classmethod
-
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 duringcommit()
.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.
-
app_class_arg
= False¶ Pass in app class as argument.
In addition to the arguments defined in
Action.config
, pass in the app class itself as an argument intoAction.identifier()
,Action.discriminators()
,Action.perform()
, andAction.before()
andAction.after()
.
-
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()
, andAction.before()
andAction.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
usingfoo
in the query, you can mapfoo
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
andbefore
andafter
of the action class indicated bygroup_class
.By default an action only groups with others of its same class.
-
static
-
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, whereaction
is an instance of classAction
orComposite
andobj
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 ofAction
orComposite
. 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
andAction.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.
directive
(action_factory)¶ Create a classmethod to hook action to application class.
You pass in a
dectate.Action
or adectate.Composite
subclass and can attach the result as a class method to andectate.App
subclass:class FooAction(dectate.Action): ... class MyApp(dectate.App): my_directive = dectate.directive(MyAction)
Alternatively you can also define the direction inline using this as a decorator:
class MyApp(dectate.App): @directive class my_directive(dectate.Action): ...
Parameters: action_factory – an action class to use as the directive. Returns: a class method that represents the directive.
-
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
withname
attribute set toalpha
:$ 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.
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.- app_class – a
-
dectate.
convert_dotted_name
(s)¶ Convert input string to an object in a module.
Takes a dotted name:
pkg.module.attr
getsattr
from modulemodule
which is in packagepkg
.To refer to builtin objects such as
int
orobject
, in Python 2 prefix with__builtin__.
, so__builtin__.int
or__builtin__.None
. In Python 3 usebuiltins.
as the prefix, sobuiltins.int
andbuiltins.None
.Raises
ValueError
if it cannot be imported.
-
dectate.
convert_bool
(s)¶ Convert input string to boolean.
Input string must either be
True
orFalse
.
-
dectate.
NOT_FOUND
= <NOT_FOUND>¶ 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.