Skip to content
This repository was archived by the owner on Oct 1, 2019. It is now read-only.

Non-injective token to AST mappings #22

Open
taion opened this issue Jan 14, 2018 · 4 comments
Open

Non-injective token to AST mappings #22

taion opened this issue Jan 14, 2018 · 4 comments

Comments

@taion
Copy link
Contributor

taion commented Jan 14, 2018

There are a number of cases in Python where the token-to-AST mapping is very clearly non-injective, where multiple different-looking statements are syntactically equivalent. We should think about how to handle these; perhaps this will require looking at the actual tokens.

Usually only one use case is common, but mangling tokens might be a bit much.

1. elif (#7)

if foo:
    foo()
elif bar:
    bar()


if foo:
    foo()
else:
    if bar:
        bar()

2. Nested with in Python 2 (#15)

with a, b:
    pass


with a:
    with b:
        pass

3. as in except in Python 2

try:
    foo()
except A as a:
    pass


try:
    foo()
except A, a:
    pass

4. Empty parent class

class Foo:
    pass


class Foo():
    pass
@patrick91
Copy link
Member

  1. I'd say let's leave like it is now (merging the ifs), if that's going to be a problem we can change that in the future :)
  2. I'd like to merge the with statements if possible
  3. Let's use as, since works for both python 2 and 3 :)
  4. I'd prefer to have no parenthesis

@taion
Copy link
Contributor Author

taion commented Jan 14, 2018

The comma syntax in except is a Python 2.5 thing so probably it's dead.

The nested with statements do arise in real code, though: https://github.com/tensorflow/models/blob/1887a5fe187c8ab9f623cd91b74fc8432ce76d6f/research/slim/nets/mobilenet_v1.py#L199-L200

Part of the issue is that there's not a good way to break with statements to multiple lines. Neither of the following work:

with (
    Foo() as foo,
    Bar() as bar,
):
    pass

with (
    Foo() as foo
), (
    Bar() as bar
):
    pass

The closest is something like:

with \
        Foo() as foo, \
        Bar() as bar:
    pass

But this is less than pretty.

@taion
Copy link
Contributor Author

taion commented Jan 14, 2018

Makes you wish they didn't drop contextlib.nested in Python 3. ExitStack can give the same semantics but it's more annoying to use.

@taion
Copy link
Contributor Author

taion commented Jan 14, 2018

YAPF's output here is good for a giggle, though:

# In:
with \
    Foo() as foo, \
    Foo() as foo_2, \
    Bar(
        long_argument,
        long_argument,
        long_argument,
        long_argument,
        long_argument,
    ) as bar, \
    Baz(some_arg) as baz, \
    Baz(some_arg) as baz_2 \
:
    pass

# Out:
with Foo() as foo, Foo() as foo_2, Bar(
        long_argument,
        long_argument,
        long_argument,
        long_argument,
        long_argument,
) as bar, Baz(some_arg) as baz, Baz(some_arg) as baz_2:
    pass

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants