Getting Started

Your usage of the exasol-toolbox will likely fall into one of two scenarios:

  1. Integration into an existing project.

    If this is your situation, proceed to the section titled Integrating Exasol-Toolbox into your Project.

  2. Creation of a new project.

    If you are starting a new project, please read the section Create a New Project with Exasol-Toolbox Support.

Create a New Project with Exasol-Toolbox Support

Important

To establish a new project with toolbox support, you need to have Cookiecutter installed.

TL;DR:

pipx install cookiecutter

1. Create a new project

Cookiecutter will create the project within the current directory. So if you usually checkout all your GitHub repos in ~/git you could use cd ~/git before calling cookiecutter.

Use the following command to create a new project:

cookiecutter https://github.com/exasol/python-toolbox.git \
  --directory project-template

2. Follow the interactive project setup prompt

3. Bootstrapp the development environment

Navigate to the directory of the newly created project:

cd <your-project-name>

Generate a poetry environment for the project:

poetry shell

Install all necessary project and development dependencies for the project:

poetry install

4. Start using your project

List all available nox tasks:

nox -l

Build and open the documentation:

nox -s docs:build  docs:open

Execute the unit tests of the project:

nox -s test:unit

Integrating Exasol-Toolbox into your 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:

Note

Be aware that the plugin definitions are completely optional. For further details on plugins, see the customization section.

"""Configuration for nox based task runner"""

from __future__ import annotations

from collections.abc import Iterable
from dataclasses import dataclass
from pathlib import Path

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):
        return 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"
    importlinter: Path = Path(__file__).parent / ".import_linter_config"
    version_file: Path = Path(__file__).parent / "exasol" / "toolbox" / "version.py"
    path_filters: Iterable[str] = (
        "dist",
        ".eggs",
        "venv",
        "metrics-schema",
        "project-template",
        "idioms",
    )
    plugins = [UpdateTemplates]


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

[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.plugins."console_scripts"]
"version-check" = "exasol.toolbox.pre_commit_hooks.package_version:main"


[tool.poetry.scripts]
tbx = 'exasol.toolbox.tools.tbx:CLI'
sphinx-multiversion = 'exasol.toolbox.sphinx.multiversion:main'

5. Make the toolbox tasks 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 = ["project:fix"]


Attention

Keep in mind that the current path may not be included in the PYTHONPATH, depending on the operating system you are using. This is explained in more detail in this resource: https://fedoraproject.org/wiki/Changes/PythonSafePath. Thus, it might be necessary to properly set the PYTHONPATH before running nox. This is because our nox tasks expect the noxconfig module to be located within the python path.

For additional information on resolving this issue, please refer to.

6. Setup the pre-commit hooks [optional]

  1. Add a .pre-commit-config.yaml file to your project root

    If you want to reuse Nox tasks in the pre-commit hooks, feel free to get some inspiration from the Python toolbox itself:

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

    poetry run pre-commit install --hook-type pre-commit --hook-type pre-push
    

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:

* project:fix -> Runs all automated fixes on the code base
- project:check -> Runs all available checks on the project
- project:report -> Collects and generates metrics summary for the workspace
- test:unit -> Runs all unit tests
- test:integration -> Runs the all integration tests
- test:coverage -> Runs all tests (unit + integration) and reports the code coverage
- lint:code -> Runs the static code analyzer on the project
- lint:typing -> Runs the type checker on the project
- lint:security -> Runs the security linter on the project
- lint:dependencies -> Checks if only valid sources of dependencies are used
- docs:multiversion -> Builds the multiversion project documentation
- docs:build -> Builds the project documentation
- docs:open -> Opens the built project documentation
- docs:clean -> Removes the documentations build folder
- release:prepare -> Prepares the project for a new release.

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

Enjoy!

Note

The targets and their names may change over time, so the list below may not be up to date, as it is not automatically generated yet. Therefore, if you find discrepancies, please submit a quick PR to address them.