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

Improve Type Safety and fix mypy errors #137

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

qnbhd
Copy link

@qnbhd qnbhd commented Jan 14, 2025

Description

Type System Improvements

  1. Added TypeGuard for safer runtime type narrowing:
  • New has_wrapped function to safely check for - __wrapped__ attribute
    New has_location function to verify AST node attributes
  1. Introduced Protocol classes for better interface definitions:
  • WithWrappedSpecial for wrapped function handling
  • LocationProvider for AST node location information
  1. Implemented proper return type casting for decorators using typing.cast

  2. Removed redundant ctx=ast.Load() parameters from AST node construction

  3. Added missing level=0 parameter to ImportFrom nodes

  4. Simplified AST node creation where context was unnecessary

Dependencies

Added typing_extensions>=4.12.2 as a required dependency to support new typing features

Testing

  • Existing tests should cover the refactored code as this is primarily a type system improvement
  • No new runtime behavior has been introduced
  • Static type checking (mypy/pyright) should show improved type safety

* Replace TYPE_CHECKING conditions with direct type variable declarations (zero overhead in runtime)
* Add TypeGuard for wrapped function checks
* Add Protocol for location providers
* Implement proper type casting for decorator return types
* Add typing_extensions as a project dependency
* Remove redundant ctx parameters from AST nodes

Signed-off-by: Templin Konstantin <[email protected]>
@qnbhd
Copy link
Author

qnbhd commented Jan 14, 2025

@orsinium, hello! Please check changes

@@ -61,7 +60,7 @@ def pre(
message=message,
exception=exception or _exceptions.PreContractError,
)
func = partial(Contracts.attach, 'pres', contract)
func = cast(Callable[[C], C], partial(Contracts.attach, 'pres', contract))
Copy link
Member

Choose a reason for hiding this comment

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

This type casting serves no purpose. cast doesn't check the validity of the cast. Also, mypy now can correctly type check partial calls, so cast even reduces the type safety.

Copy link
Author

Choose a reason for hiding this comment

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

The reason for creating these changes is mypy errors, including CI (job example: https://github.com/life4/deal/actions/runs/11742383633/job/32712993184).

You say that mypy already knows how to handle partial correctly? Then to resolve these errors, we can make a bump version of mypy?

from typing import Callable, Iterator, TypeVar
from typing import Callable, Iterator, Protocol, TypeVar

from typing_extensions import TypeGuard
Copy link
Member

Choose a reason for hiding this comment

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

with __future__ import, typing_extensions imports can be placed behind if TYPE_CHECKING, making the dependency optional.

@@ -52,6 +62,6 @@ def get_contracts(func: Callable) -> Iterator[Contract]:
if contracts.patcher:
yield _wrappers.Has(contracts.patcher)

if not hasattr(func, '__wrapped__'):
if not has_wrapped(func):
Copy link
Member

Choose a reason for hiding this comment

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

Not much value in this, tbh: the __wrapped__ is used the very next line. While I like mypy with all my heart, type safety makes more sense when it brings checks not only to the very next line.

Copy link
Author

Choose a reason for hiding this comment

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

Okay, got it! Maybe then add # type: ignore on this line?

@orsinium
Copy link
Member

Thank you for your contribution. While I appreciate the effort you've put into it, I'm not concerned too much about internal type safety: deal is very stable and extensively tested, including mutational testing and dog-fooding. However, I'm always open to improvements, including type safety, to the API consumed by the library users. So, don't hesitate if you ever have any of those.

@qnbhd
Copy link
Author

qnbhd commented Jan 14, 2025

Thank you for your contribution. While I appreciate the effort you've put into it, I'm not concerned too much about internal type safety: deal is very stable and extensively tested, including mutational testing and dog-fooding. However, I'm always open to improvements, including type safety, to the API consumed by the library users. So, don't hesitate if you ever have any of those.

Thanks for your feedback. Initially, I wanted to contribute to improving contracts (I have a couple of ideas). But when running tests locally, I got a lot of errors on mypy check, so I decided to fix them. So the main goal of the current Pull Request is to fix mypy errors.

@qnbhd
Copy link
Author

qnbhd commented Jan 14, 2025

Thank you for your contribution. While I appreciate the effort you've put into it, I'm not concerned too much about internal type safety: deal is very stable and extensively tested, including mutational testing and dog-fooding. However, I'm always open to improvements, including type safety, to the API consumed by the library users. So, don't hesitate if you ever have any of those.

However, I would like to discuss some of my ideas, so creating a pull request right away is not the best idea, because maintainers might reject this request. I don't see an issues section in the repository. How can we discuss the changes?

@orsinium
Copy link
Member

Thank you, that's good to know. I think the problem is that this PR does too many things at once. Let's split the effort. Please, bring a PR with your ast improvements, I'd be happy to merge it. And I'll have a closer look how to make mypy happy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants