Contributing

Code is not the only way to help. We aim to reply to new issues and pull requests within a few days. The project follows the Python Software Foundation Code of Conduct.

Help without code

  • Answer questions in Discussions.

  • Report a bug that you found.

  • Tell us about a part of the documentation that is not clear.

  • Share a project that uses PySAD in Discussions.

Report a bug or ask a question

  • If you found a bug, open a bug report. Include your PySAD version, your Python version and a short script that shows the problem.

  • If you want a new feature or detector, open a feature request. A new detector must meet the Inclusion criteria.

  • If you have a question, start a thread in Discussions.

  • If you found a security problem, do not open a public issue. Follow the security policy.

For a first contribution, choose an issue with the good first issue label.

Open a pull request

PySAD uses trunk-based development: each change goes to the master branch through a short-lived branch and a pull request. Each pull request fixes one issue.

You need git, Python 3.10 or newer, and pip 25.1 or newer.

Set up once

  1. Fork the repository on GitHub.

  2. Clone your fork. Replace <user> with your GitHub user name:

    $ git clone https://github.com/<user>/pysad.git
    
  3. Go into the repository root. Run all the other commands from there:

    $ cd pysad
    
  4. Upgrade pip. The --group option in the next step needs pip 25.1 or newer:

    $ pip install --upgrade pip
    
  5. Install PySAD in editable mode with the dev dependency group. The group pins the runtime dependencies and adds pytest, Sphinx and pre-commit:

    $ pip install -e . --group dev
    

    If you use uv, run uv sync --group dev instead.

  6. Install the git hook of pre-commit. pre-commit is a tool that runs the linters and the formatter on each commit:

    $ pre-commit install
    

Make the change

  1. If no issue describes your change, open one first.

  2. Make a branch named <type>/<issue>-<slug>, for example fix/123-loda-nan-scores:

    $ git switch -c fix/123-loda-nan-scores
    
  3. Change the code. If you add a detector, follow the steps in Write your own detector.

  4. Add tests that check scores, shapes and return types, not private state. If a test uses random numbers, give it a fixed seed.

AGENTS.md in the repository root lists all the rules for code, tests and naming.

Check the change

  1. Run the linters, the formatter, mypy and the file checks:

    $ pre-commit run --all-files
    
  2. Run the unit tests. Add -n auto to run them in parallel:

    $ pytest
    
  3. Run every script in examples/. The plain pytest command skips them:

    $ pytest -m examples
    
  4. If your change affects a detector, explain its effect on the results. This includes a change to shared code that the detector uses, for example BaseModel. CI runs the affected detectors on the first 2,000 points of each dataset, once with the code of master and once with your change. The summary of each CI job lists the results that moved. To see the effect on the full benchmark before you push, commit your change and run:

    $ python benchmarks/benchmark.py --check origin/master
    

    The maintainers update the results in docs/benchmark/. Run the benchmark explains the options of the benchmark.

  5. If you changed a docstring or a file in docs/, build the documentation. CI does not build it for each pull request:

    $ bash build_docs.sh
    

    Open docs/_build/html/index.html to read the result.

Send the change

  1. Push your branch to your fork.

  2. Open a pull request into master. If the change is not ready for review, open it as a draft.

  3. Write the title as a conventional commit: <type>: <summary>, for example fix: return finite LODA scores for constant features.

    Use one of these types: feat, fix, docs, build, ci, refactor, test, style or chore. For a breaking change, put ! before the colon, for example feat!:. A workflow labels the pull request from the type, and the release notes group the pull requests by these labels.

  4. Wait for CI. CI (continuous integration) is the set of checks that GitHub runs on each pull request. pre-commit.ci also pushes a commit with the fixes that it can make. If it does, pull before you push again.

Review checklist

We apply this checklist to each pull request:

  • The change fits the aim of PySAD: anomaly detection on streaming data.

  • The pull request fixes one issue, and no other open pull request covers the same work.

  • All CI checks pass.

  • New behavior has tests. A new feature also has an example or documentation.

  • A new public class is in the __init__.py and __all__ of its subpackage, and in the page of its module in docs/api/.

  • A new detector meets the Inclusion criteria and follows the steps in Write your own detector.

  • If the change moves the results of a detector, the pull request updates docs/benchmark/. The diff of docs/benchmark/results.csv shows AUROC, AUPR and time per point before and after the change.

  • The change does not keep old behavior through deprecation aliases or compatibility code.

AI tools

You can use AI tools to write issues, pull requests, reviews and code. These rules apply:

  • Put the text that an AI tool writes in a quote block or a code block.

  • Add your own comment that tells why the AI text is relevant.

  • Read and understand all the code that you submit.

  • Do not let an AI agent open an issue or a non-draft pull request, or comment, before you approve the exact content.

We close contributions that an AI agent generated with no human review.