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/callable protocols 2 #599

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

MiguelMonteiro
Copy link
Contributor

@MiguelMonteiro MiguelMonteiro commented Oct 15, 2024

What does this PR do?

Fixes callable protocol inheritance by allowing a list of private methods to be considered when matching signatures for inheritance of subclasses. The set of allowed_dunder_methods currently only contains the __call__ method.

Fixes #595

Before submitting

  • Did you read the contributing guideline?
  • Did you update the documentation? (readme and public docstrings)
  • Did you write unit tests such that there is 100% coverage on related code? (required for bug fixes and new features)
  • Did you verify that new and existing tests pass locally?
  • Did you make sure that all changes preserve backward compatibility?
  • Did you update the CHANGELOG? (not for typos, docs, test updates, or minor internal changes/refactors)

Copy link

codecov bot commented Oct 15, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 100.00%. Comparing base (3f62519) to head (8a868e5).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #599   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           22        22           
  Lines         6492      6493    +1     
=========================================
+ Hits          6492      6493    +1     
Flag Coverage Δ
py3.10 85.76% <100.00%> (+<0.01%) ⬆️
py3.10_all 98.79% <100.00%> (+<0.01%) ⬆️
py3.10_pydantic1 49.14% <0.00%> (-0.01%) ⬇️
py3.10_pydantic2 48.92% <0.00%> (-0.01%) ⬇️
py3.10_types 98.81% <100.00%> (+<0.01%) ⬆️
py3.11 85.95% <100.00%> (+<0.01%) ⬆️
py3.11_all 98.75% <100.00%> (+<0.01%) ⬆️
py3.11_types 98.76% <100.00%> (+<0.01%) ⬆️
py3.12 86.09% <100.00%> (+<0.01%) ⬆️
py3.12_all 98.75% <100.00%> (+<0.01%) ⬆️
py3.12_types 98.76% <100.00%> (+<0.01%) ⬆️
py3.8 86.38% <100.00%> (+<0.01%) ⬆️
py3.8_all 99.43% <100.00%> (+<0.01%) ⬆️
py3.8_types 99.46% <100.00%> (+<0.01%) ⬆️
py3.9 86.32% <100.00%> (+<0.01%) ⬆️
py3.9_all 99.38% <100.00%> (+<0.01%) ⬆️
py3.9_types 99.39% <100.00%> (+<0.01%) ⬆️

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

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member

@mauvilsa mauvilsa left a comment

Choose a reason for hiding this comment

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

Please add a unit test for a protocol with __call__.

Comment on lines +17 to +19
Fixed
^^^^^
- Fix callable protocol inheritance.
Copy link
Member

Choose a reason for hiding this comment

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

v4.34.0 hasn't been released yet, so this entry should be there instead of a new v4.34.1 section. Also please add a link to this pull request.

from jsonargparse._parameter_resolvers import get_signature_parameters
from jsonargparse._postponed_annotations import get_return_type

if not inspect.isclass(value):
return False
members = 0
for name, _ in inspect.getmembers(protocol, predicate=inspect.isfunction):
if name.startswith("_"):
if name.startswith("_") and name not in allowed_dunder_methods:
Copy link
Member

Choose a reason for hiding this comment

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

Give me some time and I analyze the dunder methods in general and maybe in this pull request we do more than __call__.

Copy link

sonarcloud bot commented Oct 16, 2024



class CallableInterface(Protocol):
def __call__(self, items: List[float]) -> List[float]: ...

Check notice

Code scanning / CodeQL

Statement has no effect Note test

This statement has no effect.
@MiguelMonteiro
Copy link
Contributor Author

Please add a unit test for a protocol with __call__.

I added some tests for callable protocols. One question that came up is whether functions should be checked against the protocol. Currently that test is failing, here is the example:

class CallableInterface(Protocol):
    def __call__(self, items: List[float]) -> List[float]: ...


class ImplementsCallableInterface1:
    def __init__(self, batch_size: int):
        self.batch_size = batch_size

    def __call__(self, items: List[float]) -> List[float]:
        return items

def implements_callable_interface2(items: List[float]) -> List[float]:
    return items

The result is:

implements_protocol(ImplementsCallableInterface1, CallableInterface) = True
implements_protocol(implements_callable_interface2, CallableInterface) = False

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.

Callable protocols inheritance broken
2 participants