Skip to content

Commit d2f95c0

Browse files
committed
Add pylint and run it during CI
1 parent 36bcfa9 commit d2f95c0

File tree

3 files changed

+268
-28
lines changed

3 files changed

+268
-28
lines changed

.github/workflows/ci.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,17 @@ jobs:
6565

6666
- name: Lint with Ruff
6767
run: |
68-
poetry run ruff check .
68+
poetry run ruff check . --output-format=github
69+
70+
- name: Lint with pylint
71+
run: |
72+
poetry run pylint src/**/*.py
73+
if: success() || failure()
6974

7075
- name: Run tests with coverage
7176
run: |
7277
poetry run pytest tests --cov --junit-xml=junit/test-results-${{ matrix.python-version }}.xml
78+
if: success() || failure()
7379

7480
- name: Surface failing tests
7581
uses: pmeier/pytest-results-action@main
@@ -85,7 +91,7 @@ jobs:
8591

8692
# (Optional) Fail the workflow if no JUnit XML was found.
8793
fail-on-empty: true
88-
if: ${{ always() }}
94+
if: success() || failure()
8995

9096
release:
9197
name: Release to PyPi

poetry.lock

Lines changed: 136 additions & 23 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 124 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ dacite = "^1.8.1"
3030
pytest = "^8.2.2"
3131
mock = "^5.1.0"
3232
coverage = "^7.5.4"
33-
ruff = "^0.6.0"
33+
ruff = "^0.11.7"
3434
pytest-cov = "^5.0.0"
3535
pytest-asyncio = "^0.24.0"
3636
pytest-mock = "^3.14.0"
3737
mypy = "^1.15.0"
38+
pylint = "^3.3.6"
3839

3940

4041

@@ -78,8 +79,128 @@ exclude_lines = [
7879
]
7980
ignore_errors = true
8081

81-
[tool.ruff]
82-
output-format = "github"
82+
[tool.ruff.lint]
83+
select = ["ALL"]
84+
85+
ignore = [
86+
"ANN401", # Opinioated warning on disallowing dynamically typed expressions
87+
"D203", # Conflicts with other rules
88+
"D213", # Conflicts with other rules
89+
"EM101", # raw-string-in-exception
90+
91+
"D105", # Missing docstring in magic method
92+
"D107", # Missing docstring in `__init__`
93+
"E501", # line too long
94+
95+
"FBT", # flake8-boolean-trap
96+
97+
"PLR2004", # Magic value used in comparison, consider replacing {value} with a constant variable
98+
99+
# Conflicts with the Ruff formatter
100+
"COM812",
101+
102+
# Remove later
103+
"TD", # Todos
104+
"A", # bultins
105+
"DTZ", # use tz need to test it first
106+
"TRY", # tryceratops
107+
"FIX002", # Line contains TODO, consider resolving the issue
108+
"BLE001", # Do not catch blind exception: `Exception`
109+
110+
]
111+
112+
[tool.ruff.lint.flake8-pytest-style]
113+
fixture-parentheses = false
114+
115+
116+
[tool.ruff.lint.isort]
117+
combine-as-imports = true
118+
force-sort-within-sections = true
119+
known-first-party = ["saic_ismart_client_ng"]
120+
required-imports = ["from __future__ import annotations"]
121+
122+
123+
[tool.ruff.lint.per-file-ignores]
124+
"tests/**" = [
125+
"D100", # Missing docstring in public module
126+
"D103", # Missing docstring in public function
127+
"D104", # Missing docstring in public package
128+
"N802", # Function name {name} should be lowercase
129+
"N816", # Variable {name} in global scope should not be mixedCase
130+
"PLR0913", # Too many arguments in function definition
131+
"S101", # Use of assert detected
132+
"SLF001", # Private member accessed: {access}
133+
"T201", # print found
134+
]
135+
136+
[tool.ruff.lint.mccabe]
137+
max-complexity = 13
138+
139+
[tool.ruff.lint.pylint]
140+
max-args = 7
83141

84142
[tool.mypy]
85143
files = ["./src", "./tests"]
144+
python_version = 3.11
145+
show_error_codes = true
146+
strict_equality = true
147+
warn_incomplete_stub = true
148+
warn_redundant_casts = true
149+
warn_unused_configs = true
150+
warn_unused_ignores = true
151+
check_untyped_defs = true
152+
disallow_incomplete_defs = true
153+
disallow_subclassing_any = true
154+
disallow_untyped_calls = true
155+
disallow_untyped_decorators = true
156+
disallow_untyped_defs = true
157+
no_implicit_optional = true
158+
warn_return_any = true
159+
warn_unreachable = true
160+
strict = true
161+
162+
[tool.pylint.MAIN]
163+
py-version = "3.11"
164+
ignore = ["tests"]
165+
fail-on = ["I"]
166+
167+
[tool.pylint.BASIC]
168+
good-names = ["i", "j", "k", "ex", "_", "T", "x", "y", "id", "tg"]
169+
170+
[tool.pylint."MESSAGES CONTROL"]
171+
# Reasons disabled:
172+
# format - handled by black
173+
# duplicate-code - unavoidable
174+
# cyclic-import - doesn't test if both import on load
175+
# abstract-class-little-used - prevents from setting right foundation
176+
# too-many-* - are not enforced for the sake of readability
177+
# too-few-* - same as too-many-*
178+
# abstract-method - with intro of async there are always methods missing
179+
# inconsistent-return-statements - doesn't handle raise
180+
# too-many-ancestors - it's too strict.
181+
# wrong-import-order - isort guards this
182+
# ---
183+
# Pylint CodeStyle plugin
184+
# consider-using-namedtuple-or-dataclass - too opinionated
185+
# consider-using-assignment-expr - decision to use := better left to devs
186+
disable = [
187+
"format",
188+
"cyclic-import",
189+
"duplicate-code",
190+
"too-many-arguments",
191+
"too-many-instance-attributes",
192+
"too-many-locals",
193+
"too-many-ancestors",
194+
"too-few-public-methods",
195+
"invalid-name",
196+
]
197+
enable = ["useless-suppression", "use-symbolic-message-instead"]
198+
199+
[tool.pylint.REPORTS]
200+
score = false
201+
202+
[tool.pylint.FORMAT]
203+
expected-line-ending-format = "LF"
204+
205+
[tool.pylint.EXCEPTIONS]
206+
overgeneral-exceptions = ["builtins.BaseException", "builtins.Exception"]

0 commit comments

Comments
 (0)