-
Notifications
You must be signed in to change notification settings - Fork 288
Too many false positives - what's the use? #1861
-
Hey! I am heavily using typing annotations in my code and trying to get help with mypy to ensure I don't miss anything, but after running it on my code I find it gives me so many false positives that it's useless to me. It requires me to be overly verbose just to please it, and most of the things it points out aren't problems to me.
Here are some examples:
mypy . --explicit-package-bases
utils/byte_utils.py:44: error: Returning Any from function declared to return "float" [no-any-return]
byte_utils
class DataUnit(ABC):
value: float
@property
@abstractmethod
def base(self) -> int:
pass
@property
@abstractmethod
def steps(self) -> int:
"""
The amount of steps to convert to bytes.
"""
pass
code:44 def to_bytes(self) -> float:
return self.value * (self.base ** self.steps)
It's obvious this is a float being returned - isn't it?
Then:
utils/cost_utils.py:29: error: Item "int" of "Union[int, float, PriceRepresentation]" has no attribute "value" [union-attr]
utils/cost_utils.py:29: error: Item "float" of "Union[int, float, PriceRepresentation]" has no attribute "value" [union-attr]
def __init__(self, dollar_price: typing.Union[typing.Union[int, float], PriceRepresentation], time_unit: TimeUnit):
if not isinstance(dollar_price, int) and not isinstance(dollar_price, float) and not isinstance(dollar_price, PriceRepresentation):
raise ValueError(f"dollar_price must be an int, float or PriceRepresentation, got {type(dollar_price)}")
self.dollar_price: float = float(dollar_price) if (
isinstance(dollar_price, float) or isinstance(dollar_price, int)
) else dollar_price.value
self.time_unit: TimeUnit = time_unit
self._per_second_cost = self.dollar_price / self.time_unit.to_seconds()
^ this is a bit dirty by me - having to check instances and convert, but still - I handle it properly and i'll never call .value on a non-PriceRepresentation class
then:
deployers/instance_deployer.py:66: error: "list[InstanceDeployment]" has no attribute "is_empty" [attr-defined]
options: List[InstanceDeployment] = _collect_minimum_number_of_instances_satisfying_constraints(
min_num_disks=minimum_applicable_disk_deployment.num_volumes,
min_cpus=required_cpus, vms=vms_to_choose_from)
options: InstanceDeploymentOptions = InstanceDeploymentOptions(
deployment_matching_constraints=deployment_matching_constraints,
cheaper_options=cheaper_deployment_options
)
if options.is_empty():
raise DeploymentSolutionNotFound("No deployment options were found.")
It doesn't seem to support changing variable types?
Then
deployers/disk_deployer.py:51: error: Argument "capacity" to "VirtualVolume" has incompatible type "DataUnit"; expected "Gigabyte" [arg-type]
gb_space_per_disk = Terabyte(total_tb_to_persist.value / num_disks).convert_to(Gigabyte)
volume = VirtualVolume(
capacity=gb_space_per_disk,
type=volume_type
)
when the constructor accepts a GB precisely:
class VirtualVolume:
def __init__(self, capacity: Gigabyte, type: VirtualVolumeType):
for some reason, it can't figure out that Gigabyte inherits DataUnit
Can you please tell me if my code is wrong, or I'm using mypy wrong, or my expectations aren't in order? At this point, I really don't see a way I can use mypy in a way that's useful to me
Beta Was this translation helpful? Give feedback.
All reactions
Replies: 1 comment
-
It's obvious this is a float being returned - isn't it?
The Any is because we define int ** int as returning Any in some cases, because it may return a float (if there are negative numbers involved). The option you are using here (--warn-return-any) is quite strict and I wouldn't recommend turning it on if you're just getting started with typing.
^ this is a bit dirty by me - having to check instances and convert, but still - I handle it properly and i'll never call .value on a non-PriceRepresentation class
I tried something resembling your snippet in mypy-playground and couldn't reproduce this error: https://mypy-play.net/?mypy=latest&python=3.12&flags=strict&gist=8c91ef07f1b622146546b04ea36dc4a4 . If you can provide a self-contained piece of code exhibiting this error, please report a bug to mypy.
It doesn't seem to support changing variable types?
You can turn on the --allow-redefinition flag and this code should be accepted.
for some reason, it can't figure out that Gigabyte inherits DataUnit
As far as the type checker sees, you are passing an instance of the parent class when only the child class is accepted. The constructor requires an object of type Gigabyte, but the value is of type DataUnit.
Possibly the convert_to() method needs to have a generic return type, so that if you pass Gigabyte it returns Gigabyte.
Beta Was this translation helpful? Give feedback.