Skip to content

Commit 4497164

Browse files
authored
Merge branch 'main' into hoel/add_functions
2 parents 5521e43 + 9f28171 commit 4497164

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+1058
-187
lines changed

.github/workflows/mypy_primer.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
fetch-depth: 0
3232
- uses: actions/setup-python@v5
3333
with:
34-
python-version: "3.12"
34+
python-version: "3.13"
3535
- name: Install dependencies
3636
run: pip install git+https://github.com/hauntsaninja/mypy_primer.git
3737
- name: Run mypy_primer

.pre-commit-config.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ repos:
1111
args: [--fix=lf]
1212
- id: check-case-conflict
1313
- repo: https://github.com/astral-sh/ruff-pre-commit
14-
rev: v0.8.0 # must match requirements-tests.txt
14+
rev: v0.8.5 # must match requirements-tests.txt
1515
hooks:
1616
- id: ruff
1717
name: Run ruff on stubs, tests and scripts

.vscode/settings.default.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,14 @@
7070
"editor.defaultFormatter": "ms-python.black-formatter",
7171
"editor.codeActionsOnSave": {
7272
// Let Ruff lint fixes handle imports
73-
"source.organizeImports": "never"
73+
"source.organizeImports": "never",
74+
"source.unusedImports": "never"
7475
}
7576
},
7677
// python.analysis is Pylance (pyright) configurations
7778
"python.analysis.fixAll": [
78-
"source.unusedImports"
7979
// Explicitly omiting "source.convertImportFormat", some stubs use relative imports
80+
// Explicitly omiting "source.unusedImports", Let Ruff lint fixes handle imports
8081
],
8182
"python.analysis.typeshedPaths": [
8283
"${workspaceFolder}"

lib/ts_utils/metadata.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323

2424
__all__ = [
2525
"NoSuchStubError",
26-
"StubMetadata",
2726
"PackageDependencies",
27+
"StubMetadata",
2828
"StubtestSettings",
2929
"get_recursive_requirements",
3030
"read_dependencies",
@@ -184,7 +184,7 @@ def is_obsolete(self) -> bool:
184184

185185

186186
class NoSuchStubError(ValueError):
187-
"""Raise NoSuchStubError to indicate that a stubs/{distribution} directory doesn't exist"""
187+
"""Raise NoSuchStubError to indicate that a stubs/{distribution} directory doesn't exist."""
188188

189189

190190
@cache
@@ -302,9 +302,10 @@ def read_metadata(distribution: str) -> StubMetadata:
302302

303303

304304
def update_metadata(distribution: str, **new_values: object) -> tomlkit.TOMLDocument:
305-
"""Updates a distribution's METADATA.toml.
305+
"""Update a distribution's METADATA.toml.
306306
307-
Return the updated TOML dictionary for use without having to open the file separately."""
307+
Return the updated TOML dictionary for use without having to open the file separately.
308+
"""
308309
path = metadata_path(distribution)
309310
try:
310311
with path.open("rb") as file:

lib/ts_utils/utils.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from termcolor import colored as colored # pyright: ignore[reportAssignmentType]
1818
except ImportError:
1919

20-
def colored(text: str, color: str | None = None, **kwargs: Any) -> str: # type: ignore[misc]
20+
def colored(text: str, color: str | None = None, **kwargs: Any) -> str: # type: ignore[misc] # noqa: ARG001
2121
return text
2222

2323

@@ -92,7 +92,6 @@ def venv_python(venv_dir: Path) -> Path:
9292
@cache
9393
def parse_requirements() -> Mapping[str, Requirement]:
9494
"""Return a dictionary of requirements from the requirements file."""
95-
9695
with REQUIREMENTS_PATH.open(encoding="UTF-8") as requirements_file:
9796
stripped_lines = map(strip_comments, requirements_file)
9897
stripped_more = [li for li in stripped_lines if not li.startswith("-")]

pyproject.toml

+47-10
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,39 @@ exclude = ["**/test_cases/**/*.py"]
3737
# tell ruff not to flag these as e.g. "unused noqa comments"
3838
external = ["F821", "NQA", "Y"]
3939
select = [
40+
"ARG", # flake8-unused-arguments
4041
"B", # flake8-bugbear
42+
"D", # pydocstyle
43+
"EXE", # flake8-executable
4144
"FA", # flake8-future-annotations
4245
"I", # isort
46+
"N", # pep8-naming
4347
"PGH", # pygrep-hooks
4448
"RUF", # Ruff-specific and unused-noqa
49+
"TRY", # tryceratops
4550
"UP", # pyupgrade
4651
"YTT", # flake8-2020
4752
# Flake8 base rules
4853
"E", # pycodestyle Error
4954
"F", # Pyflakes
5055
"W", # pycodestyle Warning
56+
# Only include flake8-annotations rules that are autofixable. Otherwise leave this to mypy+pyright
57+
"ANN2",
58+
# Don't include TC rules that create a TYPE_CHECKING block or stringifies annotations
59+
"TC004", # Move import `{qualified_name}` out of type-checking block. Import is used for more than type hinting.
60+
"TC005", # Found empty type-checking block
61+
# "TC008", # TODO: Enable when out of preview
62+
"TC010", # Invalid string member in `X | Y`-style union type
63+
# Most refurb rules are in preview and can be opinionated,
64+
# consider them individually as they come out of preview (last check: 0.8.4)
65+
"FURB105", # Unnecessary empty string passed to `print`
66+
"FURB129", # Instead of calling `readlines()`, iterate over file object directly
67+
"FURB136", # Replace `if` expression with `{min_max}` call
68+
"FURB167", # Use of regular expression alias `re.{}`
69+
"FURB168", # Prefer `is` operator over `isinstance` to check if an object is `None`
70+
"FURB169", # Compare the identities of `{object}` and None instead of their respective types
71+
"FURB177", # Prefer `Path.cwd()` over `Path().resolve()` for current-directory lookups
72+
"FURB187", # Use of assignment of `reversed` on list `{name}`
5173
# PYI: only enable rules that have autofixes and that we always want to fix (even manually),
5274
# avoids duplicate # noqa with flake8-pyi and flake8-noqa flagging `PYI` codes
5375
# See https://github.com/plinss/flake8-noqa/issues/22
@@ -77,10 +99,6 @@ extend-safe-fixes = [
7799
"UP036", # Remove unnecessary `sys.version_info` blocks
78100
]
79101
ignore = [
80-
# TODO: Ruff 0.8.0 added sorting of __all__ and __slots_. Validate whether we want this in stubs
81-
"RUF022",
82-
"RUF023",
83-
84102
###
85103
# Rules that can conflict with the formatter (Black)
86104
# https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
@@ -92,11 +110,17 @@ ignore = [
92110
###
93111
# Rules we don't want or don't agree with
94112
###
95-
# Slower and more verbose https://github.com/astral-sh/ruff/issues/7871
96-
"UP038", # Use `X | Y` in `isinstance` call instead of `(X, Y)`
113+
# We're not a library, no need to document everything
114+
"D1", # Missing docstring in ...
115+
# Doesn't support split "summary line"
116+
"D205", # 1 blank line required between summary line and description
97117
# Used for direct, non-subclass type comparison, for example: `type(val) is str`
98118
# see https://github.com/astral-sh/ruff/issues/6465
99119
"E721", # Do not compare types, use `isinstance()`
120+
# Mostly from scripts and tests, it's ok to have messages passed directly to exceptions
121+
"TRY003", # Avoid specifying long messages outside the exception class
122+
# Slower and more verbose https://github.com/astral-sh/ruff/issues/7871
123+
"UP038", # Use `X | Y` in `isinstance` call instead of `(X, Y)`
100124
###
101125
# False-positives, but already checked by type-checkers
102126
###
@@ -106,20 +130,33 @@ ignore = [
106130

107131
[tool.ruff.lint.per-file-ignores]
108132
"*.pyi" = [
109-
# Most flake8-bugbear rules don't apply for third-party stubs like typeshed.
110-
# B033 could be slightly useful but Ruff doesn't have per-file select
111-
"B", # flake8-bugbear
133+
# A lot of stubs are incomplete on purpose, and that's configured through pyright
134+
# Some ANN204 (special method) are autofixable in stubs, but not all.
135+
"ANN2", # Missing return type annotation for ...
136+
# Most pep8-naming rules don't apply for third-party stubs like typeshed.
137+
# N811 to N814 could apply, but we often use them to disambiguate a name whilst making it look like a more common one
138+
"N8",
112139
# Rules that are out of the control of stub authors:
113140
"F403", # `from . import *` used; unable to detect undefined names
114141
# Stubs can sometimes re-export entire modules.
115142
# Issues with using a star-imported name will be caught by type-checkers.
116143
"F405", # may be undefined, or defined from star imports
144+
# Ruff 0.8.0 added sorting of __all__ and __slots_.
145+
# There is no consensus on whether we want to apply this to stubs, so keeping the status quo.
146+
# See https://github.com/python/typeshed/pull/13108
147+
"RUF022",
148+
"RUF023",
117149
]
118-
# See comment on black's force-exclude config above
119150
"*_pb2.pyi" = [
151+
# Leave the docstrings as-is, matching source
152+
"D", # pydocstyle
153+
# See comment on black's force-exclude config above
120154
"E501", # Line too long
121155
]
122156

157+
[tool.ruff.lint.pydocstyle]
158+
convention = "pep257" # https://docs.astral.sh/ruff/settings/#lint_pydocstyle_convention
159+
123160
[tool.ruff.lint.isort]
124161
split-on-trailing-comma = false
125162
combine-as-imports = true

pyrightconfig.stricter.json

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"stubs/corus",
4545
"stubs/dateparser",
4646
"stubs/defusedxml",
47+
"stubs/django-import-export",
4748
"stubs/docker",
4849
"stubs/docutils",
4950
"stubs/Flask-SocketIO",

requirements-tests.txt

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Type checkers that we test our stubs against. These should always
22
# be pinned to a specific version to make failure reproducible.
3-
mypy==1.14.0
3+
mypy==1.14.1
44
pyright==1.1.389
55
# pytype can be installed on Windows, but requires building wheels, let's not do that on the CI
66
pytype==2024.10.11; platform_system != "Windows" and python_version >= "3.10" and python_version < "3.13"
@@ -9,17 +9,17 @@ pytype==2024.10.11; platform_system != "Windows" and python_version >= "3.10" an
99
aiohttp==3.10.11
1010
grpcio-tools>=1.66.2 # For grpc_tools.protoc
1111
mypy-protobuf==3.6.0
12-
packaging==24.1
12+
packaging==24.2
1313
pathspec>=0.11.1
1414
pre-commit
1515
# Required by create_baseline_stubs.py. Must match .pre-commit-config.yaml.
16-
ruff==0.8.0
16+
ruff==0.8.5
1717
stubdefaulter==0.1.0
1818
termcolor>=2.3
19-
tomli==2.0.2
19+
tomli==2.2.1
2020
tomlkit==0.13.2
2121
typing_extensions>=4.12.0rc1
22-
uv==0.4.26
22+
uv==0.5.14
2323

2424
# Utilities for typeshed infrastructure scripts.
2525
ts_utils @ file:lib

scripts/create_baseline_stubs.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ def main() -> None:
218218
info = get_installed_package_info(project)
219219
if info is None:
220220
print(f'Error: "{project}" is not installed', file=sys.stderr)
221-
print("", file=sys.stderr)
221+
print(file=sys.stderr)
222222
print(f'Suggestion: Run "python3 -m pip install {project}" and try again', file=sys.stderr)
223223
sys.exit(1)
224224
project, version = info

scripts/stubsabot.py

100644100755
+3-3
Original file line numberDiff line numberDiff line change
@@ -632,13 +632,13 @@ def latest_commit_is_different_to_last_commit_on_origin(branch: str) -> bool:
632632
return True
633633

634634

635-
class RemoteConflict(Exception):
635+
class RemoteConflictError(Exception):
636636
pass
637637

638638

639639
def somewhat_safe_force_push(branch: str) -> None:
640640
if has_non_stubsabot_commits(branch):
641-
raise RemoteConflict(f"origin/{branch} has non-stubsabot changes that are not on {branch}!")
641+
raise RemoteConflictError(f"origin/{branch} has non-stubsabot changes that are not on {branch}!")
642642
subprocess.check_call(["git", "push", "origin", branch, "--force"])
643643

644644

@@ -808,7 +808,7 @@ async def main() -> None:
808808
if isinstance(update, Obsolete): # pyright: ignore[reportUnnecessaryIsInstance]
809809
await suggest_typeshed_obsolete(update, session, action_level=args.action_level)
810810
continue
811-
except RemoteConflict as e:
811+
except RemoteConflictError as e:
812812
print(colored(f"... but ran into {type(e).__qualname__}: {e}", "red"))
813813
continue
814814
raise AssertionError

scripts/sync_protobuf/_utils.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def extract_archive(archive_path: StrPath, destination: StrPath) -> None:
3333
def run_protoc(
3434
proto_paths: Iterable[StrPath], mypy_out: StrPath, proto_globs: Iterable[str], cwd: StrOrBytesPath | None = None
3535
) -> str:
36-
"""TODO: Describe parameters and return"""
36+
"""TODO: Describe parameters and return."""
3737
protoc_version = (
3838
subprocess.run([sys.executable, "-m", "grpc_tools.protoc", "--version"], capture_output=True).stdout.decode().strip()
3939
)

scripts/sync_protobuf/google_protobuf.py

100644100755
+7-6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#!/usr/bin/env python3
12
"""
23
Generates the protobuf stubs for the given protobuf version using mypy-protobuf.
34
Generally, new minor versions are a good time to update the stubs.
@@ -31,7 +32,7 @@
3132

3233

3334
def extract_python_version(file_path: Path) -> str:
34-
"""Extract the Python version from https://github.com/protocolbuffers/protobuf/blob/main/version.json"""
35+
"""Extract the Python version from https://github.com/protocolbuffers/protobuf/blob/main/version.json ."""
3536
with open(file_path) as file:
3637
data: dict[str, Any] = json.load(file)
3738
# The root key will be the protobuf source code version
@@ -44,7 +45,7 @@ def extract_proto_file_paths(temp_dir: Path) -> list[str]:
4445
"""
4546
Roughly reproduce the subset of .proto files on the public interface
4647
as described in py_proto_library calls in
47-
https://github.com/protocolbuffers/protobuf/blob/main/python/dist/BUILD.bazel
48+
https://github.com/protocolbuffers/protobuf/blob/main/python/dist/BUILD.bazel .
4849
"""
4950
with open(temp_dir / EXTRACTED_PACKAGE_DIR / "python" / "dist" / "BUILD.bazel") as file:
5051
matched_lines = filter(None, (re.search(PROTO_FILE_PATTERN, line) for line in file))
@@ -66,14 +67,14 @@ def main() -> None:
6667
for old_stub in STUBS_FOLDER.rglob("*_pb2.pyi"):
6768
old_stub.unlink()
6869

69-
PROTOC_VERSION = run_protoc(
70+
protoc_version = run_protoc(
7071
proto_paths=(f"{EXTRACTED_PACKAGE_DIR}/src",),
7172
mypy_out=STUBS_FOLDER,
7273
proto_globs=extract_proto_file_paths(temp_dir),
7374
cwd=temp_dir,
7475
)
7576

76-
PYTHON_PROTOBUF_VERSION = extract_python_version(temp_dir / EXTRACTED_PACKAGE_DIR / "version.json")
77+
python_protobuf_version = extract_python_version(temp_dir / EXTRACTED_PACKAGE_DIR / "version.json")
7778

7879
# Cleanup after ourselves, this is a temp dir, but it can still grow fast if run multiple times
7980
shutil.rmtree(temp_dir)
@@ -82,9 +83,9 @@ def main() -> None:
8283
"protobuf",
8384
extra_description=f"""Partially generated using \
8485
[mypy-protobuf=={MYPY_PROTOBUF_VERSION}](https://github.com/nipunn1313/mypy-protobuf/tree/v{MYPY_PROTOBUF_VERSION}) \
85-
and {PROTOC_VERSION} on \
86+
and {protoc_version} on \
8687
[protobuf v{PACKAGE_VERSION}](https://github.com/protocolbuffers/protobuf/releases/tag/v{PACKAGE_VERSION}) \
87-
(python `protobuf=={PYTHON_PROTOBUF_VERSION}`).""",
88+
(python `protobuf=={python_protobuf_version}`).""",
8889
)
8990
print("Updated protobuf/METADATA.toml")
9091

scripts/sync_protobuf/s2clientprotocol.py

100644100755
+6-5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#!/usr/bin/env python3
12
"""
23
Generates the protobuf stubs for the given s2clientprotocol version using mypy-protobuf.
34
Generally, new minor versions are a good time to update the stubs.
@@ -29,7 +30,7 @@
2930

3031

3132
def extract_python_version(file_path: Path) -> str:
32-
"""Extract Python version from s2clientprotocol's build file"""
33+
"""Extract Python version from s2clientprotocol's build file."""
3334
match = re.search(VERSION_PATTERN, file_path.read_text())
3435
assert match
3536
return match.group(1)
@@ -46,14 +47,14 @@ def main() -> None:
4647
for old_stub in STUBS_FOLDER.rglob("*_pb2.pyi"):
4748
old_stub.unlink()
4849

49-
PROTOC_VERSION = run_protoc(
50+
protoc_version = run_protoc(
5051
proto_paths=(EXTRACTED_PACKAGE_DIR,),
5152
mypy_out=STUBS_FOLDER,
5253
proto_globs=(f"{EXTRACTED_PACKAGE_DIR}/s2clientprotocol/*.proto",),
5354
cwd=temp_dir,
5455
)
5556

56-
PYTHON_S2_CLIENT_PROTO_VERSION = extract_python_version(temp_dir / EXTRACTED_PACKAGE_DIR / "s2clientprotocol" / "build.py")
57+
python_s2_client_proto_version = extract_python_version(temp_dir / EXTRACTED_PACKAGE_DIR / "s2clientprotocol" / "build.py")
5758

5859
# Cleanup after ourselves, this is a temp dir, but it can still grow fast if run multiple times
5960
shutil.rmtree(temp_dir)
@@ -62,8 +63,8 @@ def main() -> None:
6263
"s2clientprotocol",
6364
extra_description=f"""Partially generated using \
6465
[mypy-protobuf=={MYPY_PROTOBUF_VERSION}](https://github.com/nipunn1313/mypy-protobuf/tree/v{MYPY_PROTOBUF_VERSION}) \
65-
and {PROTOC_VERSION} on \
66-
[s2client-proto {PYTHON_S2_CLIENT_PROTO_VERSION}](https://github.com/Blizzard/s2client-proto/tree/{PACKAGE_VERSION}).""",
66+
and {protoc_version} on \
67+
[s2client-proto {python_s2_client_proto_version}](https://github.com/Blizzard/s2client-proto/tree/{PACKAGE_VERSION}).""",
6768
)
6869
print("Updated s2clientprotocol/METADATA.toml")
6970

0 commit comments

Comments
 (0)