Skip to content

A story: Getting started with mypy on a large existing codebase #2096

Closed
@davidfstr

Description

@davidfstr

This evening I decided to try out mypy on a large existing Django codebase. Hundreds of .py files.

Surprisingly, I found no actual tutorial on the documentation on how to use mypy on a large existing project as opposed to single file. Therefore I will enumerate a number of issues that I have encountered so far. Perhaps such an enumeration will be useful in writing new documentation, fixing issues, or other improvements.

  • No documented way to run mypy on anything except single files.

I tried invoking mypy on a directory rather than a single .py file. This appears to work, however the documentation does not appear to mention this usage as a possiblity.

  • error: Cannot find module named 'FOO.BAR.BAZ'

I receive the following error when there certainly exists a file ./FOO/BAR/BAZ.py. Therefore this error makes no sense to me. I invoked mypy with MYPYPATH=. mypy ..

  • error: Need type annotation for variable

Why? This points to a line that looks like dependencies = []. Error message should be improved to indicate why it is demanding a type annotation.

  • error: Method must have at least one argument

Well done. This was flagging a number of unittest methods marked with @skip that took no arguments. Such as the following:

class BeaconBasicTests(SimpleTestCase):
    @skip('not yet automated')
    def test_given_beacons_exist_when_page_reloaded_then_beacons_still_exist():
        pass

It was expecting (self) as the signature, which seems reasonable.

  • error: Result type of + incompatible in assignment

Appears to be a mypy bug. Was complaining about the following construction:

INSTALLED_APPS = (
    'django.contrib.admin',
    ...
)
if USE_DEBUG_TOOLBAR:
    INSTALLED_APPS += ('debug_toolbar',)  # error here
  • error: Value of type "object" is not indexable

Appears to be a mypy bug. Was complaining about the following construction:

LESSON_OBJECT_TYPES = {
    'warm_up': dict(
        title='Warm Up',
        ...=...,
    ),
    ...
)
x = LESSON_OBJECT_TYPES['teacher_coding_exercise']['expected_file_types']  # error here
  • error: Callable[[Any, Any, Any], Any] has no attribute "short_description"

Appears to be a mypy bug. Was complaining about the following construction:

def upload_deck(modeladmin, request, queryset):
    ...

upload_deck.short_description = 'Upload slides to selected deck'  # error here

It is legal (albeit advanced) to annotate a function object (including a lambda) with additional attributes.

  • error: Name 'Foo' already defined

Common to receive this kind of error when using star-imports. For example:

=== A.py
from B import *
import C

=== B.py
import C

In the above scenario mypy will complain that C is already defined in A.

Recommend altering there to be an error only if Foo is defined more than once and is defined to be something different.

That's all folks. I suppose I'll wait to add my own type annotations until mypy gives my current unannotated code a clean bill of health.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions