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