Skip to content

fix(typing): preserve decorated function type signatures with ParamSpec#376

Open
gencurrent wants to merge 2 commits intopython-cachier:masterfrom
gencurrent:fix/preserve-decorator-type-signature
Open

fix(typing): preserve decorated function type signatures with ParamSpec#376
gencurrent wants to merge 2 commits intopython-cachier:masterfrom
gencurrent:fix/preserve-decorator-type-signature

Conversation

@gencurrent
Copy link
Copy Markdown
Contributor

I encounter this issue with Pyrefly constantly: the declared return type of the decorated function / method does not match the expected return type, so I have to add # ... ignore ... comments.

The @cachier decorator erases all type information from decorated functions. Because cachier() has no return type annotation and no generic type variables, type checkers see every decorated function -- both its signature and return value -- as Any:

@cachier()
def my_func(x: int) -> str:
    return str(x)

reveal_type(my_func)      # Any
reveal_type(my_func(5))   # Any
This breaks IDE autocomplete, disables type error detection on wrong arguments, and forces downstream typed codebases to use stubs or type: ignore.

Changes
src/cachier/core.py: Add ParamSpec/TypeVar generics to cachier(), _cachier_decorator(), and func_wrapper so the original function signature is preserved through the decorator
tests/test_typing.py: 12 mypy-based tests covering sync, async, complex signatures, wrong-arg rejection, and decorator argument variants
tests/requirements.txt: Add mypy as a test dependency
After:


reveal_type(my_func)      # (x: int) -> str
reveal_type(my_func(5))   # str

@gencurrent gencurrent requested a review from shaypal5 as a code owner April 13, 2026 22:19
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.95%. Comparing base (4602401) to head (e6ff4b1).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##           master     #376   +/-   ##
=======================================
  Coverage   99.95%   99.95%           
=======================================
  Files          16       16           
  Lines        2098     2100    +2     
  Branches      251      251           
=======================================
+ Hits         2097     2099    +2     
  Partials        1        1           
Flag Coverage Δ
local 66.42% <100.00%> (+0.03%) ⬆️
mongodb 39.76% <94.44%> (+0.05%) ⬆️
postgres 41.85% <94.44%> (+0.05%) ⬆️
redis 44.33% <94.44%> (+0.05%) ⬆️
s3 41.04% <94.44%> (+0.05%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/cachier/core.py 100.00% <100.00%> (ø)

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4602401...e6ff4b1. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

1 participant