Search code examples
pythonpython-typingmypy

Python mypy incompatible types


So, I have some code that looks like this:

def get_tree(args):
    sensor_ids = argToList(args.get("sensor_ids"))
    process_ids = argToList(args.get("process_ids"))

    all_results = {}

    for sensor_id in sensor_ids:
        sensor_id_str = str(sensor_id)
        for process_id in process_ids:
            process_id_str = str(process_id)
            main_process = query_process(sensor_id_str, process_id_str)

            results = {}
            json_response = main_process.json()

            for vertex in json_response["resources"]:
                if vertex["vertex_type"] == "process":
                    results["main_process"] = {"sensor_id": sensor_id_str,
                                               "process_id": process_id_str,
                                               "properties": vertex["properties"]}

                    for edge in vertex["edges"]:
                        if edge == "child_process":
                            results["child_processes"] = []

MyPy is creating this error and I'm not sure how to fix, flake is quite happy:

Incompatible types in assignment (expression has type "List[]", target has type "Dict[str, Any]") [assignment] results["child_processes"] = [] ^


Solution

  • For that the original code, mypy (tested with 0.950 and 0.961) should be telling you that

    Need type annotation for "results" (hint: "results: Dict[<type>, <type>] = ...")

    so it can figure out whether you're doing the right thing.

    With the augmented code, if you call reveal_type(results), you'll see

    a.py:27: note: Revealed type is "builtins.dict[builtins.str, builtins.dict[builtins.str, Any]]"
    

    i.e. based on the first assignment you do to results, mypy has inferred that you have a dict of dicts, and as such, putting a list up in there just ain't gonna fly.

    So, if you want to annotate results to be a basic "bag" with string keys and arbitrary values,

    results: Dict[str, Any] = {}
    

    or if you want more strict typing, use TypedDict:

    class Results(TypedDict):
        child_processes: Optional[List[Any]]  # or be more specific...
    
    results: Results = {}