This module defines a class that models an skeleton.
An skeleton is a directory containing some templates and static files plus some intelligence that can perform tasks programmatically. An skeleton is defined by sub-classing the dja.skel.core.skeleton.Skeleton class or one of its subclasses:
class MySkeleton(Skeleton):
variables = (Var("prjname"), Var("version"))
skeleton_path = "templates/my_skeleton"
name = "my_skeleton"
def frobnicate(self):
# this method performs some task on the
# result of instantiating the skeleton
pass
The instantiation of an skeleton is the process of rendering the individual templates (performing variable substitution and so on), copying the static files and executing the logic that fine tunes the final result. In order to instantiate an skeleton a destination directory and a dictionary mapping template variable names to their actual value are required.
skel = MySkeleton()
skel.instantiate("/path/to/some/dir", { "var" : "value" })
Any file within the skeleton_path directory whose name ends with the _tmpl suffix is considered a template that must be rendered. All other files will be copied verbatim.
File and directory names can be parameterised too, just enclose the variable parts within braces and they will be expanded upon skeleton instantiation. For example, if the skeleton directory contains a file named {var}.py the previous instantiation will create a file value.py.
An skeleton may be build upon other skeletons, such skeleton is named a compound skeleton.
class MySkeleton(Skeleton):
skeleton_path = "templates/my_skeleton"
name = "my_skeleton"
base_skeletons = (AnSkeleton, OtherSkeleton)
When a compound skeleton is instantiated in the first place the base skeletons are instantiated, in reverse order of declaration, and then the parent skeleton is instantiated. This way it’s clear what files prevail in case of conflict. That functionality makes easy building complex skeletons based on simpler ones or overriding some parts of an existing skeleton. In order to avoid variable clashes when instantiating a compound skeleton every participant will receive a shallow copy of the context dictionary, that way they can modify the context as required without interferences.
The skeleton machinery does not force you to use a particular template engine, instead it uses a pluggable architecture that eases using whatever template engine you feel more comfortable with. See dja.skel.core.templating.Engine.
Sometimes it may be useful to be able to change the directory structure when an skeleton gets instantiated. Lets supose that we have an skeleton that creates the four views required to implement CRUD on a model, the skeleton may look like:
views/{model_name}/__init__.py
views/{model_name}/create.py
views/{model_name}/read.py
views/{model_name}/update.py
views/{model_name}/delete.py
So if we instantiate the skeleton for the model ‘StudentProfile’ we’ll get the modules:
views/student_profile/__init__.py
views/student_profile/create.py
views/student_profile/read.py
views/student_profile/update.py
views/student_profile/delete.py
But our application manages both students and teachers and, as we are organizated people, we want all the views related to students stored into the views/student directory.
All that’s required to acomplish this is to pass a path rewriter object to the skeleton’s constructor in the path_rewriter parameter. The path rewriter may have a rule that transforms the path:
views/{model_name}/whatever
into:
views/{entity}/{model_name}/wathever
And passing the value student for the variable entity in the context will do the trick.
This class represents a variable declaration. The only required argument is the variable name, the constructor accepts any keyword argument and will store them as instance attributes. This way arbitrary metadata can be easily attached to the variable.
We can specify a default value for the variable using the keyword argument default. In order to ensure that the variable has a default value the has_default() method must be called before accessing the instance’s default attribute.
This property returns the default value provided to the constructor. The value returned when the variable has no default is meaningless. Use has_default() to ensure that the variable has a default value.
Returns True if a default value was provided to the constructor.
This property returns the variable’s summary. If no summary argument was provided to the constructor returns an empty string.
This class models an skeleton and provides a method for instantiating it.
Warning
Instances of this class are not thread safe although they can be safely reused after instantiation is finished.
It defines the following class attributes:
list of skeleton classes this one is based upon.
path to the directory where templates and static files are stored. It must be a relative path. It is first looked for in the directory containing the module that defines the skeleton, then in its parent until it’s found or the root of the package is reached.
name of the skeleton.
an iterable of Var instances declaring variables required by the skeleton. This parameter is used for documentation purposes.
name of the template engine used to render the templates. By default the string method format is used. The value is looked up in the entry points defined in the group dja_skel.template_engine. The first match is used.
a dictionary whose values will be passed as keyword arguments to the template engine constructor. Default an empty dict.
When an skeleton is instantiated the following steps are executed:
Subclasses may override the methods before_instantiation(), after_instantiation() and get_extra_context(). Don’t forget to call super in order to play nicely with base classes.
Constructor.
It is required that the constructor on subclasses accepts no parameters.
Performs post instantiation tasks.
This method is called after the skeleton has been instantiated.
Performs initial setup tasks.
This method is called before skeleton instantiation. It receives the same parameters that instantiate().
Gather extra context.
This method is called before skeleton instatiation in order to gather extra context. It defines the variables:
Skel_environ : | the value of os.environ |
---|---|
Skel_root_path : | |
the path to the destination directory passed to instantiate(). | |
Skel_encoding : | the encoding passed to instantiate(). |
Classes overriding this method can add variables to the context dictionary as required. Care must be taken in order to avoid name clashes. Variable names starting with the skel_ prefix are reserved.
Parameters: | context – a dictionary mapping variable names to values. |
---|---|
Returns: | the context dictionary. |
Return type: | dict |
Instantiate the skeleton.
This method is the public entry point for the class.
Parameters: |
|
---|
Path rewriting is a mechanism that allows client code to alter the directory layout for an skeleton.
A path rewriter is any class defining a rewrite(path) method. This method will receive the path to be rewritten and must return the rewritten path.
This modules defines a regex based rewriter (RegexRewriter) and a factory (json_loader()) that instantiates a RegexRewriter from a json file storing the rules.
For convenience it also defines the class ContextRewriter for use in templates. Despite his name that class is not a rewriter.
Path rewriter based upon regular expressions.
This path rewriter takes a list of rules in the form (pattern, target). When a rewrite is requested the provided path is matched against the patterns in turn. If a match is found the corresponding target is returned, otherwise the original path is returned.
The patterns may contain named group definitions. If a match is found the rewrite() method will interpolate the values of the groups into the target using the % operator. For exemple the rule:
('views/(?P<filename>.+)', 'views/{section}/%(filename)s')
will rewrite views/foo.py into views/{section}/foo.py.
Rewrite a path.
Factory function that creates a RegexRewriter object from a json file containing a list un rules in the form:
[ [ pattern, target ], ... ]
Parameters: | path – path to the file containing the rules |
---|---|
Returns: | if the file can be succesfully parsed returns a RegexRewriter instance. |
Raises : | ValueError if the file can’t be parsed |
Convenience rewriter passed in the context to the templates.
This class encapsulates an actual rewriter and the skeleton’s context and provides utility methods to ease rewriting within templates.
Rewrites and converts a path to dot notation.
Assuming that cr is a ContextRewriter instance, that the rewriter maps the path views/<filename> to views/{section}/<filename> and that the context defines section as some_section, then:
>>> cr.path('views/foo.py')
'views.some_section.foo'
>>> cr.path('views/foo')
'views.some_section.foo'
Parameters: | path – path to be rewritten, an string |
---|---|
Returns: | rewritten path, an string |
Rewrites a path.
Assuming that cr is a ContextRewriter instance, that the rewriter maps the path views/<filename> to views/{section}/<filename> and that the context defines section as some_section, then:
>>> cr.path('views/foo.py')
'views/some_section/foo.py'
Parameters: | path – path to be rewritten, an string |
---|---|
Returns: | rewritten path, an string |
Every template engine has its own API. An adapter API is defined in order to isolate the skeleton machinery from the actual template engine being used to render the template.
Skeletons expect that the engine adapter classes define two methods:
__init__(input_encoding=’utf-8’, **kwargs)
The engine adapter constructor must accept only keyword arguments. At this point only one argument is defined:
param input_encoding: | |
---|---|
encoding used in the template. |
render(path, context)
Renders the template given by the path path using the variables defined in context. The template is expected to be encoded in the input_encoding encoding.
param path: | path of the template |
---|---|
param context: | dictionary mapping variables to values. |
returns: | the rendered template |
rtype: | an unicode string |
The template engine adapter must take care of adapting exceptions raised by the template engine. At this point two translations are defined:
In order to create an adapter a class implementing the API must be defined and registered under the dja_skel.template_engine entry point.
This class implements the adapter API. Template engine adapters are not required to inherit from this class. It just provides some common functionality to ease the creation of new adapters.
Subclasses must override the _render() method.
Stores the arguments in the opts attribute (an object).
Render the template.
This implementation reads the template from the filesystem, decodes it using the input_encoding argument specified in the constructor and finally calls the _render() method.
Actual renderer.
Called by render(). It receives the template as an unicode string and must return the result as unicode.
Parameters: |
|
---|---|
Returns: | the rendered template. |
Return type: | an unicode string. |
Base exception.
Exception raised when an error is encountered in a template.
The exception object has the following attributes:
path of the template that raised the exception.
error message provided by the template engine.
Exception raised whenever a variable required by a template is missing from the context dictionary.
The exception object has the following attributes:
path of the template that raised the exception.
name of the offending variable.
This modules provides some convenience classes to ease the management of python packages.
In that context a package is a directory with and __init__.py while a module is any file.py.
Python package.
Cheks if rel_path points to a directory.
Parameters: | rel_path – |
---|---|
Raises : | |
Returns: | True if rel_path is a directory, False otherwise. |
Return type: | bool |
Checks if rel_path points to a file.
Parameters: | rel_path – |
---|---|
Raises : | |
Returns: | True if rel_path is a file, False otherwise. |
Return type: | bool |
Checks if dot_path points to a module.
Parameters: | dot_path – |
---|---|
Raises : | |
Returns: | True if dot_path is a module, False otherwise |
Return type: | bool |
Checks if dot_path points to a package.
Parameters: | dot_path – |
---|---|
Raises : | |
Returns: | True if dot_path is a package, False otherwise. |
Return type: | bool |