mypy

Kilka pojęć wstępnych

There are two independent characteristics that describe programming languages.

  • When types are checked?
  • How strictly types are checked?

When types are checked?

Statically typed languages check the types and look for type errors during compile time.

Dynamically typed languages check the types and look for type errors during runtime.

How strictly types are checked?

In a weakly typed language, the type of a value depends on how it is used.

In a strongly typed language, a value has a type and that type cannot change. What you can do to a value depends on the type of the value.

What is type hinting in python?

  • Python is (and always will) very dynamically typed and rather strong. This means that variables can change types during execution, but each change has to be explicit. Python will not attempt to execute code ,,no matter what".
  • One can annotate functions with type hints. It is treated as a comment by the intepreter, but programmer sees it in the code and tools like linters or IDEs plugins can analyze them.
  • You get no guarantee that variable you get will be of a type you expect.
  • That is why everyone would prefer to write in functional, strong, static typed languages like Haskell or Scala :D

Po co używać podpowiedzi typów?

::: incremental

  1. “type hints should be used whenever unit tests are worth writing”, cytat z cennego blog posta
  2. poprawiają czytelność kodu
  3. dokumentują kod (dla deweloperów i IDE)
  4. może być używane dla statycznego sprawdzenie typów

:::

Czym jest statyczne sprawdzanie typów?

When (most) functions (and variables) are annotated with type(s) one can check, without running a program, the compatibility. In static languages the correctness of types is checked during compilation (Java, C++, Haskell, C#). But this is not the case in Python. We just run the code and hope for the best. This gives flexibility but can also raise some runtime issues.

However, using hints we can statically check types compatibility before actually running code. The tool for that is called mypy.

Modyfikacja requirments(in)

requirements.txt

mypy-extensions==0.4.3
mypy==0.931
typing-extensions==3.10.0.2

Integracja z CI/CD

jobs:
  build:
    runs-on: ubuntu-latest
    name: Mypy
    steps:
    - uses: actions/checkout@v1
    - name: Set up Python 3.8
      uses: actions/setup-python@v1
      with:
        python-version: 3.8
    - name: Install Dependencies
      run: |
        pip install mypy
    - name: mypy
      run: |
        mypy src/

Możliwe problemy

Dostaję błąd “stubs are missing” dla poszczególnych bibliotek

Nie wszystkie biblioteki mają wbudowane sugerowane type. Mamy dwie opcje:

  1. Znaleźć bibliotekę, która dodaje typy do stubsów (np. dla pandas https://github.com/VirtusLab/pandas-stubs)
  2. Poinstruuować mypy żeby ignorować podpowiedzi dla danej biblioteki
import pandas as pd  # type: ignore

Więcej informacji tutaj

Możliwe problemy

Funkcja korzysta z argumentu/zwraca słownik z różnymi typami

Są dwa rozwiązania:

  • możemy być bardzo liberalni Dict[str, Optional[str, float]]
  • albo bardzo zachowawczy definiując klasę, w której konkretnie podamy jakie są klucze i jakiego typu mają one wartości

Na dłuższą metę drugie rozwiązanie jest lepsze, wyklucza możliwość modyfikacji, które mogłyby zepsuć kod zależący od naszej funkcji.

Więcej na tematy mypy i typowania w Pythonie