Customizing PyDitz¶
There are several ways to customize the way PyDitz operates. The most basic is to adjust the settings in your Configuration File. But you can also change the look and feel of the exported issue database, and add your own export formats and PyDitz commands. This section tells you how to do these things.
Customizing exported data¶
PyDitz uses two types of file when exporting its data: static files, and template files. Static files are copied verbatim from where they’re found into the destination directory, whereas template files are modified by inserting content into them at various points (and typically reference the static files). The engine used to insert template content is Jinja2.
Static and template files for the builtin export formats are found by default in PyDitz’s installed package directory. But other places are searched first, and this is where you can put customized files to override things. The search path for files is (in order of searching):
- The directory where issues are stored for the project
HOMEDIR/.ditz
- PyDitz’s installed package directory
When exporting issues in a given format, PyDitz looks in each of these directories for subdirectories:
DIR/static/FORMAT
- Static files for the export format
DIR/templates/FORMAT
- Template files for the export format
Modifying static files¶
So, for example, if you wanted to modify the stylesheet for the HTML output for a particular PyDitz project, you could do the following:
- Generate HTML normally.
- Copy the
style.css
file from the generated output toISSUEDIR/static/html/style.css
. - Modify
style.css
as required, putting any extra static files (e.g., images referenced by the style sheet) in the same directory.
If you wanted to modify the stylesheet for all PyDitz projects, you’d copy
the files into subdirectories of HOMEDIR/.ditz
instead.
Modifying template files¶
If you want to modify a template, the same procedure applies: copy the
appropriate template file from the PyDitz installation directory to the
corresponding place below either the project issue directory or HOMEDIR/.ditz
,
and modify it. This involves knowing how Jinja2 templating works (which I
will summarize here when I get around to it ).
Builtin export formats¶
At the moment, there’s only one builtin export format: HTML. It has these static files:
style.css
: The HTML style sheet.
sorttable.js
: Some JavaScript to enable sorting of HTML tables. Referenced by the style sheet.
*.png
: The small images used to illustrate issue status, next to their titles, in the output.
and these template files:
base.html
: The base HTML page template all the others are derived from.
index.html
: Template for the main index page.
issue.html
: Template for a single issue page.
component.html
: Template for a component page.
release.html
: Template for a release summary page.
unassigned.html
: Template for the page of issues unassigned to any release.
macros.html
: Comon Jinja macros used by the other templates.
Creating new export formats¶
You can write your own PyDitz export formats by writing a plugin which subclasses the Exporter
class. An exporter has a
bunch of class attributes which you should set appropriately:
-
Exporter.
name
= None¶ Name of the exporter. This is the argument given to the
export
command.
-
Exporter.
description
= 'undocumented'¶ One-line description. This gets printed when you list the available export formats.
-
Exporter.
suffix
= None¶ Exporter file suffix. This is usually the same as the exporter name string.
-
Exporter.
static_dir
= None¶ If the exporter uses static files, this is the subdirectory of
static
to find them. Usually the same as thename
attribute.
-
Exporter.
template_dir
= None¶ If the exporter uses templates, this is the subdirectory of
templates
to find them. Usually the same as thename
attribute.
What happens during export¶
Here’s an outline of what happens on export:
The
setup()
method is called, to initialise Jinja filters and export configuration variables. Here’s where you can define filters (viaadd_filter()
) or configuration variables (via theconfig
attribute). The exporterdb
attribute is the Ditz issue database being exported, which you can use to set up the filters.-
Exporter.
add_filter
(func, name=None)[source]¶ Add a custom Jinja filter.
This returns the original function, so the method can be used as a decorator.
Parameters: - func (callable) – Filter function.
- name (str, optional) – Name to use in templates (same as function name, if None).
Returns: original function
Return type: func
-
The
write()
method is called to do the actual exporting. If using templates, this should use therender()
method to render them.The
export_filename()
method is available to create a standard filename for each issue database item, using the exporter suffix. Or, you can generate your own.-
Exporter.
write
(dirname)[source]¶ Write exported files to the given directory.
This method must be overridden. If using templates, it should call the
render()
method.Parameters: dirname (str) – Directory to write files into.
-
Exporter.
render
(dirname, templatefile, targetfile=None, **kw)[source]¶ Render a single file from a template.
Parameters: - dirname (str) – Directory to write file into.
- templatefile (str) – Jinja template to use.
- targetfile (str, optional) – Filename to write (same as templatefile, if None).
- kw (dict) – Template parameters.
-
The exporter has several attribute which can be used during setup and export:
The
db
attribute is a DitzDB object.The
config
attribute is a ConfigSection object which allows you to access those settings of the user configuration file which control the export.The values of these can be set in the
[export]
section of a config file, prepending the name of the exporter and an underscore. For example, for thehtml
exporter, the variablefoo
can be referred to ashtml_foo
.The
write()
method can access the value of configuration variables by calling methods of the exporter’sconfig
object.
Creating new PyDitz commands¶
New in version 0.9: Command plugins.
You can also write your own PyDitz commands by writing a plugin which subclasses the CommandSet
class. The class you
create should contain one more new commands as described in the Cmd
documentation—i.e., methods with names of the form do_cmd
and
help_cmd
. These are copied into the DitzCmd
class after loading the plugin, and you can use methods and attributes of
that class in your plugin.
Commands should use the write()
method to write output to the
console, and the error()
method to give an error message (and exit
the command). Here’s an example command plugin:
from ditz.commands import CommandSet
class AdventCommands(CommandSet):
name = 'advent'
description = 'adventuring commands'
def do_xyzzy(self, arg):
self.write("Nothing happens.")
def help_xyzzy(self):
self.write("xyzzy -- a secret magic word")
def do_plugh(self, arg):
"plugh -- another secret magic word"
self.write("Nothing happens.")
The DitzCmd
object has several attributes which can be used when
running the command:
The
db
attribute is a DitzDB object.The
config
attribute is a ConfigSection object which allows you to access those settings of the user configuration file which control how the command works.The values of these can be set in the
[command]
section of a user config file, prepending the name of the command and an underscore. For example, for thelog
command, the variablefoo
can be referred to aslog_foo
.
The PyDitz Customization API¶
Warning
This API may change incompatibly before PyDitz 1.0.
DitzCmd
– the command interpreter¶
-
DitzCmd.
db
= None¶ The
DitzDB
database.
-
DitzCmd.
interactive
= False¶ Whether running interactively.
-
DitzCmd.
getissue
(name)[source]¶ Get an issue by name or ID. Return it and its assigned name.
Parameters: name (str) – Issue name or ID. Returns: Tuple(Issue, str).
-
DitzCmd.
getrelease
(name)[source]¶ Get a release and return it.
Parameters: name (str or None) – Release name.
-
DitzCmd.
getline
(prompt='> ', default='', allowempty=True)[source]¶ Get a single line of input.
Parameters: - prompt (str) – Prompt string.
- default (str) – Default value.
- allowempty (bool) – Whether value is optional.
Returns: Reply (str).
-
DitzCmd.
gettext
(title=None, prompt='> ', endchar='.')[source]¶ Get multiline text.
Parameters: - title (str) – Initial title text.
- prompt (str) – Prompt for each line of input.
- endchar (str) – Character terminating input.
Returns: Text (str).
-
DitzCmd.
getchoice
(thing, choices)[source]¶ Get a choice of several things.
Parameters: - thing (str) – Description of thing being chosen.
- choices (list) – List of available options.
Returns: Choice made (str).
-
DitzCmd.
getcomment
(comment='')[source]¶ Get a comment string.
Parameters: comment (str) – Comment given in command option. Returns: Comment text (str).
-
DitzCmd.
getyesno
(question, default=False)[source]¶ Get the answer to a yes/no question.
Parameters: - question (str) – The question.
- default (bool) – Default if no reply given.
Returns: Reply (bool).
DitzDB
– an issue database¶
-
DitzDB.
project
= None¶ Project (a
Project
object).
-
DitzDB.
issues
= []¶ List of issues. Each entry is an
Issue
.
-
DitzDB.
issue_events
¶ Yield all issue-related events and their issues.
Each yielded event is a tuple containing:
- date (
datetime
) - user (string)
- description (string)
- comment (string)
- issue (
Issue
)
- date (
-
DitzDB.
convert_to_name
(text, idmap=None)[source]¶ Replace
{issue ...}
with names in issue text.Parameters: - text (str) – Text to convert.
- idmap (dict, optional) – ID mapping.
If the ID mapping is specified and contains the issue’s ID as a key, the replacement is the mapping value. Otherwise, it’s the issue’s name.
Returns: Converted text (str).
Project
– a container for components and releases¶
-
Project.
name
= ''¶ Name of the project.
-
Project.
components
= []¶ List of components. Each entry is a
Component
.
-
Project.
releases
= []¶ List of releases. Each entry is a
Release
.
Release
– a single release¶
-
Release.
name
= None¶ Name of the release.
-
Release.
released
¶ Whether release has actually been released.
Issue
– a single issue¶
-
Issue.
attributes
= ['title', 'desc', 'type', 'component', 'release', 'reporter', 'claimer', 'status', 'disposition', 'creation_time', 'references', 'id', 'log_events']¶ Attributes that get saved to file.
-
Issue.
name
¶ Name of the issue. This is the same as its title.
-
Issue.
closed
¶ Whether the issue is closed.
-
Issue.
progress_time
¶ Total seconds the issue’s state has been in-progress.
-
Issue.
references
= []¶ List of references. Each entry is a string.
-
Issue.
log_events
= []¶ List of log events. Each entry is a tuple of (time, username, text, comment).