Skip to content

Use lowercase type everywhere #6853

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 6 commits into from
Jan 8, 2022
Merged

Conversation

AlexWaygood
Copy link
Member

This PR was prepared using the following script:
import ast
import re
import subprocess
import sys
from itertools import chain
from pathlib import Path
from typing import NamedTuple


class DeleteableImport(NamedTuple):
    old: str
    replacement: str


FAILURES = []


def fix_bad_syntax(path: Path) -> None:
    with open(path) as f:
        stub = f.read()

    lines = stub.splitlines()
    tree = ast.parse(stub)
    imports_to_delete = {}
    type_from_typing = False

    class BadImportFinder(ast.NodeVisitor):
        def visit_ImportFrom(self, node: ast.ImportFrom) -> None:
            nonlocal type_from_typing

            if node.module != "typing":
                return

            if any(cls.name == "Type" for cls in node.names):
                type_from_typing = True
            else:
                return

            new_import_list = [cls for cls in node.names if cls.name != "Type"]

            ### DEALING WITH EXISTING IMPORT STATEMENTS ###

            # Scenario (1): Now we don't need *any* imports from typing any more.
            # Don't touch the imports in collections/__init__.pyi as it causes a mypy crash (don't know why)
            if not new_import_list and path != Path("stdlib/collections/__init__.pyi"):
                imports_to_delete[node.lineno - 1] = DeleteableImport(old=ast.unparse(node), replacement="")

            # Scenario (2): we still need imports from typing; the existing import statement is only one line
            elif node.lineno == node.end_lineno:
                imports_to_delete[node.lineno - 1] = DeleteableImport(
                    old=ast.unparse(node),
                    replacement=ast.unparse(ast.ImportFrom(module="typing", names=new_import_list, level=0)),
                )

            # Scenario (3): we still need imports from typing; the existing import statement is multiline.
            else:
                for cls in node.names:
                    if cls.name == "Type":
                        imports_to_delete[cls.lineno - 1] = DeleteableImport(
                            old=f"Type," if cls.asname is None else f"Type as {cls.asname},", replacement=""
                        )

    BadImportFinder().visit(tree)

    if not type_from_typing:
        return

    for lineno, (old_syntax, new_syntax) in imports_to_delete.items():
        lines[lineno] = lines[lineno].replace(old_syntax, new_syntax)

    try:
        new_tree = ast.parse("\n".join(lines))
    except SyntaxError:
        sys.stderr.write(f"Error converting new syntax in {path}")
        FAILURES.append(path)
    else:
        lines_with_bad_syntax = []

        class OldSyntaxFinder(ast.NodeVisitor):
            def visit_Subscript(self, node: ast.Subscript) -> None:
                if isinstance(node.value, ast.Name) and node.value.id == "Type":
                    lines_with_bad_syntax.append(node.lineno - 1)
                self.generic_visit(node)

        OldSyntaxFinder().visit(new_tree)

        for lineno in lines_with_bad_syntax:
            lines[lineno] = re.sub(fr"(\W)Type\[", fr"\1type[", lines[lineno])

    with open(path, "w") as f:
        f.write("\n".join(lines) + "\n")


def main() -> None:
    print("STARTING RUN: Will attempt to fix new syntax in typeshed directory...\n\n")
    for path in chain(Path("stdlib").rglob("*.pyi"), Path("stubs").rglob("*.pyi")):
        if "@python2" in path.parts:
            print(f"Skipping {path}: Python-2 stub")
        elif Path("stubs/protobuf/google/protobuf") in path.parents:
            print(f"Skipping {path}: protobuf stub")
        else:
            print(f"Attempting to convert {path} to new syntax.")
            fix_bad_syntax(path)

    print("\n\nSTARTING ISORT...\n\n")
    for folder in {"stdlib", "stubs", "tests"}:
        subprocess.run([sys.executable, "-m", "isort", folder])

    print("\n\nSTARTING BLACK...\n\n")
    subprocess.run([sys.executable, "-m", "black", "."])

    if FAILURES:
        print("\n\nFAILED to convert the following files to new syntax:\n")
        for path in FAILURES:
            print(f"- {path}")
    else:
        print("\n\nThere were ZERO failures in converting to new syntax. HOORAY!!\n\n")

    print('\n\nRunning "check_new_syntax.py"...\n\n')
    subprocess.run([sys.executable, "tests/check_new_syntax.py"])

    print('\n\nRunning "stubtest_stdlib.py"...\n\n')
    subprocess.run([sys.executable, "tests/stubtest_stdlib.py"])


if __name__ == "__main__":
    main()

@github-actions

This comment has been minimized.

2 similar comments
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@AlexWaygood
Copy link
Member Author

I think the third-party stubtest failures for requests are unrelated to this PR?

@AlexWaygood
Copy link
Member Author

The only change to requests stubs that this PR makes is in stubs/requests/requests/models.pyi, and that looks fine to me.

@hauntsaninja
Copy link
Collaborator

Looks like it's failing on master too, https://github.com/python/typeshed/actions/runs/1669875816
requests 2.27.1 was released in the last two days, so maybe that's it

@srittau
Copy link
Collaborator

srittau commented Jan 8, 2022

#6858 for part 1 for a requests fix.

Copy link
Collaborator

@srittau srittau left a comment

Choose a reason for hiding this comment

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

I did a spot check and this looks good.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 8, 2022

According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉

@srittau srittau merged commit a40d79a into python:master Jan 8, 2022
@AlexWaygood AlexWaygood deleted the lowercase-type branch January 8, 2022 15:32
@AlexWaygood
Copy link
Member Author

Thanks for the mypy fix @sobolevn 😀

@sobolevn
Copy link
Member

sobolevn commented Jan 8, 2022

Happy to help! 😉

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.

4 participants