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
11 changes: 9 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:
- "docs/**"
- ".readthedocs.yaml"
- "pyproject.toml"
- "setup.cfg"
- "mypy.ini"
- "**/*.py"
pull_request:
paths:
Expand All @@ -28,9 +28,16 @@ concurrency:
cancel-in-progress: true

jobs:
ruff:
runs-on: ubuntu-latest
timeout-minutes: &timeout-minutes 5
steps:
- uses: actions/checkout@v6
- uses: astral-sh/ruff-action@v4.0.0

mypy:
runs-on: ${{ matrix.os }}
timeout-minutes: &timeout-minutes 5
timeout-minutes: *timeout-minutes
strategy:
# mypy is os and python-version sensitive. Test on all supported combinations
matrix:
Expand Down
6 changes: 1 addition & 5 deletions mypy.ini
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
[mypy]
mypy_path = src/, typings/
exclude = build
exclude = build/, dist/
strict = True

# Leverage type inference for function return type
disallow_untyped_calls = False
disallow_incomplete_defs = False
disallow_untyped_defs = False

# https://github.com/python/mypy/issues/8234 (post assert "type: ignore")
# https://github.com/python/mypy/issues/8823 (version specific "type: ignore")
warn_unused_ignores = False

disable_error_code =
# https://github.com/python/mypy/issues/6232 (redefinition with correct type)
attr-defined, assignment,
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ dev = [
{ include-group = "docs" },
"ewmhlib",
"mypy>=0.990,<2",
"ruff>=0.15.16",
"types-python-xlib>=0.32",
"types-pywin32>=305.0.0.3",
]
Expand Down
75 changes: 75 additions & 0 deletions ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
[lint]
future-annotations = true
# https://docs.astral.sh/ruff/rules/
extend-select = [
"ANN2", # flake8-annotations: missing-return-type
"PYI", # flake8-pyi
"FA", # flake8-future-annotations
"ICN", # flake8-import-conventions
"F401", # unused-import
"YTT", # flake8-2020
"TC", # flake8-type-checking
"TID", # flake8-tidy-imports
"UP", # pyupgrade
"RUF", # Ruff-specific rules
"F404", # late-future-import
"PGH", # pygrep-hooks (blanket-* rules)
]
ignore = [
# Only enforce return types on public functions. Where otherwise mypy infers as Any
# Still worth running `ruff check --fix --select=202` once in a while for autofixes
"ANN202", # missing-return-type-private-function
# Explicit is preferred
"UP015", # redundant-open-modes,
# Autofixes print-f style formatting to f-strings,
# which is sometimes simpler, but looses template code reading semantics
"UP032", # f-string
# TC helps prevent circular imports, reduce runtime cost of typing symbols,
# and prevent leaking implementations details into modules
# However stdlib is not at risk of circular import, is clearly not public API,
# and assume it's gonna be included in the import chain at some point anyway
"TC003", # typing-only-standard-library-import
# Typeshed doesn't want complex or non-literal defaults for maintenance and testing reasons.
# This doesn't affect us, let's have more complete stubs.
"PYI011", # typed-argument-default-in-stub
"PYI014", # argument-default-in-stub
"PYI053", # string-or-bytes-too-long

# TODO: Consider later
"UP031", # printf-string-formatting
"RUF059", # unused-unpacked-variable
"E722", # bare-except

@Avasam Avasam Jun 16, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

E722 done in #103
It's a base Ruff rule, so felt out of scope for this PR.

]
# F401 would remove imports not marked as explicit re-exports, which may break API boundaries
extend-unsafe-fixes = ["F401"]

[lint.per-file-ignores]
"**/typings/**/*.pyi" = [
"PGH003", # TODO: Blanket ignores until using pyobj type stubs
"F811", # Re-exports false positives
# The following can't be controlled for external libraries:
"A", # Shadowing builtin names
"E741", # ambiguous variable name
"F403", # `from . import *` used; unable to detect undefined names
"FBT", # flake8-boolean-trap
"ICN001", # unconventional-import-alias
"N8", # Naming conventions
"PLC2701", # Private name import
"PLE0302", # The special method expects a given signature
"PLR0904", # Too many public methods
"PLR0913", # Argument count
"PLR0917", # Too many positional arguments
"PLW3201", # misspelled dunder method name
"SLOT", # flake8-slots
# Stubs can sometimes re-export entire modules.
# Issues with using a star-imported name will be caught by type-checkers.
"F405", # may be undefined, or defined from star imports
# It's normal to be missing annotations for local stubs.
# If they were complete, we'd upload them to typeshed!
"ANN0",
"ANN2",
]

# https://docs.astral.sh/ruff/settings/#lintflake8-type-checking
[lint.flake8-type-checking]
quote-annotations = true
15 changes: 7 additions & 8 deletions src/pywinctl/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
from ._main import (Re, Window, checkPermissions, getActiveWindow,
getActiveWindowTitle, getAllAppsNames, getAllAppsWindowsTitles,
getAllTitles, getAllWindows, getAppsWithName, getWindowsWithTitle,
getAllWindowsDict, getTopWindowAt, getWindowsAt, displayWindowsUnderMouse,
getAllScreens, getScreenSize, getWorkArea, getMousePos
)

__all__ = [
__all__ = [ # noqa: RUF022
"version", "Re",
# OS Specifics
"Window", "checkPermissions", "getActiveWindow", "getActiveWindowTitle", "getWindowsWithTitle",
Expand All @@ -18,9 +23,3 @@ def version(numberOnly: bool = True) -> str:
return ("" if numberOnly else "PyWinCtl-")+__version__


from ._main import (Re, Window, checkPermissions, getActiveWindow,
getActiveWindowTitle, getAllAppsNames, getAllAppsWindowsTitles,
getAllTitles, getAllWindows, getAppsWithName, getWindowsWithTitle,
getAllWindowsDict, getTopWindowAt, getWindowsAt, displayWindowsUnderMouse,
getAllScreens, getScreenSize, getWorkArea, getMousePos
)
Loading