Plugins
This page documents the plugins that ship with the PyBuilder distribution.
QA plugins
Running Python Unittests
PyBuilder ships with a plugin to execute unittests written using Python’s unittest module
during the build. Use the python.unittest
plugin to enable unittest support.
The plugin executes all test cases found in modules ending with _tests.py
in the directory
src/unittest/python
.
Python unittest properties
Name | Type | Default Value | Description |
---|---|---|---|
teamcity_output | bool | False | Output teamcity service messages with test names and errors |
dir_source_unittest_python | string | src/unittest/python | Directory where unittest modules are located. |
unittest_module_glob | string | *_tests | Pattern used to filter Python modules that should be imported by the unittest runner. |
unittest_test_method_prefix | string | None | This allows you to define how the module unittest identifies tests. The plugin sets defaultTestLoader.testMethodPrefix to the given value. When set to None the plugin will not set the value at all. |
unittest_file_suffix | string | None | Suffix used to filter files that should be executed as tests. Deprecated: This exists for backwards compatibility with existing build.py files. If it is set to a non-None value, it will override unittest_module_glob with an appropriate glob pattern by prefixing the value with an asterisk (*) and removing the ".py" extension. |
Measuring unittest coverage
PyBuilder adds support to measure the coverage of your unittest using the coverage
module.
Use the python.coverage
module to activate coverage.
Coverage properties
Name | Type | Default Value | Description |
---|---|---|---|
coverage_threshold_warn | integer | 70 | Warn if the overall coverage drops below this threshold. |
coverage_branch_threshold_warn | integer | 0 | Warn if the branch coverage drops below this threshold. |
coverage_branch_partial_threshold_warn | integer | 0 | Warn if the branch partial coverage drops below this threshold. |
coverage_break_build | bool | True | Break the build (i.e. fail it) if the coverage is below the given threshold. |
coverage_allow_non_imported_modules | bool | True | Allow modules which were not imported by the covered tests. |
coverage_reset_modules | bool | False | Reset imported modules before coverage. |
coverage_exceptions | list of strings | empty | List of package names to exclude from coverage analyzation. |
Please note that properties coverage_reload_modules
and coverage_fork
are deprecated and will not be used.
SonarQube integration
Using the plugin python.sonarqube
will add the task run_sonar_analysis
to your project. This task has a run-time dependency to the sonar-runner
program and will submit your project to sonarqube for analysis.
SonarQube configuration
Name | Type | Default Value | Description |
---|---|---|---|
sonarqube_project_key | string | `project.name` | The SonarQube project key to use for analysis. |
sonarqube_project_name | string | `project.name` | The SonarQube project name to use for analysis. |
Linting python sources
Frosted plugin
Frosted is a fork of pyflakes (originally created by Phil Frost) that aims at more open contribution from the outside public, a smaller more maintainable code base, and a better Python checker for all.
Frosted configuration
Name | Type | Default Value | Description |
---|---|---|---|
frosted_break_build | boolean | False | Break the build if warnings are found |
frosted_include_test_sources | boolean | False | Also run frosted on integrationtest and unittest sources |
frosted_include_scripts | boolean | False | Also run the frosted linter on all files in $dir_source_main_scripts |
frosted_ignore | List of strings | [ ] | List of warnings to exclude Example: ["E205", "W101"] .See here, section Frosted error codes, for reference (or use frosted --verbose to check). |
Flake8 plugin
PyBuilder can lint your files and verify (or enforce) compliance with
PEP8 and PyFlakes through the flake8 module.
Use the python.flake8
module to activate linting.
Flake8 configuration
Name | Type | Default Value | Description |
---|---|---|---|
flake8_break_build | boolean | False | Break the build if warnings are found |
flake8_ignore | string | None | Comma separated list of error messages to ignore Example: "F403,W404,W801" |
flake8_include_scripts | boolean | False | Also run the flake8 linter on all files in $dir_source_main_scripts |
flake8_include_test_sources | boolean | False | Also run flake8 on integrationtest and unittest sources |
flake8_max_line_length | integer | 120 | Maximum allowed line length |
flake8_exclude_patterns | string | None, but flake8 comes with the default: .svn,CVS,.bzr,.hg,.git,__pycache__ |
Comma separated list of file patterns to exclude Example: ".git,__pycache__" |
flake8_verbose_output | boolean | False | Display flake8 warnings and errors in command line output. |
Pychecker plugin
Using the plugin python.pychecker
will let pychecker run on python source modules.
Pychecker configuration
Name | Type | Default Value | Description |
---|---|---|---|
pychecker_break_build | boolean | True | Break the build if warnings are found. |
pychecker_break_build_threshold | integer | 0 | Threshold to break the build. A threshold of `n` means: "break the build if more than `x` warnings are found". |
Pylint plugin
Using the plugin python.pylint
will let pylint run on python source modules.
Pylint configuration
Name | Type | Default Value | Description |
---|---|---|---|
pylint_options | list of strings | `["--max-line-length=100", "--no-docstring-rgx=.*"]` | Options to be passed to pylint |
Pep8 plugin
Using the plugin python.pep8
will let pep8 run on python sources.
There is no configuration possible currently, consider using the flake8 plugin instead.
Pymetrics plugin
Using the plugin python.pymetrics
will let pymetrics run on all python source files.
There is no configuration possible currently, consider using the flake8 plugin instead.
Running Python Integration Tests
PyBuilder ships with a plugin to run integration tests written in Python. The plugin is named
python.integrationtest
. It executes all python modules named *_tests.py
in the
src/integrationtest/python
directory.
However, the default run_integration_tests
job is just a stub per default
, which won’t run your integration tests. In order to use integration tests,
you will have to enable the module by specifying
use_plugin('python.integrationtest')
. If you don’t specify this,
your integration tests will not be run.
Every module is executed as a Python module. The Python path contains the integration test directory as well as the production source directory.
Integration test properties
Name | Type | Default Value | Description |
---|---|---|---|
teamcity_output | bool | False | Output teamcity service messages with test names and errors |
dir_source_integrationtest_python | string | src/integrationtest/python | Directory where integration test modules are located |
integrationtest_file_glob | string | *_tests.py | Pattern used to filter files that should be executed as tests. |
integrationtest_additional_environment | map | empty | Map containing additional environment variables used when executing the integration tests. |
integrationtest_additional_commandline | string | Not set | Additional command line arguments/commands to pass to the integration test call |
integrationtest_inherit_environment | boolean | False | Inherit the current environment to integration tests. |
integrationtest_parallel | boolean | False | Run integration tests in parallel. |
integrationtest_cpu_scaling_factor | integer | 4 | The amount of workers to use per cpu for integration test parallelization |
integrationtest_file_suffix | string | None | Suffix used to filter files that should be executed as tests. Deprecated: This exists for backwards compatibility with existing build.py files. If it is set to a non-None value, it will override integrationtest_file_glob with an appropriate glob pattern by prefixing the value with an asterisk (*). |
Python 3.2 warning
We have experienced strange problems (EOFErrors) on python 3.2. This seems to be due to a bug with pickling randomly raising EOFError. We recomment updating to python 3.3 or 3.4, where it works fine.Running Cram tests
The plugin python.cram
can be used to run tests written for cram. Cram tests run during run_integration_tests
but there is also a separate task available (run_cram_tests
).
Python 3.2.3 warning
Cram crashes on python 3.2.3 : https://bitbucket.org/brodie/cram/issue/28/crash-on-323 (no longer available). An easy workaround is to not use the plugin on python 3.2 :
if not sys.version_info[0:2] == (3,2):
use_plugin("python.cram")
Cram properties
Name | Type | Default Value | Description |
---|---|---|---|
dir_source_cmdlinetest | string | src/cmdlinetest | Directory where cram test files are located. |
cram_test_file_glob | string | *.t | Glob matching the cram test files |
cram_fail_if_no_tests | boolean | True | Fail if there are no cram tests |
cram_run_test_from_target | boolean | True | Run tests from the target or src directory. |
Python deployment
Python core
The python core plugin deals with sources and distributions. It copies the sources into the distribution directory.
Python core properties
Name | Type | Default Value | Description |
---|---|---|---|
dir_source_main_python | string | src/main/python | Directory where python modules are located. |
dir_source_main_scripts | string | src/main/scripts | Directory where runnable scripts are located. |
dir_dist | string | $dir_target/dist/$name-$version | Directory where distributions are built. |
dir_dist_scripts | string | scripts (starting with 0.10.40, before that scripts are simply copied to the dir_dist by default)</em> | Directory where scripts are copied to (relative to distribution directory). |
Installing dependencies
PyBuilder manages build and runtime dependencies for you.
Use the python.install_dependencies
module to activate dependency management.
This will make the following tasks available:
Task | Effect |
---|---|
install_build_dependencies | Installs build dependencies only |
install_runtime_dependencies | Installs runtime dependencies only |
install_dependencies | Installs all dependencies (build and runtime) |
Declaring dependencies
The project object exposes the following methods for declaring dependencies
Requirements file :
project.depends_on_requirements("requirements.txt")
project.build_depends_on_requirements("requirements-dev.txt")
Runtime dependencies :
project.depends_on("awesome-library")
Build dependencies :
project.build_depends_on("awesome-library")
Note that the *_depends_on
methods accept the following arguments :
Argument | Effect |
---|---|
name | Required positional argument. It's the name of the dependency on PyPI. |
version | Optional keyword argument (None default). Set it to a version string (example "==1.5.4" or ">=0.10" if necessary. |
url | Optional keyword argument (None default). Set it to an editable URL where the dependency should be downloaded from. |
The logic of version goes as follows:
- If you don’t specify any version, you don’t care about the version and any version will do, so PyB will get whatever version if one doesn’t exist and then don’t bother ever updating.
- If you specify an exact version once it is obtained there is no point in updating it.
- If you specify a fuzzy version, you want the latest and greatest that satisfies the expression specified. This aids rapid incompatibility detection, as PyBuilder tracks the latest version that always satisfies the version specifier.
Install dependencies configuration
Name | Type | Default Value | Description |
---|---|---|---|
dir_install_logs | string | $dir_logs/install_dependencies | Where installation logs should be saved. |
install_dependencies_index_url | string | None | Index URL to use with pip (None means use the pip default). |
install_dependencies_extra_index_url | string | None | Extra index url to use with pip. |
install_dependencies_use_mirrors | boolean | True | Enables the use of PyPI mirros for pip operations. |
install_dependencies_upgrade | boolean | False | If dependencies are already available, try to upgrade them instead. |
install_dependencies_insecure_installation | List of strings | [ ] |
Tell newer versions of pip that it's OK to install those dependencies insecurely (externally hosted, potentially unverified) |
Creating a source distribution
PyBuilder can build a source distribution of your code with the plugin source_distribution
. Activating this plugin will expose a task, build_source_distribution
.
Source distribution configuration
Name | Type | Default Value | Description |
---|---|---|---|
dir_source_dist | string | $dir_target/dist/$(project.name)-$(project.version)-src | Where the source distribution should be created. |
source_dist_ignore_patterns | list of strings | ["*.pyc", ".hg*", ".svn", ".CVS"] | Patterns to ignore when copying sources for the source distribution. |
Building a Python package
PyBuilder ships a plugin that generates and executes setup.py files using with distutils or setuptools (distribute will
be supported in future releases). In order to generate a setup.py
file use the python.distutils
plugin.
The distutils plugin will consider many of the project’s attributes, i.e.
- name
- version
- summary
- description
- author
- license
- url
Moving scripts to a nested directory
By default, executable scripts are located at the egg’s root. The setup.py
contains the bare script names.
Sometimes though you may want to move the scripts inside a directory to avoid naming collisions (i.e. with
packages).
The python.core
and python.distutils
plugins support the property dir_dist_scripts
that
can name a directory to contain scripts inside the egg. This property is empty by default. Set it to the local name
of the directory you want the scripts to be moved to:
@init
def initialize (project):
project.set_property("dir_dist_scripts", 'scripts')
...
Distutils properties
Name | Type | Default Value | Description |
---|---|---|---|
distutils_commands | list of strings | sdist, bdist_dump | Commands to execute using the generated setup.py script during publish |
distutils_command_options | dictionary | None | Additional options for distutils_commands values. Has to be provided as dictionary of key:value pairs where key is distutils_commands list value and value is list of additional parameters for this distutils_commands command. |
distutils_classifiers | list of strings | Development Status :: 3 - Alpha Programming Language :: Python |
Classifiers describing the project; see http://pypi.python.org/pypi?%3Aaction=list_classifiers |
distutils_upload_repository | string | None | The PyPI repository to upload the package to |
distutils_upload_sign | boolean | False | Sign each uploaded file using GPG (GNU Privacy Guard) |
distutils_upload_sign_identity | string | None | The identity to sign each file with, when distutils_upload_sign is True |
distutils_use_setuptools | boolean | True | Use setuptools instead of distutils |
distutils_readme_description | boolean | False | Get description and summary project properties from readme file |
distutils_readme_file | string | README.md | Relative path of readme file for distutils_readme_description property |
distutils_description_overwrite | boolean | False | Overwrite description and summary project properties if even set |
distutils_console_scripts | list of strings | None | Array of console scripts for entry_points argument into setup.py file. Cannot be used with distutils_entry_points |
distutils_entry_points | dictionary | None | Entry points for entry_points argument into setup.py file. Could include console_scripts section. Cannot be used with distutils_console_scripts |
distutils_setup_keywords | list of strings or string | None | Setup keywords for setup_keywords argument into setup.py file. |
distutils_issue8876_workaround_enabled | boolean | False | Deny distutils the use of hardlinks for creating binary distributions |
Each distutils_commands
is called individually with clean --all
parameter.
The reason that clean --all
is used is to ensure that if PyBuilder is generating multiple packages (bdist_wheel
vs dumb
vs bdist
) that the build/
directory doesn’t cross-contaminate the builds. Some use absolute paths, some use relative.
VirtualBox pitfall with binary dists
If you build your project on a shared filesystem (e.G. with vagrant/Virtualbox virtualization) then distutils is unable to build a binary distribution due to a python stdlib bug. Setting the propertydistutils_issue8876_workaround_enabled
to True (off by default) will work around this for you.
Distutils property examples
distutils_command_options
project.set_property('distutils_commands', 'build')
project.set_property('distutils_command_options',
{'build': ('-e', '/opt/python2.7/bin/python', 'bdist_wheel')})
distutils_console_scripts
project.set_property('distutils_console_scripts', [
"some_console1 = some_module1:some_function1",
"some_console2 = some_package.some_module2:some_function2"])
distutils_entry_points
project.set_property('distutils_entry_points', {
'console_scripts': [
"some_console1 = some_module1:some_function1",
"some_console2 = some_package.some_module2:some_function2"],
'some.entry.point': [
'value1 = some_module3:some_function3',
'value2 = some_module4:some_function4']})
Copying resources into a distribution
In some cases you want to include non-source files in a distribution. An example is adding a setup.cfg
to your project. It is not a source file, but it needs to be in the distribution to work (beneath the setup.py
file).
The copy_resources
plugin will do this for you at build-time.
Copy resources configuration
Name | Type | Default Value | Description |
---|---|---|---|
copy_resources_target | string | $dir_target | Where resources should be copied to. |
copy_resources_glob | list of strings | [] | A list of globs matching files that should be copied to $copy_resources_target . |
Filtering files
With the filter_resources
plugin, it is possible to replace placeholder values of type ${version}
with actual values at build-time.
The actual values are the attributes and the properties dict of the project
object. So ${version}
will be replaced with the value of project.version
and ${some_property}
by project.get_property('some_property')
.
In order to make resource filtering explicit, all files that go through filtering need to be specified with a glob.
Filter resources configuration
Name | Type | Default Value | Description |
---|---|---|---|
filter_resources_target | string | $dir_target | Toplevel directory containing the resources to be filtered. |
filter_resources_glob | list of strings | [] | A list of globs matching files that should be filtered. |
Filter resources example
A common use case is keeping a __version__
attribute in your main module.
But you don’t want to specify the version both in build.py
and in __init__.py
because build.py
should be the single point of truth.
So just use __version__ = '${version}'
in __init__.py
.
We can tell the plugin to filter this file by adding ['**/YOUR-PACKAGE-NAME/__init__.py']
to the filter_resources_glob
.
The correct version will be patched in at run-time since the version is defined in project.version
.
For filtering other attributes like ${myattribute}
, just add a project.myattribute = "foobar"
in build.py
’s initializer.
Creating documentation with sphinx
The plugin python.sphinx
will expose the task sphinx_generate_documentation
which will generate the project documentation.
Sphinx plugin configuration
Name | Type | Default Value | Description |
---|---|---|---|
sphinx_builder | string | html | The sphinx builder to use |
sphinx_config_path | string | "" | The path to the sphinx configuration |
sphinx_source_dir | string | "" | The path to the sphinx sources |
sphinx_output_dir | string | "_build/" | The path to the sphinx output directory where the documentation will be generated |
Generic build plugins
Executing shell commands
PyBuilder ships with a plugin that allows you to incorporate arbitrary shell commands in the build process.
This plugin can be activated using use_plugin("exec")
and is configured through
the project properties.
Adding a shell command to the build process
Adding commands is done by setting properties and is discrete towards the project lifecycles, thus you may have only one shell command for the analyze lifecycle for example.
Name | Type | Description |
---|---|---|
run_unit_tests_command | string | Run a shell command during run_unit_tests |
run_integration_tests_command | string | Run a shell command during run_integration_tests |
analyze_command | string | Run a shell command during analyze |
package_command | string | Run a shell command during package |
publish_command | string | Run a shell command during publish |
The output of the plugin can also be customized by using the properties
$PHASE_propagate_stdout
and $PHASE_propagate_stderr
.
See the properties for the phase run_unit_tests
for example:
Name | Type | Default | Description |
---|---|---|---|
run_unit_tests_propagate_stdout | string | False | Propagate the stdout of the command to the PyBuilder output |
run_unit_tests_propagate_stderr | string | False | Propagate the stdout of the command to the PyBuilder output |
IDE integration
Project files for Eclipse PyDev
If the plugin python.pydev
is used, PyBuilder provides the task pydev_generate
.
This task can be used to generate PyDev project files in the project root directory. The project can then be imported easily.
Project files for Jetbrains PyCharm
If the plugin python.pycharm
is used, PyBuilder provides the task pycharm_generate
.
This task can be used to generate a PyCharm project files in the project root directory. The project can then be imported easily through the Open...
command.
Developer tools
Visual feedback for tests
The python.pytddmon
plugin provides the task pytddmon
which will start a graphical application that gives real-time feedback about passing or failing unit tests.
Please see the pytddmon page (http://pytddmon.org/ broken link) for more information about pytddmon.
Additional project structure
Splitting up your build.py
with bldsup
Maybe you want to have project specific plugins and support code while keeping your build.py file small, while avoiding to clutter your project’s root directory. This can be done by activating bldsup support :
from pybuilder.core import use_bldsup
use_bldsup(build_support_dir="bldsup")
If it’s not called in a project’s build.py, then no “bldsup” directory is searched. If it is called, then it confirms that the build_support_dir directory exists and that includes a __init__.py
file so imports will work. It just needs to be called before you try to import
/use_plugin()
any modules from the build_support_dir
.