Makim for Nox Users¶
For those familiar with Nox, a command-line automation tool designed for testing across multiple Python environments, Makim presents a flexible alternative. While both tools serve automation purposes, they differ in configuration approach and scope.
Makim is not designed to supersede Nox or facilitate direct integration with it. The purpose of this guide is to highlight both the similarities and differences between the two tools, and to explore possible ways to integrate Nox tasks (sessions) within the Makim.
Initial Setup¶
To begin, ensure Nox is installed in your environment:
!pip install -q nox
Transitioning from Nox to Makim¶
Though Makim is not a direct replacement for Nox, understanding their similarities and differences can streamline the transition process for specific tasks or workflows. Consider the following Nox configuration:
%%writefile noxfile.py
import nox
@nox.session(name="custom-name")
def tests(session: nox.Session) -> None:
"""Run tests with pytest."""
session.install("pytest")
session.run("pytest", "--version")
@nox.session
def lint(session: nox.Session):
"""Run linters on the codebase."""
session.install('flake8')
# Example of using session.posargs for ad-hoc arguments
additional_args = session.posargs or []
session.run('flake8', '--version', *additional_args)
Overwriting noxfile.py
In this example, we are using --version
with pytest
and flake8
just to check if everything is working properly. In a real code, it should execute directly pytest
and flake8
.
Let's check how the nox list output (similar to a help output) would look like:
!nox --list
Sessions defined in /mnt/sda1/storage/dev/opensciencelabs-projects/osl-incubator/makim/docs/tutorials/noxfile.py: * custom-name -> Run tests with pytest. * lint -> Run linters on the codebase. sessions marked with * are selected, sessions marked with - are skipped.
NOTE: It appears that Nox does not offer a built-in, first-class method for displaying the arguments used by each Nox session.
We can also verify that the command functions as expected:
!nox
nox > Running session custom-name nox > Creating virtual environment (virtualenv) using python3.8 in .nox/custom-name nox > python -m pip install pytest nox > pytest --version pytest 8.1.1 nox > Session custom-name was successful. nox > Running session lint nox > Creating virtual environment (virtualenv) using python3.8 in .nox/lint nox > python -m pip install flake8 nox > flake8 --version 7.0.0 (mccabe: 0.7.0, pycodestyle: 2.11.1, pyflakes: 3.2.0) CPython 3.8.1 on Linux nox > Session lint was successful. nox > Ran multiple sessions: nox > * custom-name: success nox > * lint: success
It is working as expected!
To replicate this functionality in Makim, you would use a .makim.yaml
configuration file:
%%writefile .makim.yaml
version: 1.0
groups:
nox:
help: A set of functionality ported from noxfile.py
tasks:
tests:
help: Run tests with pytest
run: |
pytest --version
lint:
help: Run lint with flake8
args:
extras:
help: Extra arguments for flake8
type: string
default: "--version"
run: |
flake8 ${{ args.extras }}
Overwriting .makim.yaml
This example illustrates how to define similar testing and linting tasks within Makim's YAML-based configuration.
The default configuration file used by makim is .makim.yaml
, but if you want a different file name, you can run makim
with the flag --file
.
As you can see, it didn't install anything, because it assumes you already have all the dependencies there.
Of course, you can install whatever you want inside the Makim run
block, but it is much better to keep it in your pyproject.toml configuration.
In the future, makim will allow users to define specific virtual environments that could be used in a similar way as nox.
NOTE: This tutorial used makim version 1.15.0. The version 1.*
is still a beta version, so you maybe will find differences with future versions.
Before running the makim
command, please install it in your virtual environment: pip install "makim==1.15.0"
.
First, let's check how the makim help
menu looks like:
!makim --help
Usage: makim [OPTIONS] COMMAND [ARGS]... Makim is a tool that helps you to organize and simplify your helper commands. ╭─ Options ────────────────────────────────────────────────────────────────────╮ │ --version -v Show the version and exit │ │ --file TEXT Makim config file [default: .makim.yaml] │ │ --dry-run Execute the command in dry mode │ │ --verbose Execute the command in verbose mode │ │ --install-completion Install completion for the current │ │ shell. │ │ --show-completion Show completion for the current shell, │ │ to copy it or customize the │ │ installation. │ │ --help Show this message and exit. │ ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─ Commands ───────────────────────────────────────────────────────────────────╮ │ nox.lint Run lint with flake8 │ │ nox.tests Run tests with pytest │ ╰──────────────────────────────────────────────────────────────────────────────╯ If you have any problem, open an issue at: https://github.com/osl-incubator/makim
And if you want to check more details about a specific command:
!makim nox.lint --help
Makim file: .makim.yaml Usage: makim nox.lint [OPTIONS] Run lint with flake8 ╭─ Options ────────────────────────────────────────────────────────────────────╮ │ --extras TEXT Extra arguments for flake8 [default: --version] │ │ --help Show this message and exit. │ ╰──────────────────────────────────────────────────────────────────────────────╯
As you can see, it shows information about all the possible arguments for each command.
Understanding Makim's Approach¶
Makim enhances the automation process by focusing on direct command execution within predefined environments. Unlike Nox, which creates and manages virtual environments, Makim assumes dependencies are already installed, streamlining its operations.
Future versions of Makim plan to introduce more advanced virtual environment management, potentially aligning closer with Nox's functionality.
For more information about Makim, please read the Introduction tutorial.
Integrating Nox within Makim¶
While using Nox directly within a .makim.yaml
file might seem redundant, it demonstrates Makim's flexibility in accommodating various tools and workflows:
%%writefile .makim.yaml
version: 1.0
groups:
nox:
help: A set of functionality ported from noxfile.py
tasks:
run:
help: Run nox
args:
"ex":
help: Extra arguments for nox
type: string
default: ""
run: |
nox ${{ args.ex }}
Overwriting .makim.yaml
This configuration allows for the execution of Nox sessions through Makim, providing an extra layer of automation convenience.
!makim nox.run
Makim file: .makim.yaml nox > Running session custom-name nox > Creating virtual environment (virtualenv) using python3.8 in .nox/custom-name nox > python -m pip install pytest nox > pytest --version pytest 8.1.1 nox > Session custom-name was successful. nox > Running session lint nox > Creating virtual environment (virtualenv) using python3.8 in .nox/lint nox > python -m pip install flake8 nox > flake8 --version 7.0.0 (mccabe: 0.7.0, pycodestyle: 2.11.1, pyflakes: 3.2.0) CPython 3.8.1 on Linux nox > Session lint was successful. nox > Ran multiple sessions: nox > * custom-name: success nox > * lint: success
You can also run a specific nox session:
!makim nox.run --ex "-s lint"
Makim file: .makim.yaml nox > Running session lint nox > Creating virtual environment (virtualenv) using python3.8 in .nox/lint nox > python -m pip install flake8 nox > flake8 --version 7.0.0 (mccabe: 0.7.0, pycodestyle: 2.11.1, pyflakes: 3.2.0) CPython 3.8.1 on Linux nox > Session lint was successful.
Direct Noxfile Integration¶
In scenarios where integrating Nox sessions directly within Makim is preferred, Makim's shell
command can invoke Nox as the interpreter:
%%writefile .makim.yaml
version: 1.0
groups:
nox:
help: A set of functionality ported from noxfile.py
tasks:
tests:
help: Run nox tests
backend: nox
run: |
import nox
@nox.session(name="custom-name")
def tests(session: nox.Session) -> None:
"""Run tests with pytest."""
session.install("pytest")
session.run("pytest", "--version")
lint:
help: Run nox tests
backend: nox
run: |
import nox
@nox.session
def lint(session: nox.Session):
"""Run linters on the codebase."""
session.install('flake8')
session.run('flake8', '--version')
all:
help: Run nox tests
hooks:
pre-run:
- task: nox.tests
- task: nox.lint
Overwriting .makim.yaml
In this example, we created a task (task) for each Nox session. To execute the tests
task, just run:
!makim nox.tests
Makim file: .makim.yaml nox > Running session custom-name nox > Creating virtual environment (virtualenv) using python3.8 in .nox/custom-name nox > python -m pip install pytest nox > pytest --version pytest 8.1.1 nox > Session custom-name was successful.
To execute the lint
task, run:
!makim nox.lint
Makim file: .makim.yaml nox > Running session lint nox > Creating virtual environment (virtualenv) using python3.8 in .nox/lint nox > python -m pip install flake8 nox > flake8 --version 7.0.0 (mccabe: 0.7.0, pycodestyle: 2.11.1, pyflakes: 3.2.0) CPython 3.8.1 on Linux nox > Session lint was successful.
As we also created a task that has both tests
and lint
tasks as dependencies, so we can run both just running the all
task:
!makim nox.all
Makim file: .makim.yaml nox > Running session custom-name nox > Creating virtual environment (virtualenv) using python3.8 in .nox/custom-name nox > python -m pip install pytest nox > pytest --version pytest 8.1.1 nox > Session custom-name was successful. nox > Running session lint nox > Creating virtual environment (virtualenv) using python3.8 in .nox/lint nox > python -m pip install flake8 nox > flake8 --version 7.0.0 (mccabe: 0.7.0, pycodestyle: 2.11.1, pyflakes: 3.2.0) CPython 3.8.1 on Linux nox > Session lint was successful.
Concluding Thoughts¶
Integrating Nox within a Makim configuration might not always offer tangible benefits, and potentially introducing unnecessary complexity.
Although Nox offers robust automation capabilities, especially for testing across multiple Python environments, for projects where CI workflows are already optimized for environment-specific jobs, transitioning to Makim could simplify and streamline development processes.