-
-
Notifications
You must be signed in to change notification settings - Fork 34.8k
bpo-32892: Support subclasses of base types in isinstance checks for AST constants. #9934
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -399,6 +399,10 @@ def test_isinstance(self): | |
| self.assertFalse(isinstance(ast.Constant(), ast.NameConstant)) | ||
| self.assertFalse(isinstance(ast.Constant(), ast.Ellipsis)) | ||
|
|
||
| class S(str): pass | ||
| self.assertTrue(isinstance(ast.Constant(S('42')), ast.Str)) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you please add this test?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (maybe instanciate the ast object only once)
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it looks clearer if the ast object is instantiated at the same line. In most tests different ast objects are tested in sequential lines. |
||
| self.assertFalse(isinstance(ast.Constant(S('42')), ast.Num)) | ||
|
|
||
| def test_subclasses(self): | ||
| class N(ast.Num): | ||
| def __init__(self, *args, **kwargs): | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like making this
isinstancewill allow type sub-classes for all the different constant node types. I guess this only affects 'ast' module users that are using the old class names? Just wondering if it is safe to allow any subtype in there. The constants need to get marshaled don't they?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that serialization has to be considered in isinstance().
I don't understand. The second argument is _const_types[cls], not _const_types. ast.Str only check for str and str subclasses.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean the change affects all the constant node types (Str, Num, Bytes, etc). I was wondering aloud if that was okay. I looked at the new ast.py code again today and tested older versions of Python. I think this change is fine. It only affects code that uses the backwards compatibility node types. The
_ABC.__instancecheck__is not enough to make perfect backwards compatibility. Old versions of Python didn't do any type checking for ast node values so you could do something like:That will fail with the new ast.py module, even after this PR. Maybe the following would be better. Make Constant "remember" what kind of constant node it is when created. Then have
__instancecheck__use that as the first test.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be done simpler if
Str.__new__returnStrinstead ofConstant. But I think that since old classes will be removed eventually, it is better to return the pureConstant.I don't think we should support
ast.Str({}).