Skip to content

Strange name substitution on upgrading to >= 0.900 from 0.812 #10661

Closed
@choogeboom

Description

@choogeboom

Bug Report

I want to apologize in advance for the somewhat vague nature of this bug report. I've tried for hours in order to create a reproducible example, and have failed. Unfortunately, the bug occurs in some proprietary code, so I can't release it to you all to look at.

I went to upgrade my project to use mypy 0.902 and after fixing all the expected errors related to third party stub libraries, I am left with the following two errors:

buyfair/model/Warehouse.py:312: error: Invalid index type "buyfair.model.Warehouse.Warehouse" for "Dict[Warehouse, WarehouseProduct]"; expected type "buyfair.model.warehouse.Warehouse"
buyfair/model/Product.py:222: error: Argument 1 to "obeys_maximums" of "WarehouseSource" has incompatible type "Dict[buyfair.model.Product.Product, buyfair.model.Product.Unit]"; expected "Dict[buyfair.model.product.Product, buyfair.model.product.Unit]"

These errors are really strange, because there isn't any class called buyfair.model.Warehouse.Warehouse or buyfair.model.Product.Product. I shrugged my shoulders and added # type: ignore to each of these, and tried to run mypy again only to receive the following errors:

buyfair/model/warehouse.py:312: error: unused "type: ignore" comment
buyfair/model/product.py:222: error: unused "type: ignore" comment

I've set warn_unused_ignores=False and will move on, but figured this is at least worth reporting.

To Reproduce

Like I said above, I tried to reproduce this error in a smaller more self-contained example for a few hours, but wasn't successful. I'll try to give more details around the context in the error messages above:

buyfair/model/warehouse.py

from typing import Dict, AbstractSet, TYPE_CHECKING

if TYPE_CHECKING:
    from buyfair.model.product import Product, Unit

class Warehouse:
    warehouse_sources: Dict["Source", "WarehouseSource"]

class WarehouseProduct:
    some_bool_value: bool

class WarehouseGroup(AbstractSet[Warehouse]):

    def some_bool_value(self, product: "Product") -> bool:
        return any(product.warehouse_products[warehouse].some_bool_value for warehouse in self)  # <-- problematic line


class WarehouseSource:
    def obeys_maximums(self, products: Dict["Product", "Unit"]) -> bool:
        ...

buyfair/model/product.py

from typing import Dict, NewType, TYPE_CHECKING

if TYPE_CHECKING:
    from buyfair.model.warehouse import Warehouse, WarehouseProduct, WarehouseSource

Unit = NewType("Unit", int)

class Product:
    warehouse_products: "Dict[Warehouse, WarehouseProduct]"
    
    def some_other_bool_value(warehouse: "Warehouse") -> bool:
       warehouse_source:  "WarehouseSource" = ...
        products = {self: Unit(0)}
        if warehouse_source.obeys_maximums(products):  # <-- Other problematic line
            ...

In both these cases, mypy is replacing the module name with the class name.

buyfair.model.product.Product becomes buyfair.model.Product.Product and buyfair.model.warehouse.Warehouse becomes buyfair.model.Warehouse.Warehouse

Expected Behavior

In both these cases, the types work out just fine, and mypy should recognize the types just fine.

Actual Behavior

mypy fails to recognize the types correctly and creates a new made up type.

(Write what happened.)

Your Environment

  • Mypy version used: 0.900, 0.901, 0.902
  • Mypy command-line flags:
  • Mypy configuration options from mypy.ini (and other config files):
    python_version=3.6
    warn_unused_ignores=False
    check_untyped_defs=True
    strict_optional=False
    
  • Python version used: 3.6
  • Operating system and version: Centos 7.5 (running inside docker)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions