🚦 Getting Started

Preparing the Project

1. Add the toolbox as dependency

poetry add --group dev exasol-toolbox

2. Fine tune the .gitignore file

Add the standard documentation output folder (.html-documentation) to the .gitignore.

echo ".html-documentation" >> .gitignore && git add .gitignore && git commit -m "Add documentation build folder to .gitignore"

3. Provide a project configuration

Make sure you provide the required configuration. Configuration for the exasol-toolbox gets provided by creating a noxconfig.py file in the workspace root. This file should contain at least a single module constant with the name PROJECT_CONFIG pointing to an object, which is required to to provide the following attributes:

  • root: Path
  • doc: Path
  • version_file: Path

Alternatively you can use the noxconfig.py file bellow and adjust the value of the attributes if needed:

"""Configuration for nox based task runner"""
from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path
from typing import (
    Any,
    Iterable,
    MutableMapping,
)

from nox import Session

from exasol.toolbox.nox.plugin import hookimpl
from exasol.toolbox.tools.replace_version import update_workflow


class UpdateTemplates:
    TEMPLATE_PATH: Path = Path(__file__).parent / "exasol" / "toolbox" / "templates"

    @property
    def workflows(self):
        gh_workflows = self.TEMPLATE_PATH / "github" / "workflows"
        gh_workflows = [f for f in gh_workflows.iterdir() if f.is_file()]
        return gh_workflows

    @hookimpl
    def prepare_release_update_version(self, session, config, version):
        for workflow in self.workflows:
            update_workflow(workflow, version)

    @hookimpl
    def prepare_release_add_files(self, session, config, add):
        add(session, self.workflows)


@dataclass(frozen=True)
class Config:
    """Project specific configuration used by nox infrastructure"""

    root: Path = Path(__file__).parent
    doc: Path = Path(__file__).parent / "doc"
    version_file: Path = Path(__file__).parent / "exasol" / "toolbox" / "version.py"
    path_filters: Iterable[str] = ("dist", ".eggs", "venv", "metrics-schema")
    plugins = [UpdateTemplates]

    @staticmethod
    def pre_integration_tests_hook(
        _session: Session, _config: Config, _context: MutableMapping[str, Any]
    ) -> bool:
        """Implement if project specific behaviour is required"""
        return True

    @staticmethod
    def post_integration_tests_hook(
        _session: Session, _config: Config, _context: MutableMapping[str, Any]
    ) -> bool:
        """Implement if project specific behaviour is required"""
        return True


PROJECT_CONFIG = Config()

4. Configure the tooling

In order to make all standard task work properly you need add the configuration settings bellow to your pyproject.toml, and adjust the following settings to your project needs:

  • coverage
    • source

    • fail_under

  • pylint
    • fail-under

  • mypy (overrides)
    • module

[tool.coverage.run]
relative_files = true
source = [
    "exasol",
]

[tool.coverage.report]
fail_under = 15


[tool.black]
line-length = 88
verbose = false
include = "\\.pyi?$"


[tool.isort]
profile = "black"
force_grid_wrap = 2


[tool.pylint.master]
fail-under = 7.5
output-format = "colorized,json:.lint.json,text:.lint.txt"

[tool.pylint.format]
max-line-length = 88
max-module-lines = 800


[[tool.mypy.overrides]]
module = [
    "exasol.toolbox.sphinx.multiversion.*",
    "test.unit.*",
    "test.integration.*",
]
ignore_errors = true

[tool.poetry.scripts]
tbx = 'exasol.toolbox.tools.tbx:CLI'

5. Make the toolbox task available

In order to use the standard toolbox task via nox, just import them in your noxfile.py. If you only need the standard tasks provided by the toolbox your noxfile.py is straight forward and you just can use the example noxfile.py bellow.

"""defines nox tasks/targets for this project"""
import nox

# imports all nox task provided by the toolbox
from exasol.toolbox.nox.tasks import *  # pylint: disable=wildcard-import disable=unused-wildcard-import

# default actions to be run if nothing is explicitly specified with the -s option
nox.options.sessions = ["fix"]


def main() -> None:
    """
    This excerpt was taken from nox.__main__.py. Generally, users should invoke Nox using the CLI provided by the Nox package.
    However, when using Nox directly, it spawns a process and therefore, debugging isn't straightforward.
    To cope with this issue, this entry point was added to enable a straightforward way to debug Nox tasks.
    """
    import sys
    from typing import Any

    from nox import (
        _options,
        tasks,
        workflow,
    )
    from nox._version import get_nox_version
    from nox.logger import setup_logging

    def execute_workflow(args: Any) -> int:
        """
        Execute the appropriate tasks.
        """
        return workflow.execute(
            global_config=args,
            workflow=(
                tasks.load_nox_module,
                tasks.merge_noxfile_options,
                tasks.discover_manifest,
                tasks.filter_manifest,
                tasks.honor_list_request,
                tasks.run_manifest,
                tasks.print_summary,
                tasks.create_report,
                tasks.final_reduce,
            ),
        )

    args = _options.options.parse_args()

    if args.help:
        _options.options.print_help()
        return

    if args.version:
        print(get_nox_version(), file=sys.stderr)
        return

    setup_logging(
        color=args.color, verbose=args.verbose, add_timestamp=args.add_timestamp
    )
    exit_code = execute_workflow(args)
    sys.exit(exit_code)


if __name__ == "__main__":  # pragma: no cover
    main()

6. Setup the pre-commit hooks

  1. Add the following .pre-commit-config.yaml to your project root

    default_stages: [ commit ]
    repos:
    
      - repo: local
        hooks:
          - id: code-format
            name: code-format
            types: [ python ]
            files: "pyproject.toml"
            pass_filenames: false
            language: system
            entry: poetry run nox -s fix
    
      - repo: local
        hooks:
          - id: type-check
            name: type-check
            types: [ python ]
            pass_filenames: false
            language: system
            entry: poetry run nox -s type-check
    
      - repo: local
        hooks:
          - id: lint
            name: lint
            types: [ python ]
            pass_filenames: false
            language: system
            entry: poetry run nox -s lint
    
      - repo: https://github.com/pre-commit/pre-commit-hooks
        rev: v4.4.0
        hooks:
          - id: check-yaml
          - id: end-of-file-fixer
          - id: trailing-whitespace
    
  2. Enable pre commit hooks for your workspace

    poetry run pre-commit install
    

7. Go 🥜

You are ready to use the toolbox. With nox -l you can list all available tasks.

$ nox -l
Sessions defined in <PATH_TO_YOUR_PROJECT>/noxfile.py:

* fix -> Runs all automated fixes on the code base
- check -> Runs all available checks on the project
- lint -> Runs the linter on the project
- type-check -> Runs the type checker on the project
- unit-tests -> Runs all unit tests
- integration-tests -> Runs the all integration tests
- coverage -> Runs all tests (unit + integration) and reports the code coverage
- build-docs -> Builds the project documentation
- open-docs -> Opens the built project documentation
- clean-docs -> Removes the documentations build folder
- report -> Collects and generates a metrics summary for the workspace

sessions marked with * are selected, sessions marked with - are skipped.

Enjoy!