Skip to content

Infer type of class variables from base classes #12022

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 1 commit into from

Conversation

Timmmm
Copy link

@Timmmm Timmmm commented Jan 19, 2022

This sets the type of class variables to their types from the superclass (if not set). It unfortunately makes some error messages a bit worse, but I think fixing that properly requires adding a "where did this type come from? inferred/type annotation/type comment/etc." field to Type, and that would be a much bigger change.

I also had to delete some suspicious special case code that treated actual type annotations and # type: comments differently for None.

Note this does not pass all tests. I started modifying them so they would pass, so you can see the effect this has on the output. However it changes quite a lot so I thought it would make more sense to check this is along the right lines before finishing.

Description

Attempt to fix #10375

Test Plan

Simple tests added in check-classes.test

This sets the type of class variables to their types from the superclass (if not set). It unfortunately makes some error messages a bit worse, but I think fixing that properly requires adding a "where did this type come from? inferred/type annotation/type comment/etc." field to `Type`, and that would be a much bigger change.

I also had to delete some suspicious special case code that treated actual type annotations and `# type: ` comments differently for `None`.
@github-actions
Copy link
Contributor

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

alectryon (https://github.com/cpitclaudel/alectryon)
- alectryon/docutils.py:1242: error: Incompatible types in assignment (expression has type "Tuple[str]", base class "RSTLiterateParser" defined the type as "Tuple[]")
+ alectryon/docutils.py:1242: error: Incompatible types in assignment (expression has type "Tuple[str]", variable has type "Tuple[]")
- alectryon/docutils.py:1246: error: Incompatible types in assignment (expression has type "Tuple[str]", base class "RSTLiterateParser" defined the type as "Tuple[]")
+ alectryon/docutils.py:1246: error: Incompatible types in assignment (expression has type "Tuple[str]", variable has type "Tuple[]")

stone (https://github.com/dropbox/stone)
+ stone/backend.py:95: error: Incompatible types in assignment (expression has type "None", variable has type "ArgumentParser")

arviz (https://github.com/arviz-devs/arviz)
+ arviz/data/io_pyro.py:23: error: Incompatible types in assignment (expression has type "None", variable has type "int")
+ arviz/data/io_pyro.py:24: error: Incompatible types in assignment (expression has type "None", variable has type "int")
+ arviz/data/io_pymc3_3x.py:55: error: Incompatible types in assignment (expression has type "None", variable has type "int")
+ arviz/data/io_pymc3_3x.py:56: error: Incompatible types in assignment (expression has type "None", variable has type "int")
+ arviz/data/io_numpyro.py:21: error: Incompatible types in assignment (expression has type "None", variable has type "int")
+ arviz/data/io_numpyro.py:22: error: Incompatible types in assignment (expression has type "None", variable has type "int")

schema_salad (https://github.com/common-workflow-language/schema_salad)
+ schema_salad/tests/test_schemas_directive.py: note: In class "TestSchemasDirective":
+ schema_salad/tests/test_schemas_directive.py:22:23: error: Incompatible types in assignment (expression has type "None", variable has type "Loader")  [assignment]
+ schema_salad/tests/test_schemas_directive.py:23:18: error: Incompatible types in assignment (expression has type "None", variable has type "Union[Names, SchemaParseException]")  [assignment]
+ schema_salad/tests/test_schemas_directive.py:24:23: error: Incompatible types in assignment (expression has type "None", variable has type "Dict[str, Any]")  [assignment]
+ schema_salad/tests/test_schemas_directive.py:25:25: error: Incompatible types in assignment (expression has type "None", variable has type "Loader")  [assignment]
+ schema_salad/tests/test_real_cwl.py: note: In class "TestRealWorldCWL":
+ schema_salad/tests/test_real_cwl.py:23:23: error: Incompatible types in assignment (expression has type "None", variable has type "Loader")  [assignment]
+ schema_salad/tests/test_real_cwl.py:24:18: error: Incompatible types in assignment (expression has type "None", variable has type "Union[Names, SchemaParseException]")  [assignment]
+ schema_salad/tests/test_real_cwl.py:25:23: error: Incompatible types in assignment (expression has type "None", variable has type "Dict[str, Any]")  [assignment]
+ schema_salad/tests/test_real_cwl.py:26:25: error: Incompatible types in assignment (expression has type "None", variable has type "Loader")  [assignment]

dulwich (https://github.com/dulwich/dulwich)
+ dulwich/objects.py:265: error: Incompatible types in assignment (expression has type "None", variable has type "bytes")
+ dulwich/objects.py:266: error: Incompatible types in assignment (expression has type "None", variable has type "int")

sympy (https://github.com/sympy/sympy)
+ sympy/core/operations.py:44: error: Incompatible types in assignment (expression has type "None", variable has type "Type[Basic]")
+ sympy/printing/printer.py:249: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ sympy/codegen/ast.py:510: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ sympy/codegen/fnodes.py:616: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ sympy/codegen/fnodes.py:617: error: Incompatible types in assignment (expression has type "None", variable has type "int")
+ sympy/polys/domains/integerring.py:38: error: "None" not callable
+ sympy/polys/domains/integerring.py:39: error: "None" not callable
+ sympy/polys/domains/rationalfield.py:41: error: "None" not callable
+ sympy/polys/domains/rationalfield.py:42: error: "None" not callable
+ sympy/polys/domains/gmpyintegerring.py:22: error: "None" not callable
+ sympy/polys/domains/gmpyintegerring.py:23: error: "None" not callable
+ sympy/polys/domains/pythonrationalfield.py:18: error: "None" not callable
+ sympy/polys/domains/pythonrationalfield.py:19: error: "None" not callable
+ sympy/polys/domains/gmpyrationalfield.py:21: error: "None" not callable
+ sympy/polys/domains/gmpyrationalfield.py:22: error: "None" not callable
+ sympy/polys/domains/gaussiandomains.py:16: error: Incompatible types in assignment (expression has type "None", variable has type "Domain")
+ sympy/polys/domains/gaussiandomains.py:17: error: Incompatible types in assignment (expression has type "None", variable has type "Domain")
+ sympy/polys/domains/gaussiandomains.py:246: error: Incompatible types in assignment (expression has type "None", variable has type "Domain")
+ sympy/solvers/ode/single.py:86: error: Incompatible types in assignment (expression has type "None", variable has type "Expr")
+ sympy/solvers/ode/single.py:87: error: Incompatible types in assignment (expression has type "None", variable has type "AppliedUndef")
+ sympy/solvers/ode/single.py:88: error: Incompatible types in assignment (expression has type "None", variable has type "Symbol")
+ sympy/solvers/ode/single.py:89: error: Incompatible types in assignment (expression has type "None", variable has type "int")
+ sympy/solvers/ode/single.py:90: error: Incompatible types in assignment (expression has type "None", variable has type "Expr")
+ sympy/solvers/ode/single.py:91: error: Incompatible types in assignment (expression has type "None", variable has type "Expr")
+ sympy/solvers/ode/single.py:264: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ sympy/solvers/ode/single.py:268: error: Incompatible types in assignment (expression has type "None", variable has type "bool")
+ sympy/solvers/ode/single.py:271: error: Incompatible types in assignment (expression has type "None", variable has type "SingleODEProblem")
+ sympy/matrices/common.py:60: error: Incompatible types in assignment (expression has type "None", variable has type "int")
+ sympy/matrices/common.py:61: error: Incompatible types in assignment (expression has type "None", variable has type "int")
+ sympy/solvers/diophantine/diophantine.py:161: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ sympy/vector/dyadic.py:26: error: Incompatible types in assignment (expression has type "None", variable has type "Type[Dyadic]")
+ sympy/vector/dyadic.py:27: error: Incompatible types in assignment (expression has type "None", variable has type "Type[Dyadic]")
+ sympy/vector/dyadic.py:28: error: Incompatible types in assignment (expression has type "None", variable has type "Type[Dyadic]")
+ sympy/vector/dyadic.py:29: error: Incompatible types in assignment (expression has type "None", variable has type "Type[Dyadic]")
+ sympy/vector/dyadic.py:30: error: Incompatible types in assignment (expression has type "None", variable has type "Type[Dyadic]")
+ sympy/vector/dyadic.py:31: error: Incompatible types in assignment (expression has type "None", variable has type "DyadicZero")
+ sympy/vector/vector.py:28: error: Incompatible types in assignment (expression has type "None", variable has type "Type[Vector]")
+ sympy/vector/vector.py:29: error: Incompatible types in assignment (expression has type "None", variable has type "Type[Vector]")
+ sympy/vector/vector.py:30: error: Incompatible types in assignment (expression has type "None", variable has type "Type[Vector]")
+ sympy/vector/vector.py:31: error: Incompatible types in assignment (expression has type "None", variable has type "Type[Vector]")
+ sympy/vector/vector.py:32: error: Incompatible types in assignment (expression has type "None", variable has type "Type[Vector]")
+ sympy/vector/vector.py:33: error: Incompatible types in assignment (expression has type "None", variable has type "VectorZero")
+ sympy/tensor/tensor.py:2701: error: Incompatible types in assignment (expression has type "None", variable has type "_IndexStructure")
+ sympy/tensor/tensor.py:3167: error: Incompatible types in assignment (expression has type "None", variable has type "_IndexStructure")
+ sympy/stats/rv.py:195: error: Incompatible types in assignment (expression has type "None", variable has type "bool")
+ sympy/stats/rv.py:196: error: Incompatible types in assignment (expression has type "None", variable has type "bool")
+ sympy/stats/rv.py:197: error: Incompatible types in assignment (expression has type "None", variable has type "bool")
+ sympy/stats/rv.py:198: error: Incompatible types in assignment (expression has type "None", variable has type "bool")
+ sympy/utilities/_compilation/runners.py:53: error: Incompatible types in assignment (expression has type "None", variable has type "Dict[str, str]")
+ sympy/utilities/_compilation/runners.py:57: error: Incompatible types in assignment (expression has type "None", variable has type "Tuple[Optional[str], ...]")
+ sympy/utilities/_compilation/runners.py:60: error: Incompatible types in assignment (expression has type "None", variable has type "Dict[str, Callable[[Optional[str]], str]]")
+ sympy/utilities/_compilation/runners.py:63: error: Incompatible types in assignment (expression has type "None", variable has type "Dict[str, str]")

edgedb (https://github.com/edgedb/edgedb)
+ edb/schema/indexes.py:397:16: error: Unexpected keyword argument "expr" for "ObjectDDL"

urllib3 (https://github.com/urllib3/urllib3)
+ src/urllib3/connectionpool.py:1036: error: Unexpected keyword argument "cert_file" for "HTTPConnection"  [call-arg]
+ src/urllib3/connection.py:129: note: "HTTPConnection" defined here
+ src/urllib3/connectionpool.py:1036: error: Unexpected keyword argument "key_file" for "HTTPConnection"  [call-arg]
+ src/urllib3/connection.py:129: note: "HTTPConnection" defined here
+ src/urllib3/connectionpool.py:1036: error: Unexpected keyword argument "key_password" for "HTTPConnection"  [call-arg]
+ src/urllib3/connection.py:129: note: "HTTPConnection" defined here
+ src/urllib3/connectionpool.py:1046: error: Argument 1 to "_prepare_conn" of "HTTPSConnectionPool" has incompatible type "HTTPConnection"; expected "HTTPSConnection"  [arg-type]

steam.py (https://github.com/Gobot1234/steam.py)
- steam/trade.py:250: error: Incompatible types in assignment (expression has type "Tuple[str, str, str, str, str, str, str]", base class "Asset" defined the type as "Tuple[str, str, str, str, str, str]")  [assignment]
+ steam/trade.py:250: error: Incompatible types in assignment (expression has type "Tuple[str, str, str, str, str, str, str]", variable has type "Tuple[str, str, str, str, str, str]")  [assignment]

cwltool (https://github.com/common-workflow-language/cwltool)
+ cwltool/argparser.py: note: In class "FSAction":
+ cwltool/argparser.py:716:16: error: Incompatible types in assignment (expression has type "None", variable has type "str")  [assignment]
+ cwltool/argparser.py: note: In class "FSAppendAction":
+ cwltool/argparser.py:744:16: error: Incompatible types in assignment (expression has type "None", variable has type "str")  [assignment]

tornado (https://github.com/tornadoweb/tornado)
+ tornado/util.py:261: error: Incompatible types in assignment (expression has type "None", variable has type "Dict[str, Any]")
+ tornado/httputil.py:340: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ tornado/httputil.py:341: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ tornado/httputil.py:344: error: Incompatible types in assignment (expression has type "None", variable has type "Future[None]")
+ tornado/netutil.py:490: error: Incompatible types in assignment (expression has type "None", variable has type "int")
+ tornado/iostream.py:1357: error: Incompatible types in assignment (expression has type "None", variable has type "SSLSocket")
+ tornado/httpclient.py:179: error: Incompatible types in assignment (expression has type "None", variable has type "Dict[IOLoop, AsyncHTTPClient]")
+ tornado/httpclient.py:342: error: Incompatible types in assignment (expression has type "None", variable has type "Union[Dict[str, str], HTTPHeaders]")
+ tornado/httpclient.py:627: error: Incompatible types in assignment (expression has type "None", variable has type "HTTPRequest")
+ tornado/web.py:199: error: Incompatible types in assignment (expression has type "None", variable has type "List[OutputTransform]")
+ tornado/web.py:200: error: Incompatible types in assignment (expression has type "None", variable has type "List[str]")
+ tornado/web.py:201: error: Incompatible types in assignment (expression has type "None", variable has type "Dict[str, str]")
+ tornado/websocket.py:809: error: Incompatible types in assignment (expression has type "None", variable has type "IOStream")
+ tornado/websocket.py:1354: error: Incompatible types in assignment (expression has type "None", variable has type "WebSocketProtocol")
+ tornado/test/web_test.py:222: error: Incompatible types in assignment (expression has type "None", variable has type "Future[Any]")
+ tornado/test/concurrent_test.py:102: error: Incompatible types in assignment (expression has type "None", variable has type "Callable[..., Any]")

bandersnatch (https://github.com/pypa/bandersnatch)
+ src/bandersnatch_storage_plugins/swift.py: note: In member "walk" of class "SwiftStorage":
+ src/bandersnatch_storage_plugins/swift.py:624: error: Argument 1 to "append" of "list" has incompatible type "Path"; expected "SwiftPath"
+ src/bandersnatch_storage_plugins/swift.py:626: error: Argument 1 to "append" of "list" has incompatible type "Path"; expected "SwiftPath"
+ src/bandersnatch_storage_plugins/swift.py: note: In member "rmdir" of class "SwiftStorage":
+ src/bandersnatch_storage_plugins/swift.py:839: error: Unexpected keyword argument "include_swiftkeep" for "iterdir" of "Path"
+ src/bandersnatch_storage_plugins/swift.py:839: error: Unexpected keyword argument "recurse" for "iterdir" of "Path"
+ src/bandersnatch_storage_plugins/swift.py:839: error: Unexpected keyword argument "include_swiftkeep" for "iterdir" of "Path"
+ src/bandersnatch_storage_plugins/swift.py:839: error: Unexpected keyword argument "recurse" for "iterdir" of "Path"
+ src/bandersnatch_storage_plugins/swift.py: note: In member "path_backend" of class "SwiftFileLock":
+ src/bandersnatch_storage_plugins/swift.py:64: error: Incompatible return value type (got "Type[Path]", expected "Type[SwiftPath]")
+ src/bandersnatch_storage_plugins/s3.py: note: In member "path_backend" of class "S3FileLock":
+ src/bandersnatch_storage_plugins/s3.py:77: error: Incompatible return value type (got "Type[Path]", expected "Type[S3Path]")
+ src/bandersnatch_storage_plugins/s3.py: note: In member "walk" of class "S3Storage":
+ src/bandersnatch_storage_plugins/s3.py:179: error: Argument 1 to "append" of "list" has incompatible type "Path"; expected "S3Path"
+ src/bandersnatch_storage_plugins/s3.py:181: error: Argument 1 to "append" of "list" has incompatible type "Path"; expected "S3Path"
+ src/bandersnatch_storage_plugins/s3.py:183: error: Argument 1 to "append" of "list" has incompatible type "Path"; expected "S3Path"
+ src/bandersnatch_storage_plugins/s3.py: note: At top level:
+ src/bandersnatch_storage_plugins/s3.py:207: error: Unused "type: ignore" comment
+ src/bandersnatch_storage_plugins/s3.py: note: In member "copy_file" of class "S3Storage":
+ src/bandersnatch_storage_plugins/s3.py:253: error: "Path" has no attribute "_accessor"
+ src/bandersnatch_storage_plugins/s3.py:256: error: "Path" has no attribute "key"
+ src/bandersnatch_storage_plugins/s3.py:257: error: "Path" has no attribute "bucket"
+ src/bandersnatch_storage_plugins/s3.py:257: error: "Path" has no attribute "key"
+ src/bandersnatch_storage_plugins/s3.py:258: error: "Path" has no attribute "bucket"
+ src/bandersnatch_storage_plugins/s3.py: note: In member "write_file" of class "S3Storage":
+ src/bandersnatch_storage_plugins/s3.py:274: error: Incompatible types in assignment (expression has type "BinaryIO", variable has type "TextIO")
+ src/bandersnatch_storage_plugins/s3.py:275: error: Argument 1 to "write" of "IO" has incompatible type "bytes"; expected "str"
+ src/bandersnatch_storage_plugins/s3.py: note: In member "mkdir" of class "S3Storage":
+ src/bandersnatch_storage_plugins/s3.py:339: error: "Type[Path]" has no attribute "keep_file"
+ src/bandersnatch_storage_plugins/s3.py:344: error: "Type[Path]" has no attribute "keep_file"
+ src/bandersnatch_storage_plugins/s3.py: note: In member "get_upload_time" of class "S3Storage":
+ src/bandersnatch_storage_plugins/s3.py:406: error: "Path" has no attribute "_accessor"
+ src/bandersnatch_storage_plugins/s3.py:407: error: "Path" has no attribute "bucket"
+ src/bandersnatch_storage_plugins/s3.py:407: error: "Path" has no attribute "key"
+ src/bandersnatch_storage_plugins/s3.py: note: In member "set_upload_time" of class "S3Storage":
+ src/bandersnatch_storage_plugins/s3.py:416: error: "Path" has no attribute "_accessor"
+ src/bandersnatch_storage_plugins/s3.py:417: error: "Path" has no attribute "bucket"
+ src/bandersnatch_storage_plugins/s3.py:417: error: "Path" has no attribute "key"
+ src/bandersnatch_storage_plugins/s3.py:422: error: "Path" has no attribute "bucket"
+ src/bandersnatch_storage_plugins/s3.py:422: error: "Path" has no attribute "key"

ibis (https://github.com/ibis-project/ibis)
- ibis/backends/base/sql/alchemy/__init__.py:61: error: Incompatible types in assignment (expression has type "Type[AlchemyTable]", base class "BaseSQLBackend" defined the type as "Type[DatabaseTable]")

pip (https://github.com/pypa/pip)
- src/pip/_internal/cli/progress_bars.py:132: error: Incompatible types in assignment (expression has type "Tuple[str, str, str]", base class "IncrementalBar" defined the type as "Tuple[str, str, str, str, str, str, str, str, str]")
+ src/pip/_internal/cli/progress_bars.py:132: error: Incompatible types in assignment (expression has type "Tuple[str, str, str]", variable has type "Tuple[str, str, str, str, str, str, str, str, str]")

spack (https://github.com/spack/spack)
+ lib/spack/spack/platforms/_platform.py:40: error: Incompatible types in assignment (expression has type "None", variable has type "int")
+ lib/spack/spack/platforms/_platform.py:45: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ lib/spack/spack/platforms/_platform.py:46: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ lib/spack/spack/platforms/_platform.py:47: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ lib/spack/spack/platforms/_platform.py:49: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ lib/spack/spack/platforms/_platform.py:50: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ lib/spack/spack/platforms/_platform.py:51: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ lib/spack/spack/compiler.py:268: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ lib/spack/spack/compiler.py:270: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ lib/spack/spack/package.py:666: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ lib/spack/spack/package.py:669: error: Incompatible types in assignment (expression has type "None", variable has type "str")

freqtrade (https://github.com/freqtrade/freqtrade)
+ freqtrade/persistence/models.py:88: error: Item "str" of "Optional[str]" has no attribute "isnot"
+ freqtrade/persistence/models.py:88: error: Item "None" of "Optional[str]" has no attribute "isnot"
+ freqtrade/persistence/models.py:814: error: Unsupported operand types for < ("datetime" and "None")
+ freqtrade/persistence/models.py:814: note: Left operand is of type "Optional[datetime]"
+ freqtrade/persistence/models.py:816: error: "bool" has no attribute "is_"
+ freqtrade/persistence/models.py:851: error: Item "str" of "Optional[str]" has no attribute "isnot"
+ freqtrade/persistence/models.py:851: error: Item "None" of "Optional[str]" has no attribute "isnot"
+ freqtrade/persistence/models.py:882: error: "bool" has no attribute "is_"
+ freqtrade/persistence/models.py:896: error: "bool" has no attribute "is_"
+ freqtrade/persistence/models.py:908: error: "bool" has no attribute "is_"
+ freqtrade/persistence/models.py:911: error: Unsupported operand types for <= ("datetime" and "None")
+ freqtrade/persistence/models.py:911: note: Left operand is of type "Optional[datetime]"
+ freqtrade/persistence/models.py:941: error: "bool" has no attribute "is_"
+ freqtrade/persistence/models.py:974: error: "bool" has no attribute "is_"
+ freqtrade/persistence/models.py:1007: error: "bool" has no attribute "is_"
+ freqtrade/persistence/models.py:1059: error: "bool" has no attribute "is_"
+ freqtrade/persistence/models.py:1059: error: Unsupported operand types for <= ("datetime" and "None")
+ freqtrade/persistence/models.py:1059: note: Left operand is of type "Optional[datetime]"
+ freqtrade/rpc/rpc.py:150: error: "int" has no attribute "in_"
+ freqtrade/rpc/rpc.py:268: error: "bool" has no attribute "is_"
+ freqtrade/rpc/rpc.py:269: error: Unsupported operand types for <= ("date" and "None")
+ freqtrade/rpc/rpc.py:269: note: Left operand is of type "Optional[datetime]"
+ freqtrade/rpc/rpc.py:270: error: Unsupported operand types for > ("date" and "None")
+ freqtrade/rpc/rpc.py:270: note: Left operand is of type "Optional[datetime]"
+ freqtrade/rpc/rpc.py:311: error: "bool" has no attribute "is_"
+ freqtrade/rpc/rpc.py:312: error: Unsupported operand types for <= ("date" and "None")
+ freqtrade/rpc/rpc.py:312: note: Left operand is of type "Optional[datetime]"
+ freqtrade/rpc/rpc.py:313: error: Unsupported operand types for > ("date" and "None")
+ freqtrade/rpc/rpc.py:313: note: Left operand is of type "Optional[datetime]"
+ freqtrade/rpc/rpc.py:353: error: "bool" has no attribute "is_"
+ freqtrade/rpc/rpc.py:354: error: Unsupported operand types for <= ("date" and "None")
+ freqtrade/rpc/rpc.py:354: note: Left operand is of type "Optional[datetime]"
+ freqtrade/rpc/rpc.py:355: error: Unsupported operand types for > ("date" and "None")
+ freqtrade/rpc/rpc.py:355: note: Left operand is of type "Optional[datetime]"
+ freqtrade/rpc/rpc.py:385: error: Item "datetime" of "Optional[datetime]" has no attribute "desc"
+ freqtrade/rpc/rpc.py:385: error: Item "None" of "Optional[datetime]" has no attribute "desc"
+ freqtrade/rpc/rpc.py:387: error: "bool" has no attribute "is_"
+ freqtrade/rpc/rpc.py:390: error: "bool" has no attribute "is_"
+ freqtrade/rpc/rpc.py:391: error: Item "datetime" of "Optional[datetime]" has no attribute "desc"
+ freqtrade/rpc/rpc.py:391: error: Item "None" of "Optional[datetime]" has no attribute "desc"
+ freqtrade/rpc/rpc.py:398: error: "bool" has no attribute "is_"
+ freqtrade/rpc/rpc.py:412: error: "bool" has no attribute "is_"
+ freqtrade/rpc/rpc.py:438: error: "bool" has no attribute "is_"
+ freqtrade/rpc/rpc.py:438: error: Unsupported operand types for <= ("datetime" and "None")
+ freqtrade/rpc/rpc.py:438: note: Left operand is of type "Optional[datetime]"
+ freqtrade/rpc/rpc.py:439: error: "bool" has no attribute "is_"
+ freqtrade/rpc/rpc.py:692: error: "bool" has no attribute "is_"
+ freqtrade/rpc/rpc.py:724: error: "bool" has no attribute "is_"
+ freqtrade/rpc/rpc.py:739: error: "bool" has no attribute "is_"
+ freqtrade/commands/list_commands.py:214: error: "int" has no attribute "in_"
+ freqtrade/freqtradebot.py:624: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ freqtrade/freqtradebot.py:869: error: Argument 2 to "update_trade_state" of "FreqtradeBot" has incompatible type "Optional[str]"; expected "str"
+ freqtrade/freqtradebot.py:926: error: No overload variant of "__sub__" of "datetime" matches argument type "None"
+ freqtrade/freqtradebot.py:926: note: Possible overload variants:
+ freqtrade/freqtradebot.py:926: note:     def __sub__(self, timedelta) -> datetime
+ freqtrade/freqtradebot.py:926: note:     def __sub__(self, datetime) -> timedelta
+ freqtrade/freqtradebot.py:926: note: Right operand is of type "Optional[datetime]"
+ freqtrade/freqtradebot.py:1057: error: Unsupported operand types for < ("float" and "None")
+ freqtrade/freqtradebot.py:1057: note: Both left and right operands are unions
+ freqtrade/freqtradebot.py:1062: error: Argument 1 to "cancel_order_with_result" of "Exchange" has incompatible type "Optional[str]"; expected "str"
+ freqtrade/freqtradebot.py:1088: error: Argument 2 to "update_trade_state" of "FreqtradeBot" has incompatible type "Optional[str]"; expected "str"
+ freqtrade/freqtradebot.py:1099: error: Argument 2 to "update_trade_state" of "FreqtradeBot" has incompatible type "Optional[str]"; expected "str"
+ freqtrade/freqtradebot.py:1120: error: Argument 1 to "cancel_order_with_result" of "Exchange" has incompatible type "Optional[str]"; expected "str"
+ freqtrade/freqtradebot.py:1259: error: Argument 2 to "update_trade_state" of "FreqtradeBot" has incompatible type "Optional[str]"; expected "str"

alerta (https://github.com/alerta/alerta)
+ alerta/models/alarms/__init__.py:22: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ alerta/models/alarms/__init__.py:23: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ alerta/models/alarms/__init__.py:24: error: Incompatible types in assignment (expression has type "None", variable has type "str")
+ alerta/models/alarms/__init__.py:25: error: Incompatible types in assignment (expression has type "None", variable has type "str")

pandas (https://github.com/pandas-dev/pandas)
+ pandas/core/arrays/period.py:326: error: Item "NaTType" of "Union[Period, NaTType]" has no attribute "ordinal"  [union-attr]
+ pandas/core/arrays/timedeltas.py:571: error: Incompatible types in assignment (expression has type "List[Any]", variable has type "ndarray[Any, dtype[floating[_64Bit]]]")  [assignment]
+ pandas/core/arrays/timedeltas.py:586: error: Incompatible types in assignment (expression has type "TimedeltaArray", variable has type "ndarray[Any, dtype[floating[_64Bit]]]")  [assignment]
+ pandas/core/arrays/timedeltas.py:628: error: Incompatible types in assignment (expression has type "List[Any]", variable has type "ndarray[Any, dtype[floating[_64Bit]]]")  [assignment]
+ pandas/tests/tseries/offsets/test_week.py:33: error: "None" not callable  [misc]
+ pandas/tests/tseries/offsets/test_week.py:34: error: "None" not callable  [misc]
+ pandas/tests/tseries/offsets/test_week.py:155: error: "None" not callable  [misc]
+ pandas/tests/tseries/offsets/test_week.py:156: error: "None" not callable  [misc]
+ pandas/tests/tseries/offsets/test_week.py:271: error: "None" not callable  [misc]
+ pandas/tests/tseries/offsets/test_week.py:272: error: "None" not callable  [misc]
+ pandas/tests/tseries/offsets/test_month.py:35: error: "None" not callable  [misc]
+ pandas/tests/tseries/offsets/test_month.py:36: error: "None" not callable  [misc]
+ pandas/tests/tseries/offsets/test_month.py:299: error: "None" not callable  [misc]
+ pandas/tests/tseries/offsets/test_month.py:300: error: "None" not callable  [misc]
+ pandas/tests/indexes/interval/test_base.py:19: error: "Type[Index]" has no attribute "from_breaks"  [attr-defined]
+ pandas/tests/indexes/categorical/test_category.py:25: error: Incompatible return value type (got "Index", expected "CategoricalIndex")  [return-value]

@A5rocks
Copy link
Collaborator

A5rocks commented Jan 22, 2022

To me, based on the mypy primer results, it looks like you broke this case: (I haven't tested this worked, but this felt like a nice minimum repro for you to use as a base for a fix)

def f(x: int) -> int: return x

class Example:
  n = f
  g = n(42)

@Timmmm
Copy link
Author

Timmmm commented Jan 24, 2022

Hmm I can't get your example to produce any errors. I always get:

Success: no issues found in 1 source file

I think 90% of the changes look like they're because I deleted this code:

            elif (is_literal_none(rvalue) and
                    isinstance(lvalue, NameExpr) and
                    isinstance(lvalue.node, Var) and
                    lvalue.node.is_initialized_in_class and
                    not new_syntax):
                # Allow None's to be assigned to class variables with non-Optional types.
                rvalue_type = lvalue_type

So a load of errors are detected where people did # type: foo where they should have written # type: Optional[foo]. I'm not sure I understand why you'd want that weird special case in the first place though.

Anyway I'm sure you're right that it's not quite correct. I was really hoping someone more familiar with the code could take a look at it!

Comment on lines +3072 to +3073
inferred = cast(Var, lvalue.node)
assert isinstance(inferred, Var)
Copy link
Collaborator

@A5rocks A5rocks Jan 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit suspicious -- does assert isinstance(lvalue.node, Var) and then inferred = lvalue.node not work here? I would have thought it would narrow.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good spot!

@A5rocks
Copy link
Collaborator

A5rocks commented Jan 25, 2022

My bad, I should have actually loaded your branch and not just guessed, lol

Here's some cases this seems to change (I don't know much we want to support them, though):

class A:
    DEFAULT_STATUS = None  # type: str

This seems to be intentional by you?

I suspect some of the other errors may be functions overriding parents being typechecked as if they are their own function instead of reusing the parents arguments or... something. I have no clue why certain things are being unearthed and can only suspect you're propagating errors that type: ignores prevented (for instance the first pandas error)

@Timmmm
Copy link
Author

Timmmm commented Jan 25, 2022

Yeah so that was sort of intentional in that I knew it would do that. I didn't really want to have to change it but I couldn't get the code to work otherwise (can't remember the exact issue now) and it didn't seem to make any sense to allow A = None # type: str anyway. Especially when A: str = None is not allowed. Do you know why it's like that?

@JelleZijlstra
Copy link
Member

@Timmmm this is a legacy of the pre-PEP 526 days (i.e., Python 2.7 and <3.6), when x: str = None was a syntax error. To support that legacy behavior, mypy allows None in contexts like this.

@Timmmm
Copy link
Author

Timmmm commented Jan 25, 2022

Ah do you mean at some point you couldn't do A = None # type: Optional[str]? Since you can now I guess the only reason for that exception now is because it would be a breaking change to remove it?

@JelleZijlstra
Copy link
Member

No, it's because there was no way to write A: str (declaring a type but not assigning a value).

@Timmmm
Copy link
Author

Timmmm commented Jan 25, 2022

Sorry if I'm being dense but why does that mean you need to treat # type: str as if it was # type: Optional[str]?

@JelleZijlstra
Copy link
Member

I think it's the opposite. Your PR makes mypy throw errors on code like https://github.com/alerta/alerta/blob/c951891beeb855f3f97ad58df043b9c1c339f10c/alerta/models/alarms/__init__.py#L22 that does X = None # type: str, but we need to support that pattern for now.

@Timmmm
Copy link
Author

Timmmm commented Jan 25, 2022

Yes it does but the thing I don't understand is why does that pattern exist in the first place?

@JelleZijlstra
Copy link
Member

Yes it does but the thing I don't understand is why does that pattern exist in the first place?

Because there's no way to declare a variable without an initializer using type comments, so projects that still support Python 2 or 3.5 need to use this pattern.

@Timmmm
Copy link
Author

Timmmm commented Jan 26, 2022

I think we're having some communication issues! Why can projects that need to support Python 2 or 3.5 not do this?

A = None # type: Optional[str]

@A5rocks
Copy link
Collaborator

A5rocks commented Jan 26, 2022

As I understand it,

x = None  # type: str

is equivalent to

x: str

Because you cannot express the second with type comments.

@Timmmm
Copy link
Author

Timmmm commented Jan 26, 2022

They aren't equivalent. The code I removed special cases the # type: foo syntax for class variables so it is not the same as x: foo. Basically it disables strict optional for class variables using the # type: syntax.

Try it out!

I don't understand why that was ever needed.

@Timmmm
Copy link
Author

Timmmm commented Jan 26, 2022

Wait I think I might have just figured it out. With the old # type syntax there's no way to declare a class variable without also assigning it a value. So you might be forced to assign None, even if you really want the type to be something else. E.g.

class Foo:
   a = None # type: str
   def __init__(self, b: bool):
      if b:
          self.a = "yes"
      else:
          self.a = "no"

@Timmmm Timmmm closed this Aug 8, 2024
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.

Types of inheritanced class attributes aren't detected
3 participants