Contributing

Thank you for your interest in contributing! Contributions are very welcome. 😊


Bug reports and feature requests

Before opening an issue, please search existing issues to avoid duplicates. If an issue exists, you can add a comment with additional details and/or upvote (👍) the issue. If there is not an existing issue, please open one and provide as much detail as possible.

For feature requests or documentation improvements, please describe your suggestion clearly.

For bugs, include: * Steps to reproduce. * Expected and actual behaviour. * Environment details (operating system, python version, dependencies). * Relevant files (e.g. problematic .qmd files).


Code contributions

  1. Fork the repository.

  2. Create a new branch for your feature or fix.

  3. Make your changes and commit them with clear, descriptive messages using the conventional commits standard.

  4. Open a pull request against our repository. Describe your changes and reference any related issues.


Development environment

If you want to contribute to lintquarto or run its tests, you’ll need some additional tools. These are declared in pyproject.toml as:

  • The all extra under [project.optional-dependencies] (all possible linters and code checkers).
  • The dev dependency group under [dependency-groups] (packaging, docs, tests, etc.).

Set up a Python environment using your preferred tool (e.g., conda, uv, etc.) then activate it. For example, to work with conda:

conda create -n lintquarto python=3.12
conda activate lintquarto

From the project root, install the package in editable mode with all supported code quality tools:

pip install -e ".[all]"

Then install the development dependencies declared in pyproject.toml:

pip install --group dev

Confirm the required packages are installed:

pip list

Note: On 10 February 2026, found incompatible quartodoc and griffe, so had to lock griffe at 1.14.0.

Quarto

Quarto (used for the docs) is a standalone tool - install it from https://quarto.org/docs/get-started/.


Tests

Run all tests (with coverage):

pytest --cov

Run an individual test file:

pytest tests/test_back.py

Run a specific test:

pytest tests/test_linters.py::test_supported_error


Style

This project uses Ruff and lintquarto for linting and formatting checks.

Ruff configuration, including exclusions and per-file ignores, is defined in pyproject.toml. To run:

ruff format
ruff check --fix

We follow the numpydoc style for docstrings.

Pre-commit

Install pre-commit hooks:

pre-commit install

Not running in the right environment? You may find the pre-commit fails if it is using the wrong environment - I’ve found this to be the case in VSCode. I’ve found the simplest way to fix this is to work on the command line, activate the environment, and then either do the commit directly there (i.e., git add, git commit) or launch VS Code (code .) which ensures it inherits the environment.

Unstaged files detected If you see [WARNING] Unstaged files detected during commit, this is normal; pre-commit is just temporarily saving your unstaged changes. The real blocker is any “linting failed” message or linter error output that follows—fix those errors in the listed files, re-stage, and commit again! This message can occur when there are linting issues in your staged files when trying to commit, but you also have some unstaged files present. With no unstaged files present, message will be like Git: Lint Package...... failed.


Documentation

Build and preview the documentation locally:

make -C docs

When running this, function documentation will be automatically generated from the codebase using quartodoc


Supported python versions

lintquarto supports only actively maintained Python versions. Python 3.7 is end-of-life and Python 3.8 is in security-fix-only mode.

Historically, the package targeted Python 3.7+ because the codebase depended on features introduced in Python 3.5-3.7 (e.g., subprocess.run(), f-strings, and text=True in subprocess.run()). We have since dropped 3.7 and 3.8 to align with current practice.

This follows NEP 29 guidance used across the scientific Python ecosystem and keeps our tooling, packaging, and test matrix manageable.

Python 3.9 support is not possible, as this package uses the tree-sitter-markdown package which requires Python 3.10+ and above.


Updating the package

Preparation

Before proceeding, you will need to have cloned the lintquarto/staged-recipes repository which is used to push updates to conda.

git clone https://github.com/lintquarto/staged-recipes

Workflow for updates

If you are a maintainer and need to publish a new release:

  1. Update the CHANGELOG.md.

  2. Update the version number in __init__.py, CITATION.cff and README.md citation, and update the date in CITATION.cff.

  3. Create a release on GitHub. This will automatically:

  • Archive to Zenodo.
  • Build and publish the package on PyPI (via build-publish.yaml).

If you chose to remove build-publish.yaml, you could upload to PyPI manually as follows… First, remove any existing builds:

rm -rf dist/

Then build the package locally with uv. It will create an isolated build environment, installing flit_core (as specified in pyproject.toml [build-system]).

uv build

Finally, push with twine, entering the API token when prompted:

twine upload --repository pypi dist/*

For test runs, you can use the same method with test PyPI:

twine upload --repository testpypi dist/*
  1. If you haven’t already, fork the lintquarto feedstock (conda-forge/lintquarto-feedstock). This fork must be to your personal GitHub account and not an organisation account. Clone it to your local machine.

If you already have a fork, make sure it is up-to-date:

  • With the conda-forge feedstock - on your forked main branch, click “🔄 Sync fork”.
  • Locally on your main branch (git checkout main), run git pull.
  1. Create and checkout a branch - e.g. update_0_5_0.
git checkout -b update_0_5_0
  1. Use grayskull to update the recipe (recipe/meta.yaml). It will pull the metadata about the package from PyPI, and will not use your local installation of the package.
grayskull pypi lintquarto

It will create lintquarto/meta.yaml. You will need to copy over the contents into recipe/meta.yaml. When you do so, make sure to keep the two fixes made to the meta.yaml file which are…

Fix A: The addition of a home element within about.

home: https://lintquarto.github.io/lintquarto/

Fix B: Correct python version requirements syntax as per the conda-forge documentation, using python_min for host (fixed version), run (minimum version) and requires (fixed version).

As our python_min differs from the conda default (currently 3.7), we change it by adding {% set python_min = "3.10" %} to the start of the script.

{% set python_min = "3.10" %}

...

  host:
    - python {{ python_min }}

...

  run:
    - python >={{ python_min }}

...

  requires:
    - python {{ python_min }}
  1. Create a commit with the updated feedstock - for example:
git add --all
git commit -m "updated feedstock to version 0.5.0"
git push
  1. Use the GitHub website to open a pull request. Completed the provided checklist -
  • Personal account? Yes, if you used your GitHub and not an organisation.
  • Bump? Not relevant as doing a version update, can remove.
  • Reset base? Yes, should show as number: 0 in meta.yaml by default.
  • Re-render? Add the command @conda-forge-admin, please rerender to the end of the pull request.
  1. Wait for the CI actions to run. If all pass, then you can click “Merge pull request”.


Code of conduct

Please be respectful and considerate. See the code of conduct for details.


Contributors

If your name or contributions are missing from the README, or if you contributed in ways not captured by the current role emojis, please create an issue and use:

@all-contributors please add @githubuser for ...

Then list appropriate contribution types from allcontributors.org/docs/en/emoji-key (e.g., code, review, doc, content, bug, ideas, infra).

Alternatively, you can update it from the command line. This may be preferable, as the bot will create GitHub issues that email people when they are added.

You’ll need to install the All-Contributors CLI tool:

npm i -D all-contributors-cli

You can then run the following and select/enter relevant information when prompted:

npx all-contributors

If you want to remove specific contributions or people, edit the .all-contributorsrc file then run the following to regenerate the table in README.md. (Don’t edit README.md, as it is just generated based on .all-contributorsrc).

npx all-contributors generate


Journal of Open Source Software (JOSS)

The inst/ folder contains materials related to the submission to JOSS.

There is also a GitHub action which renders the paper as a PDF.