|
| 1 | +# Pylint Development Instructions |
| 2 | + |
| 3 | +Always follow these instructions first and fallback to additional search and context |
| 4 | +gathering only if the information in these instructions is incomplete or found to be in |
| 5 | +error. |
| 6 | + |
| 7 | +## Issue Label Guidelines |
| 8 | + |
| 9 | +Before attempting to fix any issue, check the GitHub issue labels using the GitHub API: |
| 10 | + |
| 11 | +- If an issue is labeled with "Astroid", "Needs astroid update", "Needs astroid |
| 12 | + constraint", or "Needs astroid Brain 🧠", **ONLY** create regression tests |
| 13 | +- Do **NOT** attempt to fix astroid-related issues as you cannot modify astroid from |
| 14 | + this repository |
| 15 | +- For astroid-related issues, focus on creating comprehensive regression tests that |
| 16 | + reproduce the problem |
| 17 | +- All other issues can be fixed normally following the standard development workflow |
| 18 | + |
| 19 | +## Development Environment Setup |
| 20 | + |
| 21 | +### Basic Installation |
| 22 | + |
| 23 | +Clone and set up pylint development environment: |
| 24 | + |
| 25 | +- `git clone https://github.com/pylint-dev/pylint` -- clone repository |
| 26 | +- `cd pylint` -- enter directory |
| 27 | +- `python3 -m venv venv` -- create virtual environment |
| 28 | +- `source venv/bin/activate` -- activate virtual environment (Linux/Mac) |
| 29 | +- `pip install -r requirements_test_min.txt` -- install test dependencies (~30 seconds) |
| 30 | +- `pip install -e .` -- install pylint in editable mode (~30-60 seconds) |
| 31 | + |
| 32 | +### Optional Setup Steps |
| 33 | + |
| 34 | +- `pre-commit install` -- enable pre-commit hooks for autoformatting |
| 35 | +- `pip install pre-commit` -- install pre-commit separately if needed |
| 36 | + |
| 37 | +### Astroid Development (if needed) |
| 38 | + |
| 39 | +If working on astroid changes: |
| 40 | + |
| 41 | +- `git clone https://github.com/pylint-dev/astroid.git` -- clone astroid |
| 42 | +- `pip install -e astroid/` -- install astroid in editable mode |
| 43 | +- `cd astroid/ && git switch my-astroid-dev-branch` -- switch to development branch |
| 44 | + |
| 45 | +## Running Tests |
| 46 | + |
| 47 | +### Core Test Commands |
| 48 | + |
| 49 | +- `pytest tests/test_functional.py -k test_functional` -- run functional tests (~60 |
| 50 | + seconds, NEVER CANCEL, set timeout to 120+ seconds) |
| 51 | +- `pytest tests/` -- run all tests (several minutes, NEVER CANCEL, set timeout to 300+ |
| 52 | + seconds) |
| 53 | +- `python3 -m pytest` -- run tests with local python |
| 54 | +- `pytest tests/test_check_parallel.py -v` -- quick test file (~2 seconds) |
| 55 | + |
| 56 | +### Specific Test Types |
| 57 | + |
| 58 | +- **Functional tests:** |
| 59 | + `pytest "tests/test_functional.py::test_functional[missing_kwoa_py3]"` -- single |
| 60 | + functional test (~1 second) |
| 61 | +- **Unit tests:** Located in `/tests/` directory, test specific pylint functionality |
| 62 | +- **Configuration tests:** In `/tests/config/functional/` for testing configuration |
| 63 | + loading |
| 64 | +- **Primer tests:** `pytest -m primer_stdlib --primer-stdlib` -- test on stdlib for |
| 65 | + crashes |
| 66 | + |
| 67 | +### Test with Coverage |
| 68 | + |
| 69 | +- `pytest tests/message/ --cov=pylint.message` -- run with coverage |
| 70 | +- `coverage html` -- generate HTML coverage report |
| 71 | + |
| 72 | +### Tox Usage (Optional) |
| 73 | + |
| 74 | +- `python -m tox` -- run all tox environments |
| 75 | +- `python -m tox -epy313` -- run Python 3.13 suite only |
| 76 | +- `python -m tox -epylint` -- run pylint on pylint's codebase |
| 77 | +- `python -m tox -eformatting` -- run formatting checks |
| 78 | +- `python -m tox --recreate` -- recreate environments (recommended) |
| 79 | +- `python -m tox -e py310 -- -k test_functional` -- run specific tests in tox |
| 80 | + |
| 81 | +## Documentation |
| 82 | + |
| 83 | +### Building Documentation |
| 84 | + |
| 85 | +- `make -C doc/ install-dependencies` -- install doc dependencies (~10 seconds) |
| 86 | +- `make -C doc/ html` -- build documentation (~3 minutes, NEVER CANCEL, set timeout to |
| 87 | + 300+ seconds) |
| 88 | +- `make -C doc/ clean` -- clean build files when starting from scratch |
| 89 | +- `tox -e docs` -- alternative way to build docs |
| 90 | + |
| 91 | +**Network dependency:** Documentation build requires internet access to fetch external |
| 92 | +inventories. |
| 93 | + |
| 94 | +## Validation and Quality Checks |
| 95 | + |
| 96 | +### Running Pylint on Code |
| 97 | + |
| 98 | +- `pylint --help` -- verify pylint installation works |
| 99 | +- `pylint --disable=all --enable=E,F pylint/` -- run pylint on itself for errors only |
| 100 | + (~20 seconds) |
| 101 | +- `pylint --rcfile=pylintrc --fail-on=I path/to/your/changes.py` -- standard pylint run |
| 102 | +- `pylint --disable=all --enable=E,F,W path/to/your/changes.py` -- focus on errors and |
| 103 | + warnings |
| 104 | + |
| 105 | +### Pre-commit and Formatting |
| 106 | + |
| 107 | +- `pre-commit run --all-files` -- run all formatting checks (requires network for |
| 108 | + initial setup) |
| 109 | +- **Network dependency:** pre-commit may fail in isolated environments due to hook |
| 110 | + downloads |
| 111 | + |
| 112 | +### Validation Test Scenarios |
| 113 | + |
| 114 | +Always test your changes with these validation scenarios: |
| 115 | + |
| 116 | +- `echo "def badFunction(): pass" > /tmp/test_sample.py && pylint --enable=C0103 /tmp/test_sample.py` |
| 117 | + -- should find naming issues |
| 118 | +- `pylint --help` and `pylint --list-msgs | head -10` -- verify CLI functionality |
| 119 | +- `pylint --help-msg=C0103` -- should show invalid-name help |
| 120 | +- `pylint --rcfile=pylintrc --fail-on=I pylint/__init__.py` -- should get 10.00/10 |
| 121 | + rating |
| 122 | + |
| 123 | +## Writing Tests |
| 124 | + |
| 125 | +### Functional Tests |
| 126 | + |
| 127 | +Located in `/tests/functional/`, consists of `.py` test files with corresponding `.txt` |
| 128 | +expected output files: |
| 129 | + |
| 130 | +- Annotate lines where messages are expected: |
| 131 | + `a, b, c = 1 # [unbalanced-tuple-unpacking]` |
| 132 | +- Multiple messages on same line: |
| 133 | + `a, b, c = 1.test # [unbalanced-tuple-unpacking, no-member]` |
| 134 | +- Use offset syntax for special cases: `# +1: [singleton-comparison]` |
| 135 | +- **Run and update:** |
| 136 | + `python tests/test_functional.py --update-functional-output -k "test_functional[test_name]"` |
| 137 | + |
| 138 | +### Test File Organization |
| 139 | + |
| 140 | +- **New checkers:** Create `new_checker_message.py` in `/tests/functional/n/` |
| 141 | +- **Extensions:** Place in `/tests/functional/ext/extension_name/` |
| 142 | +- **Regression tests:** Place in `/tests/r/regression/` with `regression_` prefix |
| 143 | +- **Configuration tests:** Place in `/tests/config/functional/` |
| 144 | + |
| 145 | +### Configuration Test Files |
| 146 | + |
| 147 | +Create `.result.json` files with configuration differences from standard config: |
| 148 | + |
| 149 | +```json |
| 150 | +{ |
| 151 | + "functional_append": { |
| 152 | + "disable": [["a-message-to-be-added"]] |
| 153 | + }, |
| 154 | + "jobs": 10 |
| 155 | +} |
| 156 | +``` |
| 157 | + |
| 158 | +## Codebase Structure |
| 159 | + |
| 160 | +``` |
| 161 | +pylint/ # Main package |
| 162 | +├── checkers/ # All pylint checkers (rules implementation) |
| 163 | +├── config/ # Configuration handling and parsing |
| 164 | +├── message/ # Message system and formatting |
| 165 | +├── reporters/ # Output formatters (text, json, etc.) |
| 166 | +├── testutils/ # Testing utilities and helpers |
| 167 | +└── extensions/ # Optional extensions and plugins |
| 168 | +
|
| 169 | +tests/ # Test suite |
| 170 | +├── functional/ # Functional test files (.py + .txt expected output) |
| 171 | +├── config/functional/ # Configuration functional tests |
| 172 | +├── r/regression/ # Regression tests |
| 173 | +├── test_*.py # Unit tests |
| 174 | +└── regrtest_data/ # Test data files |
| 175 | +
|
| 176 | +doc/ # Documentation |
| 177 | +├── user_guide/ # User documentation |
| 178 | +├── development_guide/ # Developer and contributor documentation |
| 179 | +│ ├── contributor_guide/ # Setup, testing, contribution guidelines |
| 180 | +│ ├── technical_reference/ # Technical implementation details |
| 181 | +│ └── how_tos/ # Guides for custom checkers, plugins |
| 182 | +└── additional_tools/ # Tools documentation |
| 183 | +
|
| 184 | +script/ # Development utility scripts |
| 185 | +``` |
| 186 | + |
| 187 | +### Key Files |
| 188 | + |
| 189 | +- `pyproject.toml` -- Main configuration (dependencies, build, tools) |
| 190 | +- `tox.ini` -- Multi-environment testing configuration |
| 191 | +- `.pre-commit-config.yaml` -- Code quality checks configuration |
| 192 | +- `pylintrc` -- Pylint's own configuration |
| 193 | +- `requirements_test_min.txt` -- Minimal test dependencies |
| 194 | + |
| 195 | +## Creating New Checkers |
| 196 | + |
| 197 | +### Getting Started |
| 198 | + |
| 199 | +- `python script/get_unused_message_id_category.py` -- get next available message ID |
| 200 | +- Study existing checkers in `pylint/checkers/` for patterns |
| 201 | +- Read technical reference documentation in `doc/development_guide/technical_reference/` |
| 202 | +- Use `astroid.extract_node` for AST manipulation |
| 203 | + |
| 204 | +### Workflow |
| 205 | + |
| 206 | +1. Create checker class in appropriate `pylint/checkers/` file |
| 207 | +2. Add functional tests in `tests/functional/` |
| 208 | +3. Search existing code for warning message to find where logic exists |
| 209 | +4. Test with sample code to ensure functionality works |
| 210 | + |
| 211 | +## Pull Request Guidelines |
| 212 | + |
| 213 | +### Before Submitting |
| 214 | + |
| 215 | +- Use Python 3.8+ for development (required for latest AST parser and pre-commit hooks) |
| 216 | +- Write comprehensive commit messages relating to tracker issues |
| 217 | +- Keep changes small and separate consensual from opinionated changes |
| 218 | +- Add news fragment: `towncrier create <IssueNumber>.<type>` |
| 219 | +- Always launch `pre-commit run -a` before committing |
| 220 | + |
| 221 | +### Documentation Changes |
| 222 | + |
| 223 | +- Document non-trivial changes |
| 224 | +- Generate docs with `tox -e docs` |
| 225 | +- Maintainers may label issues `skip-news` if no changelog needed |
| 226 | + |
| 227 | +### Contribution Credits |
| 228 | + |
| 229 | +- Add emails/names to `script/.contributors_aliases.json` if using multiple identities |
| 230 | + |
| 231 | +## Critical Timing Information |
| 232 | + |
| 233 | +- **NEVER CANCEL:** All operations that show "NEVER CANCEL" may take significant time |
| 234 | +- **Full test suite:** 60+ seconds (set timeout to 120+ seconds) |
| 235 | +- **Documentation build:** 180 seconds (set timeout to 300+ seconds) |
| 236 | +- **Functional tests:** 60 seconds (set timeout to 120+ seconds) |
| 237 | +- **Pylint self-check:** 20 seconds (set timeout to 60+ seconds) |
| 238 | +- **Individual test files:** 1-15 seconds |
| 239 | +- **Installation steps:** 30-60 seconds each |
| 240 | + |
| 241 | +## Environment Limitations and Workarounds |
| 242 | + |
| 243 | +- **Network connectivity required:** Documentation build and pre-commit setup require |
| 244 | + internet access |
| 245 | +- **Tox failures:** In isolated environments, use direct pytest and pip commands instead |
| 246 | + of tox |
| 247 | +- **Import errors in self-check:** Some import errors when running pylint on itself are |
| 248 | + expected (git dependencies not installed) |
| 249 | +- **Build environments:** Use direct pip/pytest commands when tox environments fail to |
| 250 | + build |
| 251 | + |
| 252 | +Always validate your changes by running pylint on sample code to ensure functionality |
| 253 | +works correctly. |
0 commit comments