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

Updated InterfaceProtocolCheckMixin & Added corresponding Tests as well ( tests_minxin ) #72

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

Conversation

RISHIKESHk07
Copy link

@RISHIKESHk07 RISHIKESHk07 commented Sep 11, 2024

Related Issue

#33

Changes Done

  • Updated the InterfaceProtocolCheckMixin in minxin file in utils folder
  • Added a line of code to check if a method is properly declared in the subclass /child class.
  • Wrote a Tests for the above in filder tests/tests_minxin.py

Summary by Sourcery

Update the InterfaceProtocolCheckMixin to include a check for method declaration in subclasses and add corresponding tests to validate this functionality.

New Features:

  • Introduce a check in the InterfaceProtocolCheckMixin to ensure methods are properly declared or overridden in subclasses.

Tests:

  • Add tests for InterfaceProtocolCheckMixin to verify that methods are correctly implemented in subclasses, including tests for both correct and incorrect implementations.

Copy link
Contributor

sourcery-ai bot commented Sep 11, 2024

Reviewer's Guide by Sourcery

This pull request updates the InterfaceProtocolCheckMixin class in the utils/mixins.py file to improve method declaration checks in subclasses. It also adds corresponding tests in a new file tests/tests_mixin.py to verify the functionality of the mixin.

File-Level Changes

Change Details Files
Enhanced method declaration check in InterfaceProtocolCheckMixin
  • Added try-except block to handle potential AttributeError
  • Implemented check to ensure method is declared/overridden in subclass
  • Added NotImplementedError raise for inherited but not overridden methods
  • Added NotImplementedError raise for methods not found in parent class
xcov19/utils/mixins.py
Added unit tests for InterfaceProtocolCheckMixin
  • Created test for incorrect implementation (missing method)
  • Created test for correct implementation
  • Implemented BaseClass for testing purposes
  • Added assertions to verify expected behavior
xcov19/tests/tests_mixin.py

Tips
  • Trigger a new Sourcery review by commenting @sourcery-ai review on the pull request.
  • Continue your discussion with Sourcery by replying directly to review comments.
  • You can change your review settings at any time by accessing your dashboard:
    • Enable or disable the Sourcery-generated pull request summary or reviewer's guide;
    • Change the review language;
  • You can always contact us if you have any questions or feedback.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

We've reviewed this pull request using the Sourcery rules engine. If you would also like our AI-powered code review then let us know.

Copy link
Contributor

@codecakes codecakes left a comment

Choose a reason for hiding this comment

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

Need refactoring and improvements.

Comment on lines +62 to +67
if defined_method in cls.__dict__:
pass
else:
raise NotImplementedError(
f"The method '{defined_method}' is inherited from the parent class '{parent_class.__name__}' and not overridden/declared."
)
Copy link
Contributor

Choose a reason for hiding this comment

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

this is a redundant overkill. L49 does exactly this, even if you remove this line.

Copy link
Author

Choose a reason for hiding this comment

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

would replacing this with commented L49 , would be fine ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a case where this is possible?

f"The method '{defined_method}' is inherited from the parent class '{parent_class.name}' and not overridden/declared."

when this part of the code kicks in?:
https://github.com/Xcov19/project-healthcare/blob/c5cdf54cf07d32f7d259d26f0a260b292da1537c/xcov19/utils/mixins.py#L49

Your block is redundant because you're reimplementing the same checks.

Comment on lines +58 to +59
cls_method = getattr(parent_class, defined_method)
subclass_method = getattr(cls, defined_method)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this even needed scoped inside?

)
except AttributeError:
raise NotImplementedError(
f"Method '{defined_method}' not found in parent class."
Copy link
Contributor

Choose a reason for hiding this comment

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

what if defined_method is defined in cls but not in parent_class? Could the try/except block be refactored to raise this part and keep the rest of the blocks same?

Copy link
Author

Choose a reason for hiding this comment

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

cls_method = getattr(parent_class, defined_method)
i thought this line would take care of that , thats why i kept it in the try catch block , correct me if i am wrong

Copy link
Contributor

Choose a reason for hiding this comment

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

There are 2 things you can do to make this clearer:

Suggestion 1

Change:
cls_method = getattr(parent_class, defined_method)
to:
parent_cls_method = getattr(parent_class, defined_method)

because parent_class -> parent_cls_method, looks more logical and then there won't be any confusion between parent_cls_method and subclass_method. You would need to make the change from cls_method-> parent_cls_method everywhere else in the code. A good IDE will help here.

Suggestion 2

You're removing this into a try block to capture exception:
https://github.com/Xcov19/project-healthcare/blob/c5cdf54cf07d32f7d259d26f0a260b292da1537c/xcov19/utils/mixins.py#L56

here:

except AttributeError:

Another way to refactor the class could be:

if not (
  hasattr(parent_class, defined_method) and (parent_cls_method := getattr(parent_class, defined_method))
):
  # you raise here

This way you wouldn't need to do alot of bloated checks in the block you have introduced and you'd trim down the lines.

Copy link
Author

Choose a reason for hiding this comment

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

@codecakes sorry about the hiatus , over here when we use hasattr the subclass method which is inherited from parent would make this True , so here we cannot differentiate whether this was inherited or overidden , it was this case which made me forget about completing the issue .

# Define IncorrectImplementation inside the test function
try:

class IncorrectImplementation(BaseClass, InterfaceProtocolCheckMixin):
Copy link
Contributor

Choose a reason for hiding this comment

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

I am of the opinion that stub classes should be defined already. Included in the file before these test cases.



def test_correct_implementation():
class CorrectImplementation(BaseClass, InterfaceProtocolCheckMixin):
Copy link
Contributor

Choose a reason for hiding this comment

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

ditto as above

Copy link
Contributor

@codecakes codecakes left a comment

Choose a reason for hiding this comment

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

i hope this helps.

Comment on lines +62 to +67
if defined_method in cls.__dict__:
pass
else:
raise NotImplementedError(
f"The method '{defined_method}' is inherited from the parent class '{parent_class.__name__}' and not overridden/declared."
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a case where this is possible?

f"The method '{defined_method}' is inherited from the parent class '{parent_class.name}' and not overridden/declared."

when this part of the code kicks in?:
https://github.com/Xcov19/project-healthcare/blob/c5cdf54cf07d32f7d259d26f0a260b292da1537c/xcov19/utils/mixins.py#L49

Your block is redundant because you're reimplementing the same checks.

)
except AttributeError:
raise NotImplementedError(
f"Method '{defined_method}' not found in parent class."
Copy link
Contributor

Choose a reason for hiding this comment

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

There are 2 things you can do to make this clearer:

Suggestion 1

Change:
cls_method = getattr(parent_class, defined_method)
to:
parent_cls_method = getattr(parent_class, defined_method)

because parent_class -> parent_cls_method, looks more logical and then there won't be any confusion between parent_cls_method and subclass_method. You would need to make the change from cls_method-> parent_cls_method everywhere else in the code. A good IDE will help here.

Suggestion 2

You're removing this into a try block to capture exception:
https://github.com/Xcov19/project-healthcare/blob/c5cdf54cf07d32f7d259d26f0a260b292da1537c/xcov19/utils/mixins.py#L56

here:

except AttributeError:

Another way to refactor the class could be:

if not (
  hasattr(parent_class, defined_method) and (parent_cls_method := getattr(parent_class, defined_method))
):
  # you raise here

This way you wouldn't need to do alot of bloated checks in the block you have introduced and you'd trim down the lines.

Comment on lines +9 to +10


Copy link
Contributor

Choose a reason for hiding this comment

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

You could simply move the setup before actual tests so the definitions would be clearer to read and your code would only instantiate it.

Suggested change
class IncorrectImplementation(BaseClass, InterfaceProtocolCheckMixin):
"""Does not implement method_with_params"""
pass

@codecakes
Copy link
Contributor

@sourcery-ai review

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

We've reviewed this pull request using the Sourcery rules engine. If you would also like our AI-powered code review then let us know.

@codecakes
Copy link
Contributor

@sourcery-ai review

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @RISHIKESHk07 - I've reviewed your changes - here's some feedback:

Overall Comments:

  • Consider simplifying the method checking logic in __init_subclass__ to avoid nested try-except blocks and reduce the use of exceptions for control flow.
  • The TODO comment in __init_subclass__ has been addressed and can be removed.
Here's what I looked at during the review
  • 🟡 General issues: 1 issue found
  • 🟢 Security: all looks good
  • 🟡 Review instructions: 1 issue found
  • 🟢 Testing: all looks good
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment to tell me if it was helpful.

Comment on lines +62 to +63
if defined_method in cls.__dict__:
pass
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion (review_instructions): Consider removing unnecessary 'pass' statement.

The 'pass' statement here is not needed as the 'if' block can be empty. This would make the code more concise.

                if defined_method not in cls.__dict__:
                    raise NotImplementedError(
Review instructions:

Path patterns: **/*.py, **/*.js, **/*.ex

Instructions:

  • Check code for Google style guide for python code.
  • Review code for Top 10 OWASP recommendations.

@@ -53,8 +52,24 @@ def __init_subclass__(cls, **kwargs):
if not method_name.startswith("__")
):
# TODO: Raise if either classes don't have the method declared.
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion: Update or remove the TODO comment

This TODO comment seems to be addressed by the new code. Consider removing it or updating it to reflect any remaining tasks.

            # Ensure both classes have the method declared before proceeding

Copy link

sonarcloud bot commented Sep 14, 2024

@codecakes codecakes added bug Something isn't working Mend: configuration error Mend configuration error labels Sep 14, 2024
@codecakes codecakes added this to the v1 milestone Sep 14, 2024
Copy link
Contributor

@codecakes codecakes left a comment

Choose a reason for hiding this comment

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

@RISHIKESHk07 added some more feedback for scope for code improvement.

class BaseClass:
@classmethod
def method_with_params(cls, param1: int, param2: str) -> None:
pass
Copy link
Contributor

Choose a reason for hiding this comment

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

Add a nested comment explaining what this method is achieves even though it is empty.

class CorrectImplementation(BaseClass, InterfaceProtocolCheckMixin):
@classmethod
def method_with_params(cls, param1: int, param2: str) -> None:
pass
Copy link
Contributor

Choose a reason for hiding this comment

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

same here. Add a nested comment.

Comment on lines +13 to +22
try:

class IncorrectImplementation(BaseClass, InterfaceProtocolCheckMixin):
"""Does not implement method_with_params"""

pass

IncorrectImplementation()

except NotImplementedError as exec:
Copy link
Contributor

Choose a reason for hiding this comment

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

replace with self.assertRaises or if not using unittest.TestCaset then pytest.raises; same in everywhere else.

try:
instance = CorrectImplementation()
instance.method_with_params(1, "test")
assert True
Copy link
Contributor

Choose a reason for hiding this comment

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

assert raise or assert on instance. assert True is an oxymoron.

@VedantKhairnar
Copy link

Hello @RISHIKESHk07
We have extended the deadline of PR merge of Augtoberfest to tomorrow EoD. If you can implement the required changes soon, we will be able to merge it by tomorrow.
Thanks.

@RISHIKESHk07
Copy link
Author

Thanks for that @VedantKhairnar , due to academic exams I have been inactive for a few days will try work on the issue as time permits

@RISHIKESHk07
Copy link
Author

@codecakes Sorry about the hiatus , did add a extra doubt above in the minxins.py conversations

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Mend: configuration error Mend configuration error
Projects
None yet
3 participants