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

feature: API checks: Check for types compatibility #113

Open
pawamoy opened this issue Nov 18, 2022 · 4 comments
Open

feature: API checks: Check for types compatibility #113

pawamoy opened this issue Nov 18, 2022 · 4 comments
Assignees
Labels
feature New feature or request fund Issue priority can be boosted

Comments

@pawamoy
Copy link
Member

pawamoy commented Nov 18, 2022

Following the discussion in #75, we released a first version of the API breakage detection feature, which does not check if types (parameters types, return types) are compatible between the old and new code.
This issue is here to discuss about adding support for checking types compatibility.

It's already possible at runtime with beartype, so maybe we could use in the inspector. But for the visitor we need something static.

Boost priority

  • Boost priority in our backlog through Polar.sh. Higher pledge, higher priority.
  • Minimum pledge by user/organization is $5, minimum amount for boost is $30.
  • View all issues with pledges.
  • We receive the funds once the issue is completed and confirmed by you.
  • Features with the insiders label are released to sponsors first, and tied to a funding goal.
Fund with Polar
@pawamoy pawamoy added the feature New feature or request label Nov 18, 2022
@pawamoy
Copy link
Member Author

pawamoy commented Mar 2, 2024

Moving this here from the README:

  • List of things to consider for breaking changes
    • Changed type of parameter
    • Changed type of public module attribute
    • Changed return type of a public function/method
    • All of the previous even when parent is private (could be publicly imported or assigned somewhere),
      and later be smarter: public assign/import makes private things public!
    • Inheritance: removed, added or changed base that changes MRO

@pawamoy pawamoy changed the title API breakages: Check for types compatibility feature: API checks: Check for types compatibility Mar 2, 2024
@pawamoy
Copy link
Member Author

pawamoy commented Mar 2, 2024

I wonder: could we somehow recurse into objects to check that they implement the same "protocols"? Example:

class Foo:
    def method1(self): ...
    def method2(self, param1: int, param2: int): ...

class Bar:
    def method2(self, param1: int, param2: int): ...

class Baz:
    def method1(self): ...
    def method2(self, param1: int): ...

class Qux:
    def method1(self): ...
    def method2(self, param1: str, param2: int): ...

class Quux:
    def method1(self): ...
    def method2(self, param1: int, param2: int): ...
    def method3(self): ...

def f_old(param: Foo): ...

def f_new(param: Bar): ...  # breaks: removed method1
def f_new(param: Baz): ...  # breaks: removed param2 on method2
def f_new(param: Qux): ...  # breaks: changed type of param1 on method2 (int -> str is a "known" breakage)
def f_new(param: Quux): ...  # doesn't break: added method3

I imagine a type_compatible(self, other) method on objects that uses next(find_breaking_changes(self, other)) and returns False if a breakage is yielded, True if StopIteration is raised.

@pawamoy
Copy link
Member Author

pawamoy commented Mar 2, 2024

Or maybe there's a way to hook into mypy...

@pawamoy pawamoy self-assigned this Jun 8, 2024
@pawamoy
Copy link
Member Author

pawamoy commented Aug 11, 2024

We would need to match protocols in all expression parts.

In dict[MyStr, This] vs. MyDict[str, That]:

  • dict and MyDict must match
  • MyStr and str must match
  • This and That must match

To compare objects, we'd have to dynamically load external objects (but only if they weren't already used). Examples:

  • param: list[otherpkg.Thing] vs. param: Sequence[otherpkg.Thing]: here we see that otherpkg.Thing is the same object (canonical path) before and after, so we don't need to load it
  • param: otherpkg.Thing vs. param: set[str]: here we'd need to load otherpkg.Thing
  • param: set[str] vs. param: otherpkg.Thing: here we'd need to load otherpkg.Thing again

Or we could expect users to pre-load these modules and soft-fail otherwise.

By the way, how to compare set[str] to Thing? Should Thing inherit from a generic with str type? Or should all the equivalent parameters be typed str, and if they're typed T (type alias? how to check that?) then only check generics?

@pawamoy pawamoy added the fund Issue priority can be boosted label Oct 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request fund Issue priority can be boosted
Projects
None yet
Development

No branches or pull requests

1 participant