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

wish: remove attribute annotations not generating code #95

Open
wrohdewald opened this issue Oct 14, 2023 · 4 comments
Open

wish: remove attribute annotations not generating code #95

wrohdewald opened this issue Oct 14, 2023 · 4 comments

Comments

@wrohdewald
Copy link

var: str

is a legal annotation but it creates no executable code. Would be nice to remove these.

I am using python-minifier for asserting that a commit only changes annotations but not real code. Very helpful for annotating old source code. Or would there be a better tool for this?

@dflook
Copy link
Owner

dflook commented Oct 14, 2023

Hi @wrohdewald, that's an interesting use of python-minifier!

A statement like var: str is an assignment without a value, but it puts the namevar in the local scope the same way var: str = 'foo' would do. You're right it has no effect when executed, but it's presence can affect the behaviour of a program.

Consider this program:

var = 'hello'
def func():
    var: str
    print(var)

When func() is executed it should raise UnboundLocalError because var is in the function namespace but has no value. If we removed the var: str statement it would print 'hello' instead.

What python-minifier should be doing is replacing the annotation value with '0', e.g

var = 'hello'
def func():
    var: 0
    print(var)

which should preserve the behaviour but make the annotation shorter.

@wrohdewald
Copy link
Author

wrohdewald commented Oct 28, 2023

OK, I see why this cannot be safely removed - at least not without a special option. Shortening is not much of a help - the diff output I have to read does not get shorter.

OTOH - what about code under if TYPE_CHECKING - if and only if TYPE_CHECKING is the original typing.TYPE_CHECKING - I see no reason why this could not be safely removed.

Like in

from typing import TYPE_CHECKING

b = cast(int, 1)
reveal_type(b)

if TYPE_CHECKING:
        a = 5

assert 'b' in globals()
assert 'a' not in globals()

expecting

b=1
assert'b'in globals()
assert'a'not in globals()

typing.cast() would be another candidate. reveal_type() too - it is only recognized by mypy.

@dflook
Copy link
Owner

dflook commented Oct 28, 2023

Hi @wrohdewald, that's a good idea

@wrohdewald
Copy link
Author

This works for me, but I do not know enough about ast to finish this. Like when somebody renames or redefines TYPE_CHECKING or cast()

class RemoveAnnotations(SuiteTransformer):
   ...
    def visit_If(self, node):
        if hasattr(node.test, 'id') and node.test.id == 'TYPE_CHECKING':
            return ast.Pass()
        return node

    def visit_ImportFrom(self, node):
        if node.module == 'typing':
            return ast.Pass()
        return node

   def visit_Call(self, node):
        if hasattr(node, 'func'):
            if hasattr(node.func, 'id'):
                if node.func.id == 'cast' and len(node.args) == 2:
                    return node.args[1]
        return node

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

No branches or pull requests

2 participants