Skip to main content

A CLI tool for generating type annotations.

Project description

Typewriter

Documentation Status GitHub Actions Build Status Coverage Status Coverage Status PyPI Package latest release PyPI Wheel Supported versions Supported implementations

Overview

Typewriter is a Python Typer CLI built on LibCST that normalizes None-related type annotations while preserving formatting and comments.

What it rewrites

  • Union[T, None] -> Optional[T]
  • Union[T1, T2, None] -> Optional[Union[T1, T2]]
  • x: T = None -> x: Optional[T] = None
  • def f(x: T = None) -> def f(x: Optional[T] = None)

Additional behavior:

  • Any annotations are left unchanged (for example, x: Any = None stays unchanged).
  • Qualified typing references are preserved (for example, typing.Union[...] -> typing.Optional[...]).
  • When bare Optional[...] is introduced, Typewriter adds from typing import Optional when needed. Also, if Union is no longer needed, Typewriter removes the previously imported Union from typing.

Directory scanning behavior

When you run against a directory, Typewriter recursively processes *.py files and skips common non-source folders such as .git, .venv, venv, __pycache__, build, and dist.

Installation

pip install py-typewriter-cli

Quick Start

Suppose you start with:

from typing import Any, Union

count: int = None
name: str = None
payload: Any = None

def greet(user_id: int = None, msg: Union[str, None] = None) -> Union[str, None]:
    if user_id is None:
        return None
    return f"hello-{user_id}\n{msg}"

Preview changes:

typewriter run path/to/file.py --check

Apply changes:

typewriter run path/to/file.py

Result:

from typing import Optional, Any

count: Optional[int] = None
name: Optional[str] = None
payload: Any = None

def greet(user_id: Optional[int] = None, msg: Optional[str] = None) -> Optional[str]:
    if user_id is None:
        return None
    return f"hello-{user_id}\n{msg}"

Run recursively on a directory:

typewriter run examples

CLI

Typewriter exposes one subcommand: run.

Transform a directory

Recursively transforms all *.py files under the directory.

typewriter run path/to/python_package_or_repo

Transform a single file

typewriter run path/to/python_file.py

Non-.py files are rejected.

Check mode (no writes)

Use --check to see what would change without writing files.

typewriter run path/to/python_dir --check
typewriter run path/to/python_file.py --check

In --check mode, Typewriter prints a unified diff for each file that would change:

Would transform path/to/python_file.py
--- path/to/python_file.py
+++ path/to/python_file.py
@@ ...
-old line
+new line

Exit codes for --check:

  • 0: no changes needed
  • 1: changes would be made
  • 2: error

Transform an in-memory string

Use --code to transform a string and print the transformed code to stdout (no files are written).

typewriter run --code "var: int = None\\n"

--code is mutually exclusive with PATH. In --check mode, this reports whether the provided code would change:

typewriter run --code "var: int = None\\n" --check

When changes are needed, --check also prints a unified diff labeled provided.

Notes:

  • PATH and --code are mutually exclusive.
  • Literal \\n sequences in --code input are interpreted as newlines.

Motivation

This project was created to resolve issue #2303 in microsoft/playwright-python.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

py_typewriter_cli-0.1.0.tar.gz (11.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

py_typewriter_cli-0.1.0-py3-none-any.whl (10.0 kB view details)

Uploaded Python 3

File details

Details for the file py_typewriter_cli-0.1.0.tar.gz.

File metadata

  • Download URL: py_typewriter_cli-0.1.0.tar.gz
  • Upload date:
  • Size: 11.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for py_typewriter_cli-0.1.0.tar.gz
Algorithm Hash digest
SHA256 37e14c611edc58b817e28927cf041c436da3ccf1ea26fa4a6aa34a6ec1b7d53d
MD5 d40b132c337437d7731582238b0520dd
BLAKE2b-256 abadc7a0b7236bb4fac85c13baf28f7359945d21b1137445e516de38d201f7be

See more details on using hashes here.

File details

Details for the file py_typewriter_cli-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for py_typewriter_cli-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f40ce352a7919c0488e3b22b4ca8e7c9f4db770cc52e318c07096d8ed18a3eb3
MD5 664a4cd415cc80b52843062cc0346a5a
BLAKE2b-256 fd9a42e61910eee87103630e434e902461cca5ccfd5d2c73242012b2ea095ab8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page