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

Fix implementation checks on generic interfaces #109

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

Conversation

ro-oliveira95
Copy link

@ro-oliveira95 ro-oliveira95 commented Nov 21, 2023

Previously checking if a non-generic class implements a generic interface always used to fail, as the latter has a special method (__class_getitem__) that the former does't have, which led to false negatives.

@ro-oliveira95 ro-oliveira95 marked this pull request as draft November 21, 2023 13:56
Previously checking if a non-generic class implements a generic interface
always used to fail, as the latter has a special method (`__class_getitem__`)
that the former does't have, which led to false negatives.
@ro-oliveira95 ro-oliveira95 force-pushed the fix-check-on-generic-interfaces branch from 32edb03 to 9ee227d Compare November 21, 2023 17:33
@ro-oliveira95 ro-oliveira95 changed the title Fix lack of support on checking generic interfaces Fix implementation checks on generic interfaces Nov 21, 2023
@ro-oliveira95 ro-oliveira95 marked this pull request as ready for review November 21, 2023 17:39
Comment on lines +1088 to +1090
class IFoo(Interface, Generic[T], TypeCheckingSupport):
# Class instance defined here as a workaround for this class to work in Python 3.6.
__abstractmethods__: FrozenSet = frozenset()
Copy link
Member

Choose a reason for hiding this comment

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

@nicoddemus
Do you think we could drop python 3.6 support in oop-ext?

Copy link
Member

@nicoddemus nicoddemus Dec 5, 2023

Choose a reason for hiding this comment

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

Definitely, IMO we can do this for all of our OS projects, supporting >=3.7 or even >=3.10 only, if the former is too much work.

@prusse-martin
Copy link
Member

@nicoddemus

The sonar cloud token is a organization wide configuration?
Here it is failing to access the token. Any ideas?

@prusse-martin
Copy link
Member

There was an early attempt at this in the past:
#97

@@ -2,6 +2,28 @@
------------------

* Added support for Python 3.10.
* #109: Non-generic implementers of generic interfaces are now correctly checked.
Copy link
Member

Choose a reason for hiding this comment

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

Great changelog entry. 👍

Comment on lines +1088 to +1090
class IFoo(Interface, Generic[T], TypeCheckingSupport):
# Class instance defined here as a workaround for this class to work in Python 3.6.
__abstractmethods__: FrozenSet = frozenset()
Copy link
Member

@nicoddemus nicoddemus Dec 5, 2023

Choose a reason for hiding this comment

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

Definitely, IMO we can do this for all of our OS projects, supporting >=3.7 or even >=3.10 only, if the former is too much work.

@@ -2,6 +2,28 @@
------------------

* Added support for Python 3.10.
* #109: Non-generic implementers of generic interfaces are now correctly checked.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* #109: Non-generic implementers of generic interfaces are now correctly checked.
* `#109 <https://github.com/ESSS/oop-ext/pull/109>`_: Non-generic implementers of generic interfaces are now correctly checked.

Comment on lines +1092 to +1093
def GetOutput(self) -> T: # type:ignore[empty-body]
...
Copy link
Member

Choose a reason for hiding this comment

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

To solve this new warning we are decorating interface methods with @abstractmethod, so mypy won't complain. Also let's make the example more comprehensive by also having an input parameter:

Suggested change
def GetOutput(self) -> T: # type:ignore[empty-body]
...
@abstractmethod
def GetOutput(self, v: T) -> T:
...

Comment on lines +1089 to +1090
# Class instance defined here as a workaround for this class to work in Python 3.6.
__abstractmethods__: FrozenSet = frozenset()
Copy link
Member

Choose a reason for hiding this comment

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

Let's drop Python 3.6 first.

Suggested change
# Class instance defined here as a workaround for this class to work in Python 3.6.
__abstractmethods__: FrozenSet = frozenset()

Copy link
Member

Choose a reason for hiding this comment

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

To drop Python 3.6:

@prusse-martin
Copy link
Member

prusse-martin commented Dec 8, 2023

Definitely, IMO we can do this for all of our OS projects, supporting >=3.7 or even >=3.10 only, if the former is too much work.

I think 3.7 has reached EOL.

Yep. It did.
https://devguide.python.org/versions/

@nicoddemus
Copy link
Member

I think 3.7 has reached EOL.

You are right, let's drop that one too.

Comment on lines +13 to +25
class IFoo(Interface, typing.Generic[T]):
def Bar(self) -> T:
...


@ImplementsInterface(IFoo, no_check=True)
class Foo:
@Implements(IFoo.Bar)
def Bar(self) -> str:
return "baz"


AssertImplements(Foo, IFoo) # Ok now.
Copy link
Member

Choose a reason for hiding this comment

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

And without the no_check? Does the interface infra complain?

To appease mypy do we still have to declare TypeCheckingSupport?

Copy link
Author

Choose a reason for hiding this comment

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

And without the no_check? Does the interface infra complain?

Yes, it does complain.

To appease mypy do we still have to declare TypeCheckingSupport?

Yeah we still have to.

Copy link
Member

Choose a reason for hiding this comment

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

And without the no_check? Does the interface infra complain?

Yes, it does complain.

Why? How?

Comment on lines +1111 to +1115
AssertImplements(GenericFoo, IFoo)
AssertImplements(GenericFoo[str](output="foo"), IFoo)

# This only works if we skip the verification of `__class_getitem__` method.
AssertImplements(NonGenericFoo, IFoo)
Copy link
Member

Choose a reason for hiding this comment

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

Just a question.

What about AssertImplements(GenericFoo[str], IFoo)?

Copy link
Author

Choose a reason for hiding this comment

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

This makes it raise an AssertionError with the following error:

E AssertionError: Method 'GetOutput' is missing in class '_GenericAlias' (required by interface 'IFoo')
E type object '_GenericAlias' has no attribute 'GetOutput'

Copy link
Member

Choose a reason for hiding this comment

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

Don't we want to handle that?

AssertImplements(GenericFoo[str], IFoo[str]) also fail?

@ro-oliveira95 ro-oliveira95 marked this pull request as draft May 21, 2024 11:49
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.

3 participants