Skip to content

Loosen __pow__ overloads a bit #7682

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

tusharsadhwani
Copy link
Contributor

@tusharsadhwani tusharsadhwani commented Apr 25, 2022

This is done to alleviate this false positive:

$ cat a.py              

def foo(x: float, y: float) -> float:
    return x ** y

$ mypy --strict a.py
a.py:2: error: Returning Any from function declared to return "float"
Found 1 error in 1 file (checked 1 source file)

This change is akin to this change in the re module.

Related: mypy#7765

@github-actions
Copy link
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

zulip (https://github.com/zulip/zulip)
+ analytics/lib/fixtures.py:73: error: Argument 1 to "int" has incompatible type "Union[complex, Any]"; expected "Union[str, bytes, array[Any], mmap, _CData, SupportsInt, SupportsIndex, SupportsTrunc]"  [arg-type]
+ analytics/lib/fixtures.py:73: error: Argument 1 to "sqrt" has incompatible type "Union[complex, Any]"; expected "Union[SupportsFloat, SupportsIndex]"  [arg-type]

rich (https://github.com/willmcgugan/rich)
+ rich/filesize.py:50: error: Incompatible return value type (got "Tuple[Union[float, Any], str]", expected "Tuple[int, str]")  [return-value]

kornia (https://github.com/kornia/kornia)
+ kornia/geometry/transform/pyramid.py:205: error: Argument 1 to "sqrt" has incompatible type "Union[complex, Any]"; expected "Union[SupportsFloat, SupportsIndex]"  [arg-type]

vision (https://github.com/pytorch/vision)
+ torchvision/models/detection/backbone_utils.py:147: error: Argument 3 to "BackboneWithFPN" has incompatible type "List[Union[float, Any]]"; expected "List[int]"  [arg-type]

freqtrade (https://github.com/freqtrade/freqtrade)
+ freqtrade/data/btanalysis.py:566: error: Incompatible return value type (got "Union[complex, Any]", expected "float")
+ freqtrade/templates/sample_hyperopt_loss.py:47: error: Argument 1 to "exp" has incompatible type "Union[complex, Any]"; expected "Union[SupportsFloat, SupportsIndex]"
+ freqtrade/optimize/hyperopt_loss_short_trade_dur.py:48: error: Argument 1 to "exp" has incompatible type "Union[complex, Any]"; expected "Union[SupportsFloat, SupportsIndex]"

pandas (https://github.com/pandas-dev/pandas)
+ pandas/io/stata.py:2976: error: Incompatible return value type (got "Union[float, Any]", expected "int")  [return-value]

prefect (https://github.com/PrefectHQ/prefect)
+ src/prefect/utilities/datetimes.py:51: error: Incompatible return value type (got "Union[timedelta, Any, float]", expected "timedelta")
+ src/prefect/utilities/datetimes.py:51: error: Unsupported operand types for * ("None" and "float")
+ src/prefect/utilities/datetimes.py:51: note: Both left and right operands are unions

rotki (https://github.com/rotki/rotki)
+ rotkehlchen/chain/ethereum/defi/price.py:107: error: Unsupported operand types for / ("FVal" and "float")
+ rotkehlchen/chain/ethereum/defi/price.py:107: note: Right operand is of type "Union[float, Any]"
+ rotkehlchen/chain/ethereum/defi/price.py:134: error: Unsupported operand types for / ("FVal" and "float")
+ rotkehlchen/chain/ethereum/defi/price.py:134: note: Right operand is of type "Union[float, Any]"
+ rotkehlchen/chain/ethereum/defi/price.py:146: error: Unsupported operand types for / ("FVal" and "float")
+ rotkehlchen/chain/ethereum/defi/price.py:146: note: Right operand is of type "Union[float, Any]"
+ rotkehlchen/chain/ethereum/defi/price.py:161: error: Unsupported operand types for / ("FVal" and "float")
+ rotkehlchen/chain/ethereum/defi/price.py:161: note: Right operand is of type "Union[float, Any]"
+ rotkehlchen/inquirer.py:626: error: Unsupported operand types for / ("FVal" and "float")
+ rotkehlchen/inquirer.py:626: note: Right operand is of type "Union[float, Any]"
+ rotkehlchen/chain/ethereum/modules/makerdao/vaults.py:316: error: Unsupported operand types for / ("FVal" and "float")
+ rotkehlchen/chain/ethereum/modules/makerdao/vaults.py:316: note: Right operand is of type "Union[float, Any]"
+ rotkehlchen/chain/ethereum/modules/makerdao/dsr.py:206: error: Unsupported operand types for * ("None" and "float")
+ rotkehlchen/chain/ethereum/modules/makerdao/dsr.py:206: note: Both left and right operands are unions
+ rotkehlchen/chain/ethereum/modules/makerdao/dsr.py:206: error: Incompatible return value type (got "Union[float, Any]", expected "Optional[int]")
+ rotkehlchen/chain/ethereum/modules/aave/graph.py:940: error: Unsupported operand types for / ("FVal" and "float")
+ rotkehlchen/chain/ethereum/modules/aave/graph.py:940: note: Right operand is of type "Union[float, Any]"
+ rotkehlchen/chain/ethereum/modules/yearn/vaultsv2.py:137: error: Unsupported operand types for * ("None" and "float")
+ rotkehlchen/chain/ethereum/modules/yearn/vaultsv2.py:137: note: Both left and right operands are unions
- rotkehlchen/api/v1/resources.py:1695: error: Untyped decorator makes function "get" untyped
- rotkehlchen/api/v1/resources.py:1715: error: Untyped decorator makes function "get" untyped
- rotkehlchen/api/v1/resources.py:1724: error: Untyped decorator makes function "get" untyped
- rotkehlchen/api/v1/resources.py:1733: error: Untyped decorator makes function "get" untyped
- rotkehlchen/api/v1/resources.py:1742: error: Untyped decorator makes function "get" untyped
- rotkehlchen/api/v1/resources.py:1762: error: Untyped decorator makes function "get" untyped
- rotkehlchen/api/v1/resources.py:1787: error: Untyped decorator makes function "put" untyped
- rotkehlchen/api/v1/resources.py:1791: error: Untyped decorator makes function "patch" untyped
- rotkehlchen/api/v1/resources.py:1795: error: Untyped decorator makes function "delete" untyped
- rotkehlchen/api/v1/resources.py:1805: error: Untyped decorator makes function "get" untyped
- rotkehlchen/api/v1/resources.py:1816: error: Untyped decorator makes function "put" untyped
- rotkehlchen/api/v1/resources.py:1820: error: Untyped decorator makes function "post" untyped
- rotkehlchen/api/v1/resources.py:1840: error: Untyped decorator makes function "put" untyped
- rotkehlchen/api/v1/resources.py:1853: error: Untyped decorator makes function "post" untyped
- rotkehlchen/api/v1/resources.py:1868: error: Untyped decorator makes function "delete" untyped
- rotkehlchen/api/v1/resources.py:1881: error: Untyped decorator makes function "post" untyped
- rotkehlchen/api/v1/resources.py:1894: error: Untyped decorator makes function "put" untyped
- rotkehlchen/api/v1/resources.py:1909: error: Untyped decorator makes function "patch" untyped
- rotkehlchen/api/v1/resources.py:1924: error: Untyped decorator makes function "get" untyped
- rotkehlchen/api/v1/resources.py:1928: error: Untyped decorator makes function "delete" untyped
- rotkehlchen/api/v1/resources.py:1944: error: Untyped decorator makes function "get" untyped
- rotkehlchen/api/v1/resources.py:1948: note: (Skipping most remaining errors due to unresolved imports or missing stubs; fix these first)
+ rotkehlchen/api/v1/resources.py:1695: note: (Skipping most remaining errors due to unresolved imports or missing stubs; fix these first)

core (https://github.com/home-assistant/core)
+ homeassistant/components/tuya/base.py:44: error: Incompatible return value type (got "Union[complex, Any]", expected "float")  [return-value]
+ homeassistant/components/tuya/base.py:48: error: Incompatible return value type (got "Union[complex, Any]", expected "float")  [return-value]
+ homeassistant/components/tuya/base.py:52: error: Argument 1 to "int" has incompatible type "Union[complex, Any]"; expected "Union[str, bytes, array[Any], mmap, _CData, SupportsInt, SupportsIndex, SupportsTrunc]"  [arg-type]
+ homeassistant/components/isy994/helpers.py:431: error: Redundant cast to "float"  [redundant-cast]

mypy (https://github.com/python/mypy)
+ mypyc/irbuild/constant_fold.py:82: error: Incompatible return value type (got "Union[float, Any]", expected "Optional[int]")  [return-value]

sympy (https://github.com/sympy/sympy)
+ sympy/core/evalf.py:300: error: Incompatible types in assignment (expression has type "Union[float, Any]", variable has type "int")
+ sympy/core/evalf.py:623: error: Incompatible types in assignment (expression has type "Union[float, Any]", variable has type "int")
+ sympy/core/evalf.py:1199: error: Incompatible types in assignment (expression has type "Union[float, Any]", variable has type "int")
+ sympy/core/evalf.py:1357: error: Incompatible types in assignment (expression has type "Union[float, Any]", variable has type "Symbol")

paasta (https://github.com/yelp/paasta)
+ paasta_tools/utils.py:3630: error: Incompatible return value type (got "Union[float, Any]", expected "int")

@AlexWaygood
Copy link
Member

It looks like when mypy sees this signature:

class int:
    def __pow__(self, __x: int, __modulo: None = ...) -> int | float | Any: ...

It automatically "simplifies" the signature to:

class int:
    def __pow__(self, __x: int, __modulo: None = ...) -> float | Any: ...

This is because of the fact that int is an implicit subtype of float (according to PEP 484), and therefore int in the int | float union is redundant.

This then leads to the rich hit from the mypy_primer output. The source code's here); here's the function that causes mypy to emit the error:

def pick_unit_and_suffix(size: int, suffixes: List[str], base: int) -> Tuple[int, str]:
    """Pick a suffix and base for the given size."""
    for i, suffix in enumerate(suffixes):
        unit = base**i
        if size < unit * base:
            break
    return unit, suffix

Will is pretty sure that unit is an int (I'm guessing he knows the two numbers being pow'd together will always be positive). But mypy sees two ints being pow'd together, and so it's pretty sure that this will create float | Any, because that's what the int.__pow__ signature says. This therefore leads it to produce the somewhat baffling error message that unit is of type float | Any, when Will is annotating it with int.

I'm not sure there's a way of doing this without creating this kind of false-positive error, sadly ☹️

@srittau
Copy link
Collaborator

srittau commented Apr 25, 2022

As @AlexWaygood points out, I don't think we can improve the types any further at this point. Ideally, there'd be a way to define int ranges, or at least types for positive and non-negative integers, which would allow use to narrow the definitions. Thank you for the PR though, which allowed us to judge the impact of such a change!

@srittau srittau closed this Apr 25, 2022
@tusharsadhwani tusharsadhwani deleted the patch-1 branch April 26, 2022 17:39
@Akuli
Copy link
Collaborator

Akuli commented Apr 26, 2022

I wonder if we could return int | Any.

@AlexWaygood
Copy link
Member

I wonder if we could return int | Any.

Yeah, might be worth a shot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants