Skip to content

best-practices: pylint 10.00/10, real docstrings, swap flake8 for pylint in CI#136

Merged
timlnx merged 8 commits intomasterfrom
best-practices
May 5, 2026
Merged

best-practices: pylint 10.00/10, real docstrings, swap flake8 for pylint in CI#136
timlnx merged 8 commits intomasterfrom
best-practices

Conversation

@timlnx
Copy link
Copy Markdown
Owner

@timlnx timlnx commented May 5, 2026

Summary

This branch completes a pylint remediation pass on bitmath/__init__.py, bringing the score from 7.29 to 10.00/10, and updates the CI/toolchain accordingly.

Code changes (bitmath/__init__.py)

  • 17× no-else-return fixed across all comparison operators (__lt__, __le__, __eq__, __ne__, __gt__, __ge__), math operators (__add__, __sub__, __mul__, __truediv__, __floordiv__, __mod__), and several properties/classmethods
  • best_prefix refactored — extracted nested _resolve_prefix_table helper to bring branch count under threshold (was 15/12); simplified index logic; converted %-formatting to f-strings
  • Real docstrings added to all 32 leaf unit subclasses (KiB, MiB, kB, Gib, kb, etc.) and all 34 to_* conversion methods
  • Real docstrings added to DISK_GEOMETRY / DISK_GEOMETRY_EX ctypes structs
  • 2 orphaned bare string statements converted to # comments
  • ordresult rename in __or__ to avoid shadowing the builtin
  • Surgical inline # pylint: disable= for intentional public API names (bytes parameter, sum/format functions) and platform-guarded conditional imports (msvcrt, stat, ctypes)

Toolchain changes

  • requirements.txt: drop flake8, add pylint — pylint at 10.00/10 covers everything pyflakes checked and more
  • Makefile: replace ci-flake8 target with ci-pylint
  • pyproject.toml: add [tool.pylint.basic] with good-names-rgxs for intentional naming conventions (unit class names like kB, kb, conversion methods like to_KiB); raise max-module-lines to 2000
  • .github/workflows/python.yml: drop flake8 step; add pylint step gated to ubuntu-latest / Python 3.12 (linting is not platform-sensitive)
  • docsite/source/contributing.rst: update Code Style, Components, and make ci sections to reflect the toolchain change

Test status

314 passed, 2 skipped — zero regressions.

timlnx added 6 commits May 4, 2026 20:57
Three small things that were overdue:
- Copyright lines now use SPDX-FileCopyrightText: format to match
  the LICENSES/MIT.txt we added
- Two http:// links in the module docstring updated to https://
- Removed a comment explaining # pragma: no cover that had no
  business living in the module header
pylint.toml existed as a 560-line --generate-toml-config dump. Moved
the one non-default setting (py-version = "3.12") into pyproject.toml
where it belongs and deleted the rest.

Running pylint at 6.93/10 then actually fixing things:

parse_string was one 64-statement, 27-branch function handling two
completely different parsing modes. Extracted _parse_string_strict and
_parse_string_unsafe as private helpers; parse_string is now a thin
dispatcher. Should have been that way from the start.

listdir's filter= parameter shadowed the built-in filter. Since we're
in the 2.0 window anyway, renamed it to glob= (which is what it
actually is). filter= still works with a DeprecationWarning pointing
at the caller -- same pattern as parse_string_unsafe.

Smaller fixes:
- struct and warnings moved into unconditional top-level imports
- fcntl: inline pylint disable with a note explaining why the platform
  guards above make it safe at that point
- unit_class = None replaces an UnboundLocalError try/except used as
  flow control (ask me how I know that ends badly)
- raise ... from None on StopIteration re-raises -- the internal
  exception is an implementation detail callers shouldn't see
- dropped a try/except ValueError: raise that did nothing at all
- removed unnecessary else clauses after returns in two places
- cli_script gets a one-line docstring instead of a comment
The parse_string refactor made the split obvious. TestParseStrict
covers the default strict=True path plus public entry-point tests
(including parse_string_unsafe's deprecation shim). TestParseUnsafe
covers strict=False.

314 passing, 2 skipped. Up from 303 before this branch.
- Fix 17x no-else-return across comparison and math operators, system
  property, unit property, from_other, and best_prefix
- Refactor best_prefix: extract nested _resolve_prefix_table helper to
  bring branch count under threshold; simplify index logic; use f-strings
- Add real docstrings to all 32 leaf unit subclasses and 34 to_* methods
- Add real docstrings to DISK_GEOMETRY / DISK_GEOMETRY_EX ctypes structs
- Convert 2 orphaned bare string statements to # comments
- Rename local ord -> result in __or__ to avoid shadowing builtin
- Surgical inline pylint: disable comments for intentional API names
  (bytes parameter, sum/format functions) and platform-guarded imports
- pyproject.toml: good-names-rgxs for unit naming conventions (kB, kb,
  to_KiB, etc.), max-module-lines raised to 2000
pylint at 10.00/10 covers everything pyflakes checked (unused imports,
undefined names) and more. pycodestyle is kept — it owns PEP 8
whitespace/indentation checks that pylint doesn't replicate.

- requirements.txt: drop flake8, add pylint
- Makefile: replace ci-flake8 target with ci-pylint
- python.yml: drop flake8 step; add pylint step gated to ubuntu/3.12
  (linting is not platform-sensitive, no need to run 15x)
- contributing.rst: update Code Style, Components, and make ci sections
grep class matched issubclass() calls too, causing false duplicate
detection when test_parse_strict.py was added alongside test_file_size.py
(both assert issubclass(..., DeprecationWarning)). Changing to grep "^class"
restricts matching to actual class definition lines only.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 5, 2026

Coverage

Test Coverage Report
FileStmtsMissCoverMissing
__init__.py6640100% 
TOTAL6640100% 

timlnx added 2 commits May 4, 2026 22:23
- TestBestPrefixInvalidSystem: cover line 514 (bad system= arg)
- TestSystemPropertyInvalidBase: cover line 317 (invalid _base)
- TestQueryDeviceCapacityWindowsBody: cover lines 1358-1397 via
  mock.patch(create=True) injecting ctypes/msvcrt — runs on all platforms
- TestQueryCapacityWindowsDriveLetterMock: cover lines 1549-1551 via
  mocked os.name='nt' and shutil.disk_usage — runs on all platforms
- Lines 65-68: add # pragma: no cover to elif os.name == 'nt': import
  block (import-time, cannot be covered without module reload)

Local result: 319 passed, 2 skipped, TOTAL 100% coverage, pylint 10.00/10
Replace freeform 'Copyright © YEAR Tim Case <timbielawa@gmail.com>'
with 'SPDX-FileCopyrightText: YEAR[-2026] Tim Case <bitmath@lnx.cx>'
across all 26 test files, matching the format already applied to
bitmath/__init__.py. Year ranges preserved from original headers.
@timlnx timlnx linked an issue May 5, 2026 that may be closed by this pull request
@timlnx timlnx merged commit 49a6bc8 into master May 5, 2026
36 checks passed
@timlnx timlnx deleted the best-practices branch May 5, 2026 13:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix up pylint

1 participant