Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

py.typed and strictly type-checked #3

Merged
merged 2 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Empty file added jaraco/compat/py.typed
Empty file.
30 changes: 20 additions & 10 deletions jaraco/compat/py38.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,43 @@
import functools
import sys
import types
from typing import Protocol, cast


def _fixer(orig: str): # pragma: no cover
class _RFixed(Protocol):
def removesuffix(self, suffix: str) -> str: ...
def removeprefix(self, prefix: str) -> str: ...


def _fixer(orig: str) -> _RFixed: # pragma: no cover
"""
Return an object that implements removesuffix and removeprefix on orig.
"""

def removesuffix(suffix):
def removesuffix(suffix: str) -> str:
# suffix='' should not call orig[:-0].
if suffix and orig.endswith(suffix):
return orig[: -len(suffix)]
else:
return orig[:]

def removeprefix(prefix):
def removeprefix(prefix: str) -> str:
if orig.startswith(prefix):
return orig[len(prefix) :]
else:
return orig[:]

return types.SimpleNamespace(removesuffix=removesuffix, removeprefix=removeprefix)
return cast(
_RFixed,
types.SimpleNamespace(removesuffix=removesuffix, removeprefix=removeprefix),
)


r_fix = _fixer if sys.version_info < (3, 9) else lambda x: x
if sys.version_info < (3, 9): # pragma: no cover
cache = functools.lru_cache(maxsize=None)
r_fix = _fixer
else:
cache = functools.cache

cache = (
functools.cache # type: ignore[attr-defined]
if sys.version_info >= (3, 9)
else functools.lru_cache(maxsize=None)
)
def r_fix(orig: str) -> str:
return orig
Copy link
Owner

Choose a reason for hiding this comment

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

I do prefer to have single assignment rather than conditional assignment. I also like to keep concerns separate. With this change, now r_fix and cache is interleaved.

But I see now why you do it - mypy doesn't honor conditionals that aren't conditional blocks.

The problem with accepting this change is I'm already tempted to refactor it to separate the concerns and consolidate assignments.

I think this is a case where the value of the original logic is greater than the value of the type checking.

Restored in 67d3f31.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's definitely a balance of what you value!
Pyright understands "ternary" (conditional expression), by not mypy https://github.com/python/mypy/issues?q=sort%3Aupdated-desc+is%3Aopen+label%3Atopic-ternary-expression (the most specific issue/request related to this case would be python/mypy#13003 )

Generally as long as the exposed type is correct.

2 changes: 1 addition & 1 deletion mypy.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[mypy]
# Is the project well-typed?
strict = False
strict = True

# Early opt-in even when strict = False
warn_unused_ignores = True
Expand Down
4 changes: 0 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,3 @@ type = [


[tool.setuptools_scm]


[tool.pytest-enabler.mypy]
# Disabled due to jaraco/skeleton#143
Loading