Skip to main content

Based static typing for Python

Project description

https://raw.githubusercontent.com/KotlinIsland/basedmypy/master/docs/static/logo-light.png

Basedmypy is a type checker that is built on top of the work done by the mypy project. It adds based functionality and breaks compatibility with the cringe parts of pep 484.

Based features

Baseline

Basedmypy has baseline, baseline is based! It allows you to adopt new strictness or features without the burden of fixing up every usage, just save all current errors to the baseline file and deal with them later.

Consider the following:

def foo(a):
    print(a)
> mypy demo.py
demo.py:1: error: missing typehints
Failed: errors found in source file


> mypy --write-baseline demo.py
demo.py:1: error: missing typehints
Baseline successfully written to .mypy/baseline.json

> mypy demo.py
Success: no issues found in 1 source file

Then on subsequent runs the existing errors will be filtered out:

def foo(a):
    print(a)

def bar(b: str, c: int) -> bool:
    return b + c
> mypy demo.py
demo.py:4:5: error: Returning Any from function declared to return "bool"  [no-any-return]
demo.py:4:16: error: Unsupported operand types for + ("str" and "int")  [operator]
Found 2 errors in 1 file (checked 1 source file)

Intersection Types

Using the & operator or basedtyping.Intersection you can denote intersection types:

class Growable(ABC, Generic[T]):
    @abstractmethod
    def add(self, item: T): ...

class Resettable(ABC):
    @abstractmethod
    def reset(self): ...

def f(x: Resettable & Growable[str]):
    x.reset()
    x.add("first")

Type Joins

Mypy joins types to their common base type:

a: int
b: str
reveal_type(a if bool() else b)  # Revealed type is "builtins.object"

Basedmypy joins types into unions instead:

a: int
b: str
reveal_type(a if bool() else b)  # Revealed type is "int | str"

Bare Literals

Literal is so cumbersome! just use a bare literal instead:

class Color(Enum):
    RED = auto()

a: 1 | 2
b: True | Color.RED

Default Return Type

The default return type of functions is None instead of Any: (configurable with the default_return option.)

def f(name: str):
    print(f"Hello, {name}!")

reveal_type(f)  # (str) -> None

Generic TypeVar Bounds

Allows the bounds of TypeVars to be generic.

So you are able to have functions with polymorphic generic parameters.

E = TypeVar("E")
I = TypeVar("I", bound=Iterable[E])

def foo(i: I, e: E) -> I:
    assert e not in i
    return i

reveal_type(foo(["based"], "mypy"))  # N: Revealed type is "list[str]"
reveal_type(foo({1, 2}, 3))  # N: Revealed type is "set[int]"

Overload Implementation Inference

The types in overload implementations (including properties) can be inferred:

@overload
def f(a: int) -> str: ...

@overload
def f(a: str) -> int: ...

def f(a):
    reveal_type(a)  # int | str
    return None  # error: expected str | int

class A:
    @property
    def foo(self) -> int: ...
    @foo.setter
    def foo(self, value): ...  # no need for annotations

Infer Function Parameters

Infer the type of a function parameter from it’s default value:

def f(a=1, b=True):
    reveal_type((a, b))  # (int, bool)

Tuple Literal Types

Basedmypy allows denotation of tuple types with tuple literals:

a: (int, str) = (1, "a")

Types in Messages

Basedmypy makes significant changes to error and info messages, consider:

T = TypeVar("T", bound=int)

def f(a: T, b: list[str | 1 | 2]) -> Never:
    reveal_type((a, b))

reveal_type(f)

Mypy shows:

Revealed type is "Tuple[T`-1, Union[builtins.str, Literal[1], Literal[2]]]"
Revealed type is "def [T <: builtins.int] (a: T`-1, b: Union[builtins.str, Literal[1], Literal[2]]) -> <nothing>"

Basedmypy shows:

Revealed type is "(T@f, str | 1 | 2)"
Revealed type is "def [T: int] (a: T, b: str | 1 | 2) -> Never"

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

basedmypy-2.4.0.tar.gz (5.3 MB view hashes)

Uploaded Source

Built Distributions

basedmypy-2.4.0-py3-none-any.whl (2.6 MB view hashes)

Uploaded Python 3

basedmypy-2.4.0-cp312-cp312-win_amd64.whl (9.6 MB view hashes)

Uploaded CPython 3.12 Windows x86-64

basedmypy-2.4.0-cp312-cp312-musllinux_1_1_x86_64.whl (12.9 MB view hashes)

Uploaded CPython 3.12 musllinux: musl 1.1+ x86-64

basedmypy-2.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.8 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64

basedmypy-2.4.0-cp312-cp312-macosx_11_0_arm64.whl (10.1 MB view hashes)

Uploaded CPython 3.12 macOS 11.0+ ARM64

basedmypy-2.4.0-cp312-cp312-macosx_10_9_x86_64.whl (11.2 MB view hashes)

Uploaded CPython 3.12 macOS 10.9+ x86-64

basedmypy-2.4.0-cp311-cp311-win_amd64.whl (9.5 MB view hashes)

Uploaded CPython 3.11 Windows x86-64

basedmypy-2.4.0-cp311-cp311-musllinux_1_1_x86_64.whl (12.8 MB view hashes)

Uploaded CPython 3.11 musllinux: musl 1.1+ x86-64

basedmypy-2.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.7 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

basedmypy-2.4.0-cp311-cp311-macosx_11_0_arm64.whl (10.1 MB view hashes)

Uploaded CPython 3.11 macOS 11.0+ ARM64

basedmypy-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl (11.1 MB view hashes)

Uploaded CPython 3.11 macOS 10.9+ x86-64

basedmypy-2.4.0-cp310-cp310-win_amd64.whl (9.5 MB view hashes)

Uploaded CPython 3.10 Windows x86-64

basedmypy-2.4.0-cp310-cp310-musllinux_1_1_x86_64.whl (12.9 MB view hashes)

Uploaded CPython 3.10 musllinux: musl 1.1+ x86-64

basedmypy-2.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.9 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

basedmypy-2.4.0-cp310-cp310-macosx_11_0_arm64.whl (10.2 MB view hashes)

Uploaded CPython 3.10 macOS 11.0+ ARM64

basedmypy-2.4.0-cp310-cp310-macosx_10_9_x86_64.whl (11.2 MB view hashes)

Uploaded CPython 3.10 macOS 10.9+ x86-64

basedmypy-2.4.0-cp39-cp39-win_amd64.whl (9.5 MB view hashes)

Uploaded CPython 3.9 Windows x86-64

basedmypy-2.4.0-cp39-cp39-musllinux_1_1_x86_64.whl (12.9 MB view hashes)

Uploaded CPython 3.9 musllinux: musl 1.1+ x86-64

basedmypy-2.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.9 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

basedmypy-2.4.0-cp39-cp39-macosx_11_0_arm64.whl (10.2 MB view hashes)

Uploaded CPython 3.9 macOS 11.0+ ARM64

basedmypy-2.4.0-cp39-cp39-macosx_10_9_x86_64.whl (11.2 MB view hashes)

Uploaded CPython 3.9 macOS 10.9+ x86-64

basedmypy-2.4.0-cp38-cp38-win_amd64.whl (9.4 MB view hashes)

Uploaded CPython 3.8 Windows x86-64

basedmypy-2.4.0-cp38-cp38-musllinux_1_1_x86_64.whl (12.9 MB view hashes)

Uploaded CPython 3.8 musllinux: musl 1.1+ x86-64

basedmypy-2.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.8 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

basedmypy-2.4.0-cp38-cp38-macosx_11_0_arm64.whl (10.2 MB view hashes)

Uploaded CPython 3.8 macOS 11.0+ ARM64

basedmypy-2.4.0-cp38-cp38-macosx_10_9_x86_64.whl (11.2 MB view hashes)

Uploaded CPython 3.8 macOS 10.9+ x86-64

Supported by

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