Skip to content

bpo-34939: Allow annotated global names in module namespace #9844

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

Merged
merged 5 commits into from
Oct 14, 2018

Conversation

pablogsal
Copy link
Member

@pablogsal pablogsal commented Oct 13, 2018

@pablogsal pablogsal self-assigned this Oct 13, 2018
@tirkarthi
Copy link
Member

@ilevkivskyi Is there any documentation update needed with respect to https://bugs.python.org/issue34939#msg327386 ?

Thanks

Copy link
Member

@ilevkivskyi ilevkivskyi left a comment

Choose a reason for hiding this comment

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

Thanks for working on this! Here are some comments.

&& s->v.AnnAssign.simple) {
if (((cur & DEF_NONLOCAL) |
((cur & DEF_GLOBAL) && !(cur & DEF_GLOBAL_TOP))
) && s->v.AnnAssign.simple) {
Copy link
Member

Choose a reason for hiding this comment

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

Adding a new symbol table flag to solve this looks like an overkill (plus TBH I don't fully understand this solution). Why not just skip emitting this error at global scope? For example check that st->st_cur->ste_symbols != st->st_global?

Copy link
Member

Choose a reason for hiding this comment

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

I would probably also add a comment here explaining that annotation forces a variable to be local for current scope, while global forces it to be global, so these two "directives" are conflicting, unless we are currently at the global scope.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for the review @ilevkivskyi. This is the first time I touch the symtable so sorry if the original proposed solution was a bit convoluted. I have simplified it in 701bffe.

global x
x = 1
x:int = 3
"""))
Copy link
Member

Choose a reason for hiding this comment

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

I would reserve this test file only for basic things. I propose to add this test to either test_symtable.py or test_syntax.py.

Also there is even a simpler repro for the issue:

global x
x: int  # SyntaxError

plus I would add test cases for nonlocal as well (even though it already works).

Copy link
Member Author

Choose a reason for hiding this comment

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

It seems that test_syntax tests all raise SyntaxErrors, but in this case, we want to test that the solution is valid. On the other hand, test_symtable seems to test the symtable properties directly, as opposed to check that something is a valid Syntax or not. I am a bit unsure on which file to put the reproducer (along with the "nonlocal" one).

Copy link
Member Author

Choose a reason for hiding this comment

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

I have moved the tests to test_symtable in 0e21eba.

Copy link
Member Author

Choose a reason for hiding this comment

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

I have openend #9872 as there are no current way to test for nonlocal declarations in the symtable python module.

@ilevkivskyi
Copy link
Member

@tirkarthi I don't have ideas for better wording. Maybe just note that this is an error only for non-global scope (because annotation forces a variable to be local for current scope)?

Copy link
Member

@ilevkivskyi ilevkivskyi left a comment

Choose a reason for hiding this comment

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

Thanks! I have one additional suggestion. Feel free to merge after you address it.

# Test that annotations for nonlocals are valid after the
# variable is declared as nonlocal.
st6 = symtable.symtable('def g():\n x=2\n def f():\n'
' nonlocal x\n x:int', 'test', 'exec')
Copy link
Member

Choose a reason for hiding this comment

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

Complex multi-line tests are easier to read if you split them like this:

        st6 = symtable.symtable('def g():\n'
                                '    x = 2\n'
                                '    def f():\n'
                                '        nonlocal x\n'
                                '    x: int',
                                'test', 'exec')

(Also I would stick to PEP 8 even in tests, see other test above. In this case space around = and space after : in annotation.)

Copy link
Member Author

Choose a reason for hiding this comment

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

Done in 547dbba. I would like to add an extra nonlocal check to st6 after if #9872 is merged.

@pablogsal
Copy link
Member Author

@ilevkivskyi Thank you very much for the review and the helpful advice :)

@pablogsal pablogsal merged commit de2aea0 into python:master Oct 14, 2018
@pablogsal pablogsal deleted the bpo34939 branch October 14, 2018 17:01
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.

5 participants