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