Skip to content

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

Merged
pablogsal merged 5 commits into
python:masterfrom
pablogsal:bpo34939
Oct 14, 2018
Merged

bpo-34939: Allow annotated global names in module namespace#9844
pablogsal merged 5 commits into
python:masterfrom
pablogsal:bpo34939

Conversation

@pablogsal

@pablogsal pablogsal commented Oct 13, 2018

Copy link
Copy Markdown
Member

@pablogsal pablogsal self-assigned this Oct 13, 2018
@tirkarthi

Copy link
Copy Markdown
Member

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

Thanks

@ilevkivskyi ilevkivskyi left a comment

Copy link
Copy Markdown
Member

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.

Comment thread Python/symtable.c Outdated
&& s->v.AnnAssign.simple) {
if (((cur & DEF_NONLOCAL) |
((cur & DEF_GLOBAL) && !(cur & DEF_GLOBAL_TOP))
) && s->v.AnnAssign.simple) {

Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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.

Comment thread Lib/test/test_grammar.py Outdated
global x
x = 1
x:int = 3
"""))

Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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)?

@ilevkivskyi ilevkivskyi left a comment

Copy link
Copy Markdown
Member

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.

Comment thread Lib/test/test_symtable.py Outdated
# 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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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