Extending Pylease

Although Pylease is an Open Source project, it is impossible to consider and include all possible features at once. Moreover, one may want a particular feature urgently. Even after sending a feature request, he may have no time to wait for confirmation, implementation and release of that feature. On the other hand, Pylease may get too much loaded with features that does not get used by everyone.

For this reason, one of the major parts of Pylease is its modular extension system. It allows to develop a separate Python pakage and optionally plug it into Pylease.

So basically there are two ways to extend Pylease:

  • Add before and after tasks for existing commands
  • Add new commands

The following two subsections discuss both scenarios with their details.

Extending Existing Commands

Here is the step-by-setp guide on how to add extensions to Pylease.

The first step is inheriting the Extension class and adding it to your package __init__.py, where you will place the initialisation code by implementing the load() method. As an instance attribute you will have the _lizy attribute, which is an instance of Pylease class, and contains everything you need for your extension.

Extending an existing Pylease command is done by adding a BeforeTask or AfterTask (or both) to it using the Command methods add_before_task() and add_after_task(). What is needed to do is just implement those classes and add their instances to the command that is the subject of extension. For both BeforeTask and AfterTask you need to inherit and implement their execute() method, which must include the extension logic. Also, in case of AfterTask, you are provided with the _command_result attribute, which is the result returned by the command being extended.

So basically this is the scenario of extending a Pylease command:

Adding New Commands

To add a new command to Pylease it is enough to implement a class by inheriting the Command class and add it to your package __init__.py. Implementing the Command class is implementing the _process_command() method. As an additional convenience you can inherit the NamedCommand class instead. This will eliminate the need to manually specify the name of the command while calling the base constructor. Instead this base class will automatically parse the command name from the class name by removing the “Command” suffix and using the rest as the command name. So for example, the init command is defined as a child class of NamedCommand with the name InitCommand.

As in the case of implementing Extension, here you will also be provided with the Pylease lizy singleton.

Rollbacks

Even if you ship a perfectly clear extension, which will never crash in any conditions, you have no guarantee for others. As Pylease is a modular tool, it is possible to plug any number of independent extensions. This means that it is possible that after your extension task or command is executed, there may be another task executed after, that will lead to an error. In this case, you might need to rollback all the changes that your extension made to maintain the original state of the project.

For instance, the Git plugin makes a commit for the changes of version of the project, then creates a tag for the version. If any error raises after this operations, is it critical to roll them back. Thus, this plugin deletes the last commit and removes the created tag.

Pylease provides the Rollback class and Stage decorator to implement this feature in your extension. The Stage decorator enables to have a staged rollback. For example, in case of the Git plugin, if the error occurres in the stage of creating the version tag, the only rollback step to perform is deleting the last commit.

For reference on using this classes please see the Class Reference for Rollback and Stage