API reference

Module dja.skel.core.skeleton

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.

Path rewriting

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.

The Skeleton class

class dja.skel.core.skeleton.Var(name, **kwargs)

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.

default

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.

has_default()

Returns True if a default value was provided to the constructor.

summary

This property returns the variable’s summary. If no summary argument was provided to the constructor returns an empty string.

class dja.skel.core.skeleton.Skeleton(path_rewriter=None)

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:

base_skeletons = ()

list of skeleton classes this one is based upon.

skeleton_path

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

name of the skeleton.

variables = ()

an iterable of Var instances declaring variables required by the skeleton. This parameter is used for documentation purposes.

template_engine = "format"

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.

template_engine_parametres = {}

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:

  1. the before_instantiation() method is called. This is a good place to place initialisation code and the like.
  2. the get_extra_context() method is called. This method is responsible for gathering extra context variables.
  3. the actual instantiation is performed
  4. the after_instantiation() method is called. This is a good place to perform tasks that further customise the result of the instantiation.

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.

__init__()

Constructor.

It is required that the constructor on subclasses accepts no parameters.

after_instantiation()

Performs post instantiation tasks.

This method is called after the skeleton has been instantiated.

before_instantiation(dest_dir, context, encoding)

Performs initial setup tasks.

This method is called before skeleton instantiation. It receives the same parameters that instantiate().

get_extra_context(context)

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(dest_dir, context, encoding='utf-8')

Instantiate the skeleton.

This method is the public entry point for the class.

Parameters:
  • dest_dir – the path of the directory where the result will be saved. It’s not required but is advisable to use an absolute path.
  • context – a dictionary mapping variable names to values. It will be used for variable substitution in templates and file names. Internally this class works with unicode strings, so it is expected that the string values are stored in the context as unicode strings.
  • encoding – the desired encoding for the output files. It is only meaningful for templates, the static files are copied verbatim.

Module dja.skel.core.rewriter

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.

The RegexRewriter class

class dja.skel.core.rewriter.RegexRewriter(rules)

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(path)

Rewrite a path.

dja.skel.core.rewriter.json_loader(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

The ContextRewriter class

class dja.skel.core.rewriter.ContextRewriter(rewriter, context)

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.

dotted(path)

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
path(path)

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

Module dja.skel.core.templating

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.

The Engine base class

class dja.skel.core.templating.Engine(**kw)

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.

__init__(**kw)

Stores the arguments in the opts attribute (an object).

render(path, context)

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.

_render(template, context, path)

Actual renderer.

Called by render(). It receives the template as an unicode string and must return the result as unicode.

Parameters:
  • template – unicode string with template contents.
  • context – dictionary mapping variables to values.
  • path – path of the template, mostly useful to report errors.
Returns:

the rendered template.

Return type:

an unicode string.

Module dja.skel.core.errors

exception dja.skel.core.errors.SkelError

Base exception.

exception dja.skel.core.errors.TemplateError(message, filename)

Exception raised when an error is encountered in a template.

The exception object has the following attributes:

filename

path of the template that raised the exception.

message

error message provided by the template engine.

exception dja.skel.core.errors.UndefinedVarError(varname, filename)

Exception raised whenever a variable required by a template is missing from the context dictionary.

The exception object has the following attributes:

filename

path of the template that raised the exception.

varname

name of the offending variable.

Helper classes

Module dja.skel.core.python_package

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.

class dja.skel.core.python_package.PythonPackage(path=None, pkg=None)

Python package.

get_file(rel_path, encoding='utf-8')
is_dir(rel_path)

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
is_file(rel_path)

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
is_module(dot_path)

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
is_package(dot_path)

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