summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/ext/mypy/decl_class.py
Commit message (Collapse)AuthorAgeFilesLines
* pep-484 for sqlalchemy.event; use future annotationsMike Bayer2022-02-151-0/+2
| | | | | | | | | | __future__.annotations mode allows us to use non-string annotations for argument and return types in most cases, but more importantly it removes a large amount of runtime overhead that would be spent in evaluating the annotations. Change-Id: I2f5b6126fe0019713fc50001be3627b664019ede References: #6810
* establish mypy / typing approach for v2.0Mike Bayer2022-02-131-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | large patch to get ORM / typing efforts started. this is to support adding new test cases to mypy, support dropping sqlalchemy2-stubs entirely from the test suite, validate major ORM typing reorganization to eliminate the need for the mypy plugin. * New declarative approach which uses annotation introspection, fixes: #7535 * Mapped[] is now at the base of all ORM constructs that find themselves in classes, to support direct typing without plugins * Mypy plugin updated for new typing structures * Mypy test suite broken out into "plugin" tests vs. "plain" tests, and enhanced to better support test structures where we assert that various objects are introspected by the type checker as we expect. as we go forward with typing, we will add new use cases to "plain" where we can assert that types are introspected as we expect. * For typing support, users will be much more exposed to the class names of things. Add these all to "sqlalchemy" import space. * Column(ForeignKey()) no longer needs to be `@declared_attr` if the FK refers to a remote table * composite() attributes mapped to a dataclass no longer need to implement a `__composite_values__()` method * with_variant() accepts multiple dialect names Change-Id: I22797c0be73a8fbbd2d6f5e0c0b7258b17fe145d Fixes: #7535 Fixes: #7551 References: #6810
* use fully qualified, locatable names for all use of api.named_type()Mike Bayer2021-12-221-1/+1
| | | | | | | | | | | | Fixed mypy regression where the release of mypy 0.930 added additional internal checks to the format of "named types", requiring that they be fully qualified and locatable. This broke the mypy plugin for SQLAlchemy, raising an assertion error, as there was use of symbols such as ``__builtins__`` and other un-locatable or unqualified names that previously had not raised any assertions. Fixes: #7496 Change-Id: I037680606a1d51158ef6503508ec76c5d5adc946
* handle dunder names in @declared_attr separatelyMike Bayer2021-11-171-1/+14
| | | | | | | | | | | | | | | | Fixed Mypy crash which would occur when using Mypy plugin against code which made use of :class:`_orm.declared_attr` methods for non-mapped names like ``__mapper_args__``, ``__table_args__``, or other dunder names, as the plugin would try to interpret these as mapped attributes which would then be later mis-handled. As part of this change, the decorated function is still converted by the plugin into a generic assignment statement (e.g. ``__mapper_args__: Any``) so that the argument signature can continue to be annotated in the same way one would for any other ``@classmethod`` without Mypy complaining about the wrong argument type for a method that isn't explicitly ``@classmethod``. Fixes: #7321 Change-Id: I55656e867876677c5c55143449db371344be8600
* ensure "sqlalchemy" info set for all considered classesMike Bayer2021-08-251-0/+3
| | | | | | | | | Fixed issue in mypy plugin where columns on a mixin would not be correctly interpreted if the mapped class relied upon a ``__tablename__`` routine that came from a superclass. Fixes: #6937 Change-Id: I74aed4862d0545008ee67f781aaa794ab6866926
* Refactor mypy pluginBryan Forbes2021-08-071-68/+82
| | | | | | | | | | A major refactor of the mypy plugin Closes: #6764 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/6764 Pull-request-sha: 3e2295b2da7b57a6669f26db0df78f6409934184 Change-Id: I067d56dcfbc998ddd1b22a448f756859428b9e31
* Replace all http:// links to https://Federico Caselli2021-07-041-1/+1
| | | | | | Also replace http://pypi.python.org/pypi with https://pypi.org/project Change-Id: I84b5005c39969a82140706472989f2a30b0c7685
* accommodate no cls info found in _scan_declarativeMike Bayer2021-06-211-1/+4
| | | | | | | | | Fixed issue in mypy plugin where class info for a custom declarative base would not be handled correctly on a cached mypy pass, leading to an AssertionError being raised. Fixes: #6476 Change-Id: If78340673e6a4d16d8f7cf787ce3bdb02c8bd47b
* Re-infer statements that got more specific on subsequent passMike Bayer2021-04-201-28/+7
| | | | | | | | | | | | | | | | | | | | | | | | Fixed issue where mypy plugin would not correctly interpret an explicit :class:`_orm.Mapped` annotation in conjunction with a :func:`_orm.relationship` that refers to a class by string name; the correct annotation would be downgraded to a less specific one leading to typing errors. The thing figured out here is that after we've already scanned a class in the semanal stage and created DeclClassApplied, when we are called again with that same DeclClassApplied, for this specific kind of case we actually now have *better* types than we did before, where the left side that looked like List?[Address?] now seems to say builtins.list[official.module.Address] - so let's take the right side expression again, this time embedded in our Mapped._empty_constructor() expression, and run the infer all over again just like mypy would. Just not setting the "wrong" type here fixed the test cases but by re-applying the whole infer we get the correct Mapped[] on the left side too. Fixes: #6255 Change-Id: Iafe7254374f685a8458c7a1db82aafc2ed6d0232
* Update mypy plugin to conform to strict modeBryan Forbes2021-04-121-54/+68
| | | | Change-Id: I09a3df5af2f2d4ee34d8d72c3dedc4f236df8eb1
* Update mypy plugin to only use public plugin APIBryan Forbes2021-04-091-7/+7
| | | | Change-Id: Id7f4e4a39e17c1b6ec3c754e2fc5c6ba4b437c38
* Adjust for mypy incremental behaviorsMike Bayer2021-04-051-642/+129
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Applied a series of refactorings and fixes to accommodate for Mypy "incremental" mode across multiple files, which previously was not taken into account. In this mode the Mypy plugin has to accommodate Python datatypes expressed in other files coming in with less information than they have on a direct run. Additionally, a new decorator :func:`_orm.declarative_mixin` is added, which is necessary for the Mypy plugin to be able to definifitely identify a Declarative mixin class that is otherwise not used inside a particular Python file. discussion: With incremental / deserialized mypy runs, it appears that when we look at a base class that comes from another file, cls.info is set to a special undefined node that matches CLASSDEF_NO_INFO, and we otherwise can't touch it without crashing. Additionally, sometimes cls.defs.body is present but empty. However, it appears that both of these cases can be sidestepped, first by doing a lookup() for the type name where we get a SymbolTableNode that then has the TypeInfo we wanted when we tried touching cls.info, and then however we got the TypeInfo, if cls.defs.body is empty we can just look in the names to get at the symbols for that class; we just can't access AssignmentStmts, but that's fine because we just need the information for classes we aren't actually type checking. This work also revealed there's no easy way to detect a mixin class so we just create a new decorator to mark that. will make code look better in any case. Fixes: #6147 Change-Id: Ia8fac8acfeec931d8f280491cffc5c6cb4a1204e
* Add DeclarativeMeta to globalsMike Bayer2021-03-311-10/+6
| | | | | | | | | | | | | | | | Fixed issue in mypy plugin where newly added support for :func:`_orm.as_declarative` needed to more fully add the ``DeclarativeMeta`` class to the mypy interpreter's state so that it does not result in a name not found error; additionally improves how global names are setup for the plugin including the ``Mapped`` name. Introduces directory oriented testing as well, where a full set of files will be copied, mypy runs, then zero or more patches are applied and mypy is run again, to fully test incremental behaviors. Fixes: sqlalchemy/sqlalchemy2-stubs/#14 Change-Id: Ide785c07e19ba0694e8cf6f91560094ecb182016
* Add support for Boolean, EnumMike Bayer2021-03-211-12/+30
| | | | | | | | | | Fixed bug in Mypy plugin where the Python type detection for the :class:`_sqltypes.Boolean` column type would produce an exception; additionally implemented support for :class:`_sqltypes.Enum`, including detection of a string-based enum vs. use of Python ``enum.Enum``. Fixes: #6109 Change-Id: I25e546ea2f50d90be2d6fec303976d82849a3d31
* check for MemberExpr looking for column argumentMike Bayer2021-03-181-1/+1
| | | | | | | | | Fixed issue in MyPy extension which crashed on detecting the type of a :class:`.Column` if the type were given with a module prefix like ``sa.Integer()``. Fixes: sqlalchemy/sqlalchemy2-stubs/#2 Change-Id: I71f53a6ced501ae144e28ce255cf3f50ea2b2e84
* Implement Mypy pluginMike Bayer2021-03-131-0/+989
Rudimentary and experimental support for Mypy has been added in the form of a new plugin, which itself depends on new typing stubs for SQLAlchemy. The plugin allows declarative mappings in their standard form to both be compatible with Mypy as well as to provide typing support for mapped classes and instances. Fixes: #4609 Change-Id: Ia035978c02ad3a5c0e5b3c6c30044dd5a3155170