Getting Started

With dwas installed, the next question is now, how do you configure and use it?

To get started, you need a dwasfile.py at the root of your project. This guide will help you through writing your first file.

In this example, we will guide you through writing a dwasfile.py that runs pytest against your project.

We will increase the complexity of the setup as we go, to show some of the constructs that dwas offers. For a complete example, you can always have a look at dwasown dwasfile.py.

1. Running pytest with the current python version

We will now define a step that runs pytest:

 1# The first thing is to import dwas, which will make available all the
 2# public API.
 3import dwas
 4
 5# This registers the step and makes it available to dwas.
 6# Additionally, it tells dwas that it requires dependencies, and list the
 7# ones that need to be installed.
 8#
 9# Note that if no dependency was required, you could have used
10# `@dwas.step()` instead.
11@dwas.managed_step(dependencies=["pytest"])
12# This defined the actual step, for dwas, a step is simply a function (or
13# a callable class)
14def pytest(step: dwas.StepRunner) -> None:
15    step.run(["pytest"])

And this is enough to run pytest in the current directory.

You can see now that dwas recognizes this step and that it would run by default:

dwas --list

And you can obviously run the step itself:

dwas
# Or, if you want to run this specific step:
dwas pytest

2. Running against multiple python versions (parametrization)

While the first example is already useful, we often want to run pytest against multiple versions of python, to ensure our programs is compatible.

We will show here how to do it, leveraging another construct of dwas, namely parametrization of steps.

In this example, we will run against python 3.9 to 3.12:

 1import dwas
 2
 3# As before, we register the step
 4@dwas.managed_step(dependencies=["pytest"])
 5# We now leverage a second decorator, to parametrize the step such that
 6# it runs against
 7# Note that the order of both decorators does not matter.
 8@dwas.parametrize("python", ["3.9", "3.10", "3.11", "3.12"])
 9# And as before, our method calling pytest
10def pytest(step: dwas.StepRunner) -> None:
11    step.run(["pytest"])

And as before, you can see the resulting steps by running:

dwas --list

You can note this time, that we have 5 steps defined, a pytest one, that, when referenced, will run all pytest steps, and 4 steps like pytest[version], which can be used to reference each individual steps.

Now try running some of them:

# Runs all steps, by default
dwas
# Runs pytest and all it's dependencies
dwas pytest
# Run only against python3.11
dwas pytest[3.11]

3. Using predefined (provided) step generators

While being able to write all your steps manually is great, if you have many different projects, it can be tedious to write the same code every time. For this, dwas provides some predefined, commonly used steps. Other packages can provide some too if wanted.

Here, we will see how to use the pytest step provided by dwas itself:

 1import dwas
 2# New import, all predefined steps by dwas
 3import dwas.predefined
 4
 5# Since we do not defined a method, we use `register_managed_step` instead
 6# here. It is functionally the same, but slightly nicer on reading.
 7dwas.register_managed_step(
 8    # Here, we parametrize again the pytest step to run against all versions
 9    dwas.parametrize("python", ["3.9", "3.10", "3.11", "3.12"])(
10        # And here, we add the predefined step for pytest
11        dwas.predefined.pytest(),
12    ),
13    dependencies=["pytest"],
14)

Which is functionally almost equivalent to the previous pytest step we have defined, though this step has more functionality. See dwas.predefined.pytest() for the full documentation about this step.

4. Dependencies between steps

While all the previous examples focused on a single step, there is often cases where you might want to have dependencies between them, for example, to avoid doing some work multiple times, or to gather data from multiple steps.

In this example. we will show how to easily:

  • Build a source distribution and wheel for your current python package

  • Run pytest with multiple versions of python against it

  • Give coverage report for all the tests.

This assumes you have such a project handy. If you don’t, you can follow looking at dwasown dwasfile.py.

 1import dwas
 2import dwas.predefined
 3
 4# A new step, this one builds the current package, and, when declared as
 5# a dependency of another step, will install it in the virtual environment
 6# of the dependent, before it runs.
 7dwas.register_managed_step(dwas.predefined.package())
 8
 9# Our well known pytest step, note the new `requires` config!
10dwas.register_managed_step(
11    # Here, we parametrize again the pytest step to run against all versions
12    dwas.parametrize("python", ["3.9", "3.10", "3.11", "3.12"])(
13        # And here, we add the predefined step for pytest
14        dwas.predefined.pytest(),
15    ),
16    dependencies=["pytest"],
17    # Declare the dependency on the previous step, this ensures that the
18    # package will be installed before we run tests.
19    requires=["package"],
20)
21
22# And finally coverage reports for all our tests
23dwas.register_managed_step(
24    dwas.predefined.coverage(),
25    requires=["pytest"],
26    dependencies=["coverage"],
27)

If you now try to list steps, you should this time see quite a few more:

dwas --list

Next Steps

Once you have understood the concepts here, the next steps would be to look at dwas' public API and it’s sibling provided predefined steps. For a real example, dwasown dwasfile.py is also a good resource.

If you think anything is missing from this starting guide or have suggestions on how to improve it, please submit an issue or open a pull request.