Metadata-Version: 2.1
Name: basedmypy
Version: 1.8.0
Summary: Based static typing for Python
Author: KotlinIsland
License: MIT License
Project-URL: News, https://github.com/KotlinIsland/basedmypy/releases
Project-URL: Documentation, https://github.com/KotlinIsland/basedmypy/wiki
Project-URL: Repository, https://github.com/KotlinIsland/basedmypy
Project-URL: Discord, https://discord.gg/7y9upqPrk2
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Software Development
Classifier: Typing :: Typed
Requires-Python: >=3.7
License-File: LICENSE
Requires-Dist: basedtyping (>=0.0.3)
Requires-Dist: typing-extensions (>=3.10)
Requires-Dist: mypy-extensions (>=1.0.0)
Requires-Dist: tomli (>=1.1.0) ; python_version < "3.11"
Requires-Dist: typed-ast (<2,>=1.4.0) ; python_version < "3.8"
Provides-Extra: dmypy
Requires-Dist: psutil (>=4.0) ; extra == 'dmypy'
Provides-Extra: install-types
Requires-Dist: pip ; extra == 'install-types'
Provides-Extra: python2
Requires-Dist: typed-ast (<2,>=1.4.0) ; extra == 'python2'
Provides-Extra: reports
Requires-Dist: lxml ; extra == 'reports'

Basedmypy -- Based Static Typing for Python
===========================================

Ever tried to use pythons type system and thought to yourself "This doesn't seem based".

Well fret no longer as basedmypy got you covered!

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.

.. code-block:: python

    def foo(a):
        print(a)

.. code-block:: bash

    > mypy test.py
    error: missing typehints !!!!!
    Epic fail bro!

    > mypy --write-baseline test.py
    test.py:1:1: error: Function is missing a type annotation for one or more arguments  [no-untyped-def]
    Baseline successfully written to .mypy/baseline.json

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

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

.. code-block:: python

    def foo(a):
        print(a)

    def bar(b: str, c: int) -> bool:
        return b + c

.. code-block:: bash

    > mypy test.py
    test.py:4:5: error: Returning Any from function declared to return "bool"  [no-any-return]
    test.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.

.. code-block:: python

    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 like so:

.. code-block:: python

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

Basedmypy joins types into unions instead:

.. code-block:: python

    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.

.. code-block:: python

    class Color(Enum):
        RED = auto()

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


Default Return Type
-------------------

With the ``default_return`` option, the default return type of functions becomes ``None`` instead of `Any`.

.. code-block:: python

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

    reveal_type(f)  # (str) -> None

Nested TypeVars
---------------

With nested ``TypeVar``\s you are able to have functions with polymorphic generic parameters.

.. code-block:: python

    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
---------------------------------

Specifying types in overload implementations is completely redundant! basedmypy will infer them.

.. code-block:: python

    @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.

.. code-block:: python

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

Better Types in Messages
------------------------

.. code-block:: python

    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"

Ignore Unused Type Ignores
--------------------------

In code that is targeting multiple versions of python or multiple platforms it is difficult
to work with `type: ignore` comments and use the `warn_unused_ignore` option.

The ``unused-ignore`` error code can be used for this situation.

.. code-block:: python

    if sys.platform != "linux":
      foo()  # type: ignore[misc, unused-ignore]
