pycommons.dev.building package

Tools for building python projects.

Submodules

pycommons.dev.building.build_info module

The project build information.

class pycommons.dev.building.build_info.BuildInfo(base_dir, package_name, tests_dir=None, examples_dir=None, doc_source_dir=None, doc_dest_dir=None, dist_dir=None, timeout=3600)[source]

Bases: object

A class that represents information about building a project.

>>> b = BuildInfo(Path(__file__).up(4), "pycommons", "tests", "examples",
...         "docs/source", "docs/build", "dist")
>>> b.base_dir == Path(__file__).up(4)
True
>>> b.package_name
'pycommons'
>>> b.sources_dir.endswith('pycommons')
True
>>> b.examples_dir.endswith('examples')
True
>>> b.tests_dir.endswith('tests')
True
>>> b.doc_source_dir.endswith('source')
True
>>> b.doc_dest_dir.endswith('build')
True
>>> b.dist_dir.endswith('dist')
True
>>> try:
...     BuildInfo(None, "pycommons")
... except TypeError as te:
...     print(te)
descriptor '__len__' requires a 'str' object but received a 'NoneType'
>>> try:
...     BuildInfo(1, "pycommons")
... except TypeError as te:
...     print(te)
descriptor '__len__' requires a 'str' object but received a 'int'
>>> try:
...     BuildInfo(Path(__file__).up(4), None)
... except TypeError as te:
...     print(te)
descriptor 'strip' for 'str' objects doesn't apply to a 'NoneType' object
>>> try:
...     BuildInfo(Path(__file__).up(4), 1)
... except TypeError as te:
...     print(te)
descriptor 'strip' for 'str' objects doesn't apply to a 'int' object
>>> try:
...     BuildInfo(Path(__file__).up(4), "")
... except ValueError as ve:
...     print(ve)
Relative path must not be empty.
>>> try:
...     BuildInfo(Path(__file__).up(4), ".")
... except ValueError as ve:
...     print(str(ve)[:32])
Inconsistent directories ['.', '
>>> try:
...     BuildInfo(Path(__file__).up(4), "..")
... except ValueError as ve:
...     print("does not contain" in str(ve))
True
>>> try:
...     BuildInfo(Path(__file__).up(4), "pycommons", 1)
... except TypeError as te:
...     print(te)
descriptor 'strip' for 'str' objects doesn't apply to a 'int' object
>>> try:
...     BuildInfo(Path(__file__).up(4), "pycommons", "..")
... except ValueError as ve:
...     print("does not contain" in str(ve))
True
>>> try:
...     BuildInfo(Path(__file__).up(4), "pycommons", ".")
... except ValueError as ve:
...     print(str(ve)[:27])
Inconsistent directories ['
>>> try:
...     BuildInfo(Path(__file__).up(4), "pycommons", None, 1)
... except TypeError as te:
...     print(te)
descriptor 'strip' for 'str' objects doesn't apply to a 'int' object
>>> try:
...     BuildInfo(Path(__file__).up(4), "pycommons", None, "..")
... except ValueError as ve:
...     print("does not contain" in str(ve))
True
>>> try:
...     BuildInfo(Path(__file__).up(4), "pycommons", None, ".")
... except ValueError as ve:
...     print(str(ve)[:27])
Inconsistent directories ['
>>> try:
...     BuildInfo(Path(__file__).up(4), "pycommons", doc_source_dir=1)
... except TypeError as te:
...     print(te)
descriptor 'strip' for 'str' objects doesn't apply to a 'int' object
>>> try:
...     BuildInfo(Path(__file__).up(4), "pycommons", doc_dest_dir=1)
... except TypeError as te:
...     print(te)
descriptor 'strip' for 'str' objects doesn't apply to a 'int' object
>>> try:
...     BuildInfo(Path(__file__).up(4), "pycommons", dist_dir=1)
... except TypeError as te:
...     print(te)
descriptor 'strip' for 'str' objects doesn't apply to a 'int' object
>>> try:
...     BuildInfo(Path(__file__).up(4), "pycommons",
...          doc_source_dir="docs", doc_dest_dir="docs/build")
... except ValueError as ve:
...     print(str(ve)[:20])
Nested directories '
base_dir: Path

the path to the project base directory

command(args)[source]

Create a typical build step command.

Parameters:

args (Iterable[str]) – the arguments of the command

>>> b = BuildInfo(Path(__file__).up(4), "pycommons")
>>> cmd = b.command(("cat", "README.txt"))
>>> cmd.working_dir == b.base_dir
True
>>> cmd.command
('cat', 'README.txt')
>>> cmd.timeout
3600
>>> cmd.stderr == STREAM_FORWARD
True
>>> cmd.stdout == STREAM_FORWARD
:rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~pycommons.processes.shell.Command\``
True
>>> cmd.timeout
3600
dist_dir: Path | None

the directory where the distribution files should be located

doc_dest_dir: Path | None

the destination directory for documentation

doc_source_dir: Path | None

the source directory for documentation

examples_dir: Path | None

the path to the examples directory, if any

package_name: str

the name of the project / package

sources_dir: Path

the path to the directory with the package sources

tests_dir: Path | None

the path to the tests directory, if any

timeout: int

the standard timeout

pycommons.dev.building.build_info.parse_project_arguments(parser, args=None)[source]

Load project information arguments from the command line.

Parameters:
>>> from pycommons.io.arguments import pycommons_argparser
>>> ap = pycommons_argparser(__file__, "a test program",
...     "An argument parser for testing this function.")
>>> ee = parse_project_arguments(ap, ["--root", Path(__file__).up(4),
...                              "--package", "pycommons"])
>>> ee.package_name
'pycommons'
>>> ee.sources_dir.endswith("pycommons")
True
>>> ee.dist_dir.endswith("dist")
True
>>> ee.doc_source_dir.endswith("docs/source")
True
>>> ee.doc_dest_dir.endswith("docs/build")
True
>>> ee.examples_dir.endswith("examples")
:rtype: :sphinx_autodoc_typehints_type:`\:py\:class\:\`\~pycommons.dev.building.build\_info.BuildInfo\``
True
>>> ee.tests_dir.endswith("tests")
True
>>> try:
...     parse_project_arguments(None)
... except TypeError as te:
...     print(te)
parser should be an instance of argparse.ArgumentParser but is None.
>>> try:
...     parse_project_arguments(1)
... except TypeError as te:
...     print(str(te)[:40])
parser should be an instance of argparse
pycommons.dev.building.build_info.replace_in_cmd(orig, replace_with, replace_what='.')[source]

Replace the occurrences of replace_what with replace_with.

Parameters:
  • orig (Iterable[str]) – the original sequence

  • replace_with (str) – the string it is to be replace with

  • replace_what (str, default: '.') – the string to be replaced

Return type:

Iterable[str]

Returns:

the replaced sequence

>>> replace_in_cmd(('x', '.', 'y'), 'a', '.')
['x', 'a', 'y']
>>> replace_in_cmd(('x', '.', 'y'), 'a')
['x', 'a', 'y']
>>> try:
...     replace_in_cmd(None, 'a', '.')
... except TypeError as te:
...     print(te)
orig should be an instance of typing.Iterable but is None.
>>> try:
...     replace_in_cmd(1, 'a', '.')
... except TypeError as te:
...     print(te)
orig should be an instance of typing.Iterable but is int, namely '1'.
>>> try:
...     replace_in_cmd([], 'a', '.')
... except ValueError as ve:
...     print(ve)
Did not find '.'.
>>> try:
...     replace_in_cmd(['x'], 'a', '.')
... except ValueError as ve:
...     print(ve)
Did not find '.'.
>>> try:
...     replace_in_cmd(['x'], 'a')
... except ValueError as ve:
...     print(ve)
Did not find '.'.
>>> try:
...     replace_in_cmd(['x'], None, '.')
... except TypeError as te:
...     print(te)
descriptor '__len__' requires a 'str' object but received a 'NoneType'
>>> try:
...     replace_in_cmd(['x'], 1, '.')
... except TypeError as te:
...     print(te)
descriptor '__len__' requires a 'str' object but received a 'int'
>>> try:
...     replace_in_cmd(['x'], '', '.')
... except ValueError as ve:
...     print(ve)
Invalid replace_with ''.
>>> try:
...     replace_in_cmd(['x'], 'y', None)
... except TypeError as te:
...     print(te)
descriptor '__len__' requires a 'str' object but received a 'NoneType'
>>> try:
...     replace_in_cmd(['x'], 'y', 1)
... except TypeError as te:
...     print(te)
descriptor '__len__' requires a 'str' object but received a 'int'
>>> try:
...     replace_in_cmd(['x'], 'x', '')
... except ValueError as ve:
...     print(ve)
Invalid replace_what ''.

pycommons.dev.building.make_dist module

Make the distribution.

pycommons.dev.building.make_dist.make_dist(info)[source]

Create the distribution files.

This code cannot really be unit tested, as it would run the itself recursively.

Parameters:

info (BuildInfo) – the build information

>>> root = Path(__file__).up(4)
>>> bf = BuildInfo(root, "pycommons",
...     examples_dir=root.resolve_inside("examples"),
...     tests_dir=root.resolve_inside("tests"),
...     dist_dir=root.resolve_inside("dist"),
...     doc_source_dir=root.resolve_inside("docs/source"),
...     doc_dest_dir=root.resolve_inside("docs/build"))
>>> from io import StringIO
>>> from contextlib import redirect_stdout
>>> sio = StringIO()
>>> with redirect_stdout(sio):
:rtype: :sphinx_autodoc_typehints_type:`\:py\:obj\:\`None\``
...     make_dist(bf)
>>> "Finished building distribution" in sio.getvalue()
True
>>> try:
...     make_dist(None)
... except TypeError as te:
...     print(str(te)[:50])
info should be an instance of pycommons.dev.buildi
>>> try:
...     make_dist(1)
... except TypeError as te:
...     print(str(te)[:50])
info should be an instance of pycommons.dev.buildi

pycommons.dev.building.make_documentation module

Create the documentation.

pycommons.dev.building.make_documentation.make_documentation(info)[source]

Make the documentation of the project.

Parameters:

info (BuildInfo) – the build information

>>> root = Path(__file__).up(4)
>>> bf = BuildInfo(root, "pycommons",
...     examples_dir=root.resolve_inside("examples"),
...     tests_dir=root.resolve_inside("tests"),
...     doc_source_dir=root.resolve_inside("docs/source"),
...     doc_dest_dir=root.resolve_inside("docs/build"))
>>> from io import StringIO
>>> from contextlib import redirect_stdout
>>> sio = StringIO()
>>> with redirect_stdout(sio):
:rtype: :sphinx_autodoc_typehints_type:`\:py\:obj\:\`None\``
...     make_documentation(bf)
>>> "Finished building documentation" in sio.getvalue()
True

pycommons.dev.building.run_tests module

Run the pytest tests.

pycommons.dev.building.run_tests.run_tests(info)[source]

Perform the unit testing of the project.

This code cannot really be unit tested, as it would run the itself recursively.

Parameters:

info (BuildInfo) – the build information

>>> try:
...     run_tests(None)
:rtype: :sphinx_autodoc_typehints_type:`\:py\:obj\:\`None\``
... except TypeError as te:
...     print(str(te)[:50])
info should be an instance of pycommons.dev.buildi
>>> try:
...     run_tests(1)
... except TypeError as te:
...     print(str(te)[:50])
info should be an instance of pycommons.dev.buildi

pycommons.dev.building.static_analysis module

Perform the static code analysis.

pycommons.dev.building.static_analysis.static_analysis(info)[source]

Perform the static code analysis for a Python project.

Parameters:

info (BuildInfo) – the build information

>>> from io import StringIO
>>> from contextlib import redirect_stdout
>>> s = StringIO()
>>> with redirect_stdout(s):
...     static_analysis(BuildInfo(
...         Path(__file__).up(4), "pycommons", "tests",
:rtype: :sphinx_autodoc_typehints_type:`\:py\:obj\:\`None\``
...             "examples", "docs/source"))
>>> "Successfully completed" in s.getvalue()
True
>>> try:
...     static_analysis(None)
... except TypeError as te:
...     print(str(te)[:50])
info should be an instance of pycommons.dev.buildi
>>> try:
...     static_analysis(1)
... except TypeError as te:
...     print(str(te)[:50])
info should be an instance of pycommons.dev.buildi