com2ann

repository·master·Indexed 41 days ago

https://github.com/ilevkivskyi/com2ann

A Python tool that automates the conversion of legacy type comments into modern Python type annotations. It works at the source code and tokenizer level to preserve original formatting and supports target Python versions 3.4+. Key features include translating function signatures and assignments, wrapping long signatures, and dropping redundant assignment values like None or Ellipsis for stub generation.

Tokens
1.8K
Snippets
5
Records
7
Agent score
50%

What's inside com2ann

  1. What is com2ann?

    master

    com2ann is a tool designed to translate Python type comments into modern Python type annotations. It is built with a philosophy of being minimally invasive, working at the source code and tokenizer level rather than using AST un-parsing. This ensures that original code formatting is preserved as much as possible, including the placement of non-type comments.

    Key capabilities:

    • Translates function signature type comments to annotations.
    • Translates assignment type comments to annotations.
    • Supports target Python versions from 3.4+.
    • Can be configured to wrap long function signatures.
    • Can be configured to drop redundant assignment values (like None or ...) when generating stubs.
  2. Use com2ann to translate type comments

    master

    To use com2ann, provide an input file or directory. By default, the translation is performed in place unless an output file or directory is specified using the -o or --outfile flag.

    Example Translation:

    Input:

    from typing import Optional, Final
    
    MAX_LEVEL = 80  # type: Final
    
    class Template:
        default = None  # type: Optional[str]
    
        def apply(self, value, **opts):
            # type: (str, **bool) -> str
            ...

    Output:

    from typing import Optional, Final
    
    MAX_LEVEL: Final = 80
    
    class Template:
        default: Optional[str] = None
    
        def apply(self, value: str, **opts: bool) -> str:
            ...
    com2ann infile.py
  3. Configure signature wrapping and stub generation

    master

    Wrapping Long Signatures

    Use --wrap-signatures MAX_LENGTH to force function headers to wrap if they exceed a certain length. The tool wraps them one argument per line after each comma.

    Example with --wrap-signatures 40:

        def apply(self,
                  value: str,
                  **opts: bool) -> str:
            ...

    Generating Stubs (Dropping Redundant Assignments)

    When creating stubs, you can use --drop-none and --drop-ellipsis to remove the right-hand side of assignments that are redundant once annotated.

    Input:

    var = ...  # type: List[int]
    class Test:
        attr = None  # type: str

    Output with -n -e:

    var: List[int]
    class Test:
        attr: str
    # Example of dropping ellipsis and None for stubs
    $ com2ann -n -e input.py
  4. Configure function signature wrapping

    master

    When translating function comments, the resulting signature might be very long. You can use the wrap_sig parameter (in the API) or the --wrap-signatures flag (in the CLI) to force the tool to wrap long function headers into a multi-line format (one argument per line).

    Example transformation: Input:

    def foo(arg1: LongType1, arg2: LongType2) -> None:
        pass

    Output (with wrap_sig applied):

    def foo(arg1: LongType1,
                    arg2: LongType2) -> None:
        pass
  5. Configure com2ann CLI options

    master

    The com2ann CLI provides several options to control the translation behavior, formatting, and target Python version.

    Positional Arguments

    • infile: The input file or directory to translate. Must contain no syntax errors.

    Optional Arguments

    • -h, --help: Show help message.
    • -o OUTFILE, --outfile OUTFILE: Specify an output file or directory (overwrites if exists). Defaults to in-place.
    • -s, --silent: Suppress the summary of translated and rejected line numbers.
    • -n, --drop-none: When working with stubs, omit None as an assignment value if it is annotated by a type comment.
    • -e, --drop-ellipsis: When working with stubs, omit ... (Ellipsis) as an assignment value if it is annotated by a type comment.
    • -i, --add-future-imports: Add from __future__ import annotations to files where translation succeeded.
    • -w WRAP_SIGNATURES, --wrap-signatures WRAP_SIGNATURES: Wrap function headers longer than the specified length (one argument per line).
    • -v PYTHON_MINOR_VERSION, --python-minor-version PYTHON_MINOR_VERSION: Specify the target Python 3 minor version for parsing (supports 3.4+).
    usage: com2ann [-h] [-o OUTFILE] [-s] [-n] [-e] [-i] [-w WRAP_SIGNATURES]
                   [-v PYTHON_MINOR_VERSION]
                   infile
  6. Use the com2ann API to translate code strings

    master

    The com2ann function is the primary programmatic entry point. It takes a Python code string and converts # type: ... comments into formal type annotations. It attempts to preserve original formatting by working at the tokenizer level rather than using AST un-parsing.

    Key behaviors:

    • Assignments: x = value # type: int becomes x: int = value.
    • Function Arguments: Supports both per-argument comments and full function signature comments.
    • Special Handling: If drop_none=True, x = None # type: int becomes x: int. If drop_ellipsis=True, x = ... # type: int becomes x: int.
    • Return Types: Translates return type comments in function signatures.
    • Error Handling: If the input code has syntax errors, it returns None.
    from com2ann import com2ann
    
    code = """
    """
    def func(arg1, arg2):  # type: (int, str) -> None
        pass
    
    x = 10  # type: int
    """
    
    new_code, data = com2ann(
        code,
        drop_none=False,
        drop_ellipsis=False,
        silent=False,
        add_future_imports=True,
        wrap_sig=0,
        python_minor_version=-1
    )
    
    print(new_code)
  7. Configure com2ann via the CLI

    master

    The com2ann CLI allows you to translate files or entire directories. If no --outfile is provided, or if multiple input files are provided, translation is performed in place.

    Arguments:

    • infiles: Input files or directories (must contain no syntax errors).

    Options:

    • -o, --outfile: Output file or directory. Cannot be used with multiple input files. infiles and outfile must be the same type (file vs. directory).
    • -s, --silent: Do not print the summary of translated and rejected line numbers.
    • -n, --drop-none: Drop None as an assignment value during translation if it is annotated.
    • -e, --drop-ellipsis: Drop ... (Ellipsis) as an assignment value during translation if it is annotated.
    • -i, --add-future-imports: Add from __future__ import annotations to files where translation succeeded.
    • -w, --wrap-signatures <int>: Wrap function headers that are longer than the specified length.
    • -v, --python-minor-version <int>: Specify the Python 3 minor version to use for parsing.
    # Translate a single file in place
    com2ann my_script.py
    
    # Translate a directory and save to a different location, adding future imports
    com2ann src/ -o build/src/ --add-future-imports
    
    # Translate and drop None/Ellipsis assignments
    com2ann my_script.py --drop-none --drop-ellipsis