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

use full name for Attributes #507

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

Conversation

fefe982
Copy link
Contributor

@fefe982 fefe982 commented Jan 15, 2025

Changes

Fixes #506

In assignment check, when attribute is added:

  1. Attribute is only handled in tuple, but not bare attribute assignments. Add check for bare attribute assignment
  2. exp.id is used for Attribute, but for Attribute, it points to the parent object, not the attribute. Changed it to use name ,which is obj.attr, the full path.

Checklist

If this is a user-facing code change, like a bugfix or a new feature, please ensure that
you've fulfilled the following conditions (where applicable):

  • You've added tests (in tests/) added which would fail without your patch
  • You've updated the documentation (in docs/, in case of behavior changes or new
    features)
  • You've added a new changelog entry (in docs/versionhistory.rst).

@coveralls
Copy link

coveralls commented Jan 15, 2025

Coverage Status

coverage: 94.316% (-0.2%) from 94.511%
when pulling 5cf59d4 on fefe982:fix_issue506
into 91b0cbd on agronholm:master.

@fefe982
Copy link
Contributor Author

fefe982 commented Jan 16, 2025

  1. Attribute is only handled in tuple, but not bare attribute assignments. Add check for bare attribute assignment
  2. exp.id is used for Attribute, but for Attribute, it points to the parent object, not the attribute. Changed it to use name ,which is obj.attr, the full path.

The new commit reverted change 2, keeping the annotation of the parent object. Instead, it changed check_variable_assignment, to get the real annotation of the attribute from the parent object. In this way the type of attribute can be correctly checked.

Other changes are due to the pytest does not pass on my Windows machine occasionally, as the path is case insensitive on Windows, and the case changed.

@agronholm
Copy link
Owner

I'll try to find time to review this on the weekend.

Copy link
Owner

@agronholm agronholm left a comment

Choose a reason for hiding this comment

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

Style fixes and a question.

Comment on lines +14 to +19
if (
os.name == "nt"
): # file path name (and drive letter) is case insensitive on windows
assert warning.list[0].filename.lower() == __file__.lower()
else:
assert warning.list[0].filename == __file__
Copy link
Owner

Choose a reason for hiding this comment

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

What exactly prompted this change? Was something failing?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It break test on Windows. The drive letter (D:\) can be either lower or upper case. And they do appear differently two sides sometime.

However, they do not always appear differently. So this sometimes make the tests fail on my windows machine. I do know how to definitely reproduce this. Windows is case insensitive. Maybe os.path.normcase can be used avoid the test for OS.

Comment on lines +287 to +296
have_annotation_for_attribute = True
for seg in varpath[1:]:
if not inspect.isclass(annotation):
have_annotation_for_attribute = False
break
if sys.version_info >= (3, 10):
annotation = inspect.get_annotations(annotation).get(seg)
else:
annotation = annotation.__annotations__.get(seg)
if have_annotation_for_attribute:
Copy link
Owner

Choose a reason for hiding this comment

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

Separate unrelated control blocks for code readability. I wish I could enforce this with Ruff.

Suggested change
have_annotation_for_attribute = True
for seg in varpath[1:]:
if not inspect.isclass(annotation):
have_annotation_for_attribute = False
break
if sys.version_info >= (3, 10):
annotation = inspect.get_annotations(annotation).get(seg)
else:
annotation = annotation.__annotations__.get(seg)
if have_annotation_for_attribute:
have_annotation_for_attribute = True
for seg in varpath[1:]:
if not inspect.isclass(annotation):
have_annotation_for_attribute = False
break
if sys.version_info >= (3, 10):
annotation = inspect.get_annotations(annotation).get(seg)
else:
annotation = annotation.__annotations__.get(seg)
if have_annotation_for_attribute:

@agronholm
Copy link
Owner

So the thing is, Typeguard so far hasn't checked attribute assignments, or at least that it didn't intend to. I haven't yet fully delved into the details of this PR, but is your intention to add checks for attribute assignments?

@agronholm
Copy link
Owner

agronholm commented Jan 19, 2025

So the thing is, Typeguard so far hasn't checked attribute assignments, or at least that it didn't intend to. I haven't yet fully delved into the details of this PR, but is your intention to add checks for attribute assignments?

Never mind, judging from the tests it looks like this was indeed your intention. But attribute assignment is much more complicated than local variable assignment due to the potential interference by descriptors and __setattr__(), and I'm not prepared to handle all that complexity. Until there is a plan to handle that aspect of attribute assignment, I'm not ready to accept such a new feature. Let's just focus on fixing this one false positive.

@agronholm
Copy link
Owner

Ok, I've pushed a fix for the linked issue. Given that this PR (as I understand) expands the capabilities of Typeguard, we should take our time to sort out any potential issues with descriptors and __setattr__(), okay?

@fefe982
Copy link
Contributor Author

fefe982 commented Jan 20, 2025

I did wonder why the code some check for Attribute and included it, but not actually do the check :)

I only added type check for attributes that there is an annotation. Anything other than that are not checked.

I agree with that we leave this until we know more.

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.

TypeCheckError when tuple unpacking to properties of method parameter
3 participants