Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 0 additions & 47 deletions .github/CONTRIBUTING.md

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/ci-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
strategy:
matrix:
os: ["ubuntu-latest", "windows-latest", "macos-latest"]
python-version: ["3.10", "3.11", "3.12"]
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Set up Python
Expand Down
40 changes: 40 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-toml
- id: check-added-large-files
- id: check-merge-conflict
- id: debug-statements
- id: mixed-line-ending
files: \.py$

# Black
- repo: https://github.com/psf/black
rev: 25.9.0
hooks:
- id: black
args: ['--line-length=120', '--target-version=py310']
files: ^causal_testing/

# isort
- repo: https://github.com/pycqa/isort
rev: 7.0.0
hooks:
- id: isort
args: ['--profile', 'black', '--line-length', '120']
files: ^causal_testing/

# Pylint
- repo: local
hooks:
- id: pylint
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this block commits that aren't perfectly linted? I'm not sure I want this. Sometimes it takes a while to resolve and I need to commit something I know isn't right. I know you can disable checks, but I prefer not to have commits be blocked. Obviously if it can fix it itself, then that's fine, but if it's everything, then that could get annoying.

Copy link
Collaborator Author

@f-allian f-allian Oct 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jmafoster1 - no, pre-commit doesn't completely block anything from being committed, it fixes it instead. The workflow is like this: 1) your script(s) contain unlinted, unformatted code 2) you commit files naively or run manually run pre-commit before committing 3) pre-commit identifies and initially "blocks" commits due to the rules defined in the pre-commit config 4) pre-commit formats and lints it for you 5) you commit as normal.

To avoid it "blocking" your commit from the get-go, just run pre-commit run --all-files before committing.

name: pylint
entry: pylint
language: system
types: [python]
args: ['--max-line-length=120', '--max-positional-arguments=12']
files: ^causal_testing/
42 changes: 30 additions & 12 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,15 @@ persistent=yes

# Minimum Python version to use for version dependent checks. Will default to
# the version used to run pylint.
py-version=3.9
py-version=3.10

# Discover python modules and packages in the file system subtree.
recursive=no

# When enabled, pylint would attempt to guess common misconfiguration and emit
# user-friendly hints instead of false-positive error messages.
suggestion-mode=yes
# REMOVED: suggestion-mode is deprecated and not recognized in newer versions
# suggestion-mode=yes

# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
Expand Down Expand Up @@ -154,6 +155,9 @@ disable=raw-checker-failed,
use-symbolic-message-instead,
logging-fstring-interpolation,
import-error,
too-many-positional-arguments,
unbalanced-tuple-unpacking,
possibly-used-before-assignment,

# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
Expand Down Expand Up @@ -244,7 +248,14 @@ good-names=i,
df,
Run,
z3,
_
_,
x,
y,
z,
e,
ax,
fig,
id

# Good variable names regexes, separated by a comma. If names match any regex,
# they will always be accepted
Expand Down Expand Up @@ -338,10 +349,10 @@ exclude-too-few-public-methods=
ignored-parents=

# Maximum number of arguments for function / method.
max-args=5
max-args=12

# Maximum number of attributes for a class (see R0902).
max-attributes=7
max-attributes=10

# Maximum number of boolean expressions in an if statement (see R0916).
max-bool-expr=5
Expand All @@ -350,22 +361,22 @@ max-bool-expr=5
max-branches=12

# Maximum number of locals for function / method body.
max-locals=15
max-locals=20

# Maximum number of parents for a class (see R0901).
max-parents=7

# Maximum number of public methods for a class (see R0904).
max-public-methods=20
max-public-methods=25

# Maximum number of return / yield for function / method body.
max-returns=6

# Maximum number of statements in function / method body.
max-statements=50
max-statements=60

# Minimum number of public methods for a class (see R0903).
min-public-methods=2
min-public-methods=1


[EXCEPTIONS]
Expand Down Expand Up @@ -394,7 +405,7 @@ indent-string=' '
max-line-length=120

# Maximum number of lines in a module.
max-module-lines=1000
max-module-lines=1500

# Allow the body of a class to be on the same line as the declaration if body
# contains single statement.
Expand Down Expand Up @@ -538,7 +549,11 @@ contextmanager-decorators=contextlib.contextmanager
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=
generated-members=deap.creator.*,
deap.tools.*,
networkx.graphml,
networkx.*,
deap.base.Toolbox.*,

# Tells whether to warn about missing members when the owner of the attribute
# is inferred to be None.
Expand All @@ -561,7 +576,7 @@ ignored-checks-for-mixins=no-member,
# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace
ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace,deap.creator,deap.base.Toolbox

# Show a hint with possible names when a member name was not found. The aspect
# of finding the hint is based on edit distance.
Expand Down Expand Up @@ -613,3 +628,6 @@ init-import=no
# List of qualified module names which can have objects that can redefine
# builtins.
redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io

[causal_testing.specification.causal_dag]
disable=no-member
2 changes: 1 addition & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ version: 2
build:
os: ubuntu-20.04
tools:
python: "3.9"
python: "3.13"

# Build documentation in the docs/ directory with Sphinx
sphinx:
Expand Down
92 changes: 92 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# How to Contribute

### Questions
Please ask any questions about the Causal Testing Framework or surrounding concepts on the
[discussions board](https://github.com/CITCOM-project/CausalTestingFramework/discussions). Before opening a new
discussion, please see whether a relevant one already exists - someone may have answered your question already.

### Reporting Bugs and Making Suggestions
Upon identifying any bugs or features that could be improved, please open an
[issue](https://github.com/CITCOM-project/CausalTestingFramework/issues) and label with bug or feature suggestion. Every issue
should clearly explain the bug or feature to be improved and, where necessary, instructions to replicate. We also
provide templates for common scenarios when creating an issue.

### Contributing to the Codebase
To contribute to our work, please ensure the following:

1. [Fork the repository](https://help.github.com/articles/fork-a-repo/) into your own GitHub account, and [clone](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) it to your local machine.
2. [Create a new branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-and-deleting-branches-within-your-repository) in your forked repository. Give this branch an appropriate name, and create commits that describe the changes.
3. [Push your changes](https://docs.github.com/en/get-started/using-git/pushing-commits-to-a-remote-repository) to your new branch in your remote fork, compare with `CausalTestingFramework/main`, and ensure any conflicts are resolved.
4. Create a draft [pull request](https://docs.github.com/en/get-started/quickstart/hello-world#opening-a-pull-request) from your branch, and ensure you have [linked](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/autolinked-references-and-urls) it to any relevant issues in your description.

### Continuous Integration (CI) and Code Quality
Our CI/CD tests include:
- Build: Install the necessary Python and runtime dependencies.
- Linting: [pylint](https://pypi.org/project/pylint/) is employed for our code linter and analyser.
- Testing: We use the [unittest]() module to develop our tests and the [pytest](https://pytest.org/en/latest/) framework as our test discovery.
- Formatting: We use [black](https://pypi.org/project/black/) for our code formatting.

To find the other (optional) developer dependencies, please check `pyproject.toml`.

### Pre-commit Hooks
We use [pre-commit](https://pre-commit.com/) to automatically run code quality checks before each commit. This ensures consistent code style and catches issues early.

Automated checks include:

- Trailing whitespace removal.
- End-of-file fixing.
- YAML and TOML validation.
- Black formatting.
- isort import sorting.
- Pylint code analysis.

To use pre-commit:
```bash
# Install pre-commit hooks (one-time setup of .pre-commit-config.yaml)
pre-commit install

# Manually run hooks on all files (optional)
pre-commit run --all-files
```

### Coding Style
In the Causal Testing Framework, we aim to provide highly reusable and easily maintainable packages. To this end,
we ask contributors to stick to the following guidelines:
1. Make small and frequent changes rather than verbose and infrequent changes.
2. Favour readable and informative variable, method, and class names over concise names.
3. Use logging instead of print.
4. For every method and class, include detailed docstrings following the
[reStructuredText/Sphinx](https://sphinx-rtd-tutorial.readthedocs.io/en/latest/docstrings.html) guidelines.
5. Add credit and license information where existing code has been used (in the method or class docstring).
6. If a method implements a specific algorithm/technique from a paper, add a citation to the docstring.
7. Use [variable](https://www.python.org/dev/peps/pep-0008/#variable-annotations) and [function](https://www.python.org/dev/peps/pep-0008/#function-annotations)
annotations.
8. All methods should be thoroughly tested with PyTest (see [Testing]() below).
9. Code formatting and linting is handled automatically by pre-commit hooks (see above).

### Manual Code Quality Checks (Optional)
While pre-commit handles most formatting automatically, you can run these commands manually if needed:

```bash
# Format code
black causal_testing

# Sort imports
isort causal_testing

# Run linter
pylint causal_testing

# Run tests
pytest
```

### Compatibility Testing Across Python Versions with tox

For compatibility testing Python versions, we use [tox](https://pypi.org/project/tox/) to automate
testing across all supported Python versions (3.10, 3.11, 3.12, and 3.13):

- Install tox: `pip install tox`.
- Test all versions: `tox` (runs tests on all Python versions + linting in the root folder).
- Test specific version: `tox -e py313` (or py310, py311, py312).
- Quick iteration: Use `pytest` directly for fast testing during development.
Loading