Skip to content

Commit

Permalink
Merge branch 'master' into related-descriptors
Browse files Browse the repository at this point in the history
  • Loading branch information
JaeHyuckSa authored May 16, 2024
2 parents 761b4b8 + de6d1fa commit 3ab49c2
Show file tree
Hide file tree
Showing 17 changed files with 82 additions and 58 deletions.
24 changes: 24 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,27 @@ jobs:
run: python -m build
- name: Publish to PyPI
uses: pypa/[email protected]

build-and-publish-ext:
runs-on: ubuntu-latest
environment:
name: release-ext
url: https://pypi.org/p/django-stubs-ext
permissions:
id-token: write
steps:
- name: Setup python to build package
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install build
run: python -m pip install build
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build ext package
run: python -m build ext/
- name: Publish ext to PyPI
uses: pypa/[email protected]
with:
packages-dir: ext/dist/
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ repos:
args: [--fix=lf]
- id: check-case-conflict
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.3
rev: v0.4.4
hooks:
- id: ruff
args: ["--fix", "--exit-non-zero-on-fix"]
Expand Down
8 changes: 7 additions & 1 deletion django-stubs/contrib/gis/db/backends/postgis/operations.pyi
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from typing import Any, Literal
from typing import Any, Literal, MutableMapping

from django.contrib.gis.db.backends.base.operations import BaseSpatialOperations
from django.contrib.gis.db.backends.utils import SpatialOperator
from django.contrib.gis.db.models.fields import GeometryField
from django.contrib.gis.db.models.lookups import GISLookup
from django.db.backends.postgresql.operations import DatabaseOperations
from django.db.models import Func
from django.utils.functional import cached_property
Expand All @@ -14,6 +15,11 @@ class PostGISOperator(SpatialOperator):
raster: bool | Literal["bilateral"]
def __init__(self, geography: bool = ..., raster: bool | Literal["bilateral"] = ..., **kwargs: Any) -> None: ...
def check_raster(self, lookup: Any, template_params: Any) -> Any: ...
def check_geography(
self,
lookup: GISLookup,
template_params: MutableMapping[str, Any],
) -> MutableMapping[str, Any]: ...

class ST_Polygon(Func):
function: str
Expand Down
6 changes: 3 additions & 3 deletions django-stubs/contrib/gis/db/backends/utils.pyi
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from collections.abc import Mapping, Sequence
from typing import Any
from collections.abc import Sequence
from typing import Any, MutableMapping

from django.contrib.gis.db.models.lookups import GISLookup
from django.db.backends.base.base import BaseDatabaseWrapper
Expand All @@ -16,6 +16,6 @@ class SpatialOperator:
self,
connection: BaseDatabaseWrapper,
lookup: GISLookup,
template_params: Mapping[str, Any],
template_params: MutableMapping[str, Any],
sql_params: Sequence[Any],
) -> _AsSqlType: ...
2 changes: 1 addition & 1 deletion django-stubs/db/models/enums.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,6 @@ class _TextChoicesMeta(ChoicesType):
def values(self) -> list[str]: ...

class TextChoices(Choices, StrEnum, metaclass=_TextChoicesMeta):
def __new__(cls, value: str) -> Self: ...
def __new__(cls, value: str | tuple[str, str]) -> Self: ...
@_enum_property
def value(self) -> str: ...
1 change: 1 addition & 0 deletions django-stubs/db/models/fields/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]):
remote_field: ForeignObjectRel | None
is_relation: bool
related_model: type[Model] | Literal["self"] | None
generated: ClassVar[bool]
one_to_many: bool | None
one_to_one: bool | None
many_to_many: bool | None
Expand Down
4 changes: 2 additions & 2 deletions django-stubs/db/models/fields/generated.pyi
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Iterable, Literal
from typing import Any, ClassVar, Iterable, Literal

from django.core.validators import _ValidatorCallable
from django.db import models
Expand All @@ -11,7 +11,7 @@ from django.utils.datastructures import DictWrapper
from django.utils.functional import _StrOrPromise

class GeneratedField(models.Field):
generated: Literal[True]
generated: ClassVar[Literal[True]]
db_returning: Literal[True]
_query: Query | None
output_field: models.Field | None
Expand Down
2 changes: 2 additions & 0 deletions django-stubs/db/models/fields/related.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ class ForeignObject(RelatedField[_ST, _GT]):
def local_related_fields(self) -> tuple[Field, ...]: ...
@cached_property
def foreign_related_fields(self) -> tuple[Field, ...]: ...
def get_joining_fields(self, reverse_join: bool = False) -> tuple[tuple[Field, Field], ...]: ...
def get_reverse_joining_fields(self) -> tuple[tuple[Field, Field], ...]: ...

class ForeignKey(ForeignObject[_ST, _GT]):
_pyi_private_set_type: Any | Combinable
Expand Down
5 changes: 4 additions & 1 deletion django-stubs/db/models/fields/reverse_related.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ from typing import Any, Literal
from django.db.models.base import Model
from django.db.models.fields import AutoField, Field, _AllLimitChoicesTo, _ChoicesList, _LimitChoicesTo
from django.db.models.fields.related import ForeignKey, ForeignObject, ManyToManyField, OneToOneField
from django.db.models.lookups import Lookup, StartsWith
from django.db.models.lookups import Lookup, StartsWith, Transform
from django.db.models.query_utils import FilteredRelation, PathInfo
from django.db.models.sql.where import WhereNode
from django.utils.functional import cached_property
Expand Down Expand Up @@ -62,6 +62,8 @@ class ForeignObjectRel(FieldCacheMixin):
@cached_property
def one_to_one(self) -> bool: ...
def get_lookup(self, lookup_name: str) -> type[Lookup] | None: ...
def get_lookups(self) -> dict[str, Any]: ...
def get_transform(self, name: str) -> type[Transform] | None: ...
def get_internal_type(self) -> str: ...
@property
def db_type(self) -> Any: ...
Expand All @@ -76,6 +78,7 @@ class ForeignObjectRel(FieldCacheMixin):
) -> _ChoicesList: ...
def is_hidden(self) -> bool: ...
def get_joining_columns(self) -> tuple: ...
def get_joining_fields(self) -> tuple[tuple[Field, Field], ...]: ...
def get_extra_restriction(
self, where_class: type[WhereNode], alias: str, related_alias: str
) -> StartsWith | WhereNode | None: ...
Expand Down
1 change: 1 addition & 0 deletions django-stubs/db/models/query.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ class Prefetch:
def get_current_prefetch_to(self, level: int) -> str: ...
def get_current_to_attr(self, level: int) -> tuple[str, str]: ...
def get_current_queryset(self, level: int) -> QuerySet | None: ...
def get_current_querysets(self, level: int) -> list[QuerySet] | None: ...

def prefetch_related_objects(model_instances: Iterable[_Model], *related_lookups: str | Prefetch) -> None: ...
async def aprefetch_related_objects(model_instances: Iterable[_Model], *related_lookups: str | Prefetch) -> None: ...
Expand Down
2 changes: 0 additions & 2 deletions django-stubs/db/models/sql/datastructures.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ class Join:
) -> None: ...
def as_sql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper) -> _AsSqlType: ...
def relabeled_clone(self, change_map: dict[str | None, str]) -> Join: ...
def equals(self, other: BaseTable | Join, with_filtered_relation: bool) -> bool: ...
def demote(self) -> Join: ...
def promote(self) -> Join: ...

Expand All @@ -46,4 +45,3 @@ class BaseTable:
def __init__(self, table_name: str, alias: str | None) -> None: ...
def as_sql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper) -> _AsSqlType: ...
def relabeled_clone(self, change_map: dict[str | None, str]) -> BaseTable: ...
def equals(self, other: Join, with_filtered_relation: bool) -> bool: ...
17 changes: 0 additions & 17 deletions ext/release.sh

This file was deleted.

4 changes: 2 additions & 2 deletions mypy_django_plugin/transformers/manytomany.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import NamedTuple, Optional, Tuple, Union

from mypy.checker import TypeChecker
from mypy.nodes import AssignmentStmt, Expression, MemberExpr, NameExpr, StrExpr, TypeInfo
from mypy.nodes import AssignmentStmt, Expression, MemberExpr, NameExpr, RefExpr, StrExpr, TypeInfo
from mypy.plugin import FunctionContext, MethodContext
from mypy.semanal import SemanticAnalyzer
from mypy.types import Instance, ProperType, TypeVarType, UninhabitedType
Expand Down Expand Up @@ -129,7 +129,7 @@ def get_model_from_expression(
Attempts to resolve an expression to a 'TypeInfo' instance. Any lazy reference
argument(e.g. "<app_label>.<object_name>") to a Django model is also attempted.
"""
if isinstance(expr, NameExpr) and isinstance(expr.node, TypeInfo):
if isinstance(expr, RefExpr) and isinstance(expr.node, TypeInfo):
if helpers.is_model_type(expr.node):
return Instance(expr.node, [])

Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Dev tools:
black==24.4.2
pre-commit==3.5.0; python_version < '3.9'
pre-commit==3.7.0; python_version >= '3.9'
pre-commit==3.7.1; python_version >= '3.9'
pytest==8.2.0
pytest-mypy-plugins==3.1.2
pytest-shard==0.1.2
Expand Down
11 changes: 0 additions & 11 deletions scripts/stubtest/allowlist_todo.txt
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,6 @@ django.contrib.gis.db.backends.postgis.features.DatabaseFeatures.empty_intersect
django.contrib.gis.db.backends.postgis.features.DatabaseFeatures.supports_geography
django.contrib.gis.db.backends.postgis.operations.PostGISOperations.convert_extent
django.contrib.gis.db.backends.postgis.operations.PostGISOperations.convert_extent3d
django.contrib.gis.db.backends.postgis.operations.PostGISOperator.check_geography
django.contrib.gis.db.backends.postgis.schema.PostGISSchemaEditor.rast_index_template
django.contrib.gis.db.backends.spatialite.base.DatabaseWrapper.ops
django.contrib.gis.db.backends.spatialite.features.DatabaseFeatures.can_alter_geometry_field
Expand Down Expand Up @@ -316,8 +315,6 @@ django.contrib.gis.db.models.ForeignObject.reverse_path_infos
django.contrib.gis.db.models.ForeignObjectRel.__init__
django.contrib.gis.db.models.ForeignObjectRel.empty_strings_allowed
django.contrib.gis.db.models.ForeignObjectRel.get_extra_restriction
django.contrib.gis.db.models.ForeignObjectRel.get_lookups
django.contrib.gis.db.models.ForeignObjectRel.get_transform
django.contrib.gis.db.models.ForeignObjectRel.identity
django.contrib.gis.db.models.ForeignObjectRel.path_infos
django.contrib.gis.db.models.Func.function
Expand Down Expand Up @@ -753,8 +750,6 @@ django.db.models.ForeignObject.reverse_path_infos
django.db.models.ForeignObjectRel.__init__
django.db.models.ForeignObjectRel.empty_strings_allowed
django.db.models.ForeignObjectRel.get_extra_restriction
django.db.models.ForeignObjectRel.get_lookups
django.db.models.ForeignObjectRel.get_transform
django.db.models.ForeignObjectRel.identity
django.db.models.ForeignObjectRel.path_infos
django.db.models.Func.function
Expand Down Expand Up @@ -995,8 +990,6 @@ django.db.models.fields.related.ForeignObject.reverse_path_infos
django.db.models.fields.related.ForeignObjectRel.__init__
django.db.models.fields.related.ForeignObjectRel.empty_strings_allowed
django.db.models.fields.related.ForeignObjectRel.get_extra_restriction
django.db.models.fields.related.ForeignObjectRel.get_lookups
django.db.models.fields.related.ForeignObjectRel.get_transform
django.db.models.fields.related.ForeignObjectRel.identity
django.db.models.fields.related.ForeignObjectRel.path_infos
django.db.models.fields.related.ManyToManyField.__get__
Expand Down Expand Up @@ -1027,8 +1020,6 @@ django.db.models.fields.related_lookups.RelatedLookupMixin.as_sql
django.db.models.fields.reverse_related.ForeignObjectRel.__init__
django.db.models.fields.reverse_related.ForeignObjectRel.empty_strings_allowed
django.db.models.fields.reverse_related.ForeignObjectRel.get_extra_restriction
django.db.models.fields.reverse_related.ForeignObjectRel.get_lookups
django.db.models.fields.reverse_related.ForeignObjectRel.get_transform
django.db.models.fields.reverse_related.ForeignObjectRel.identity
django.db.models.fields.reverse_related.ForeignObjectRel.path_infos
django.db.models.fields.reverse_related.ManyToManyRel.identity
Expand Down Expand Up @@ -1237,9 +1228,7 @@ django.db.models.sql.compiler.SQLCompiler.deferred_to_columns
django.db.models.sql.compiler.SQLCompiler.get_default_columns
django.db.models.sql.compiler.SQLCompiler.get_qualify_sql
django.db.models.sql.compiler.SQLCompiler.get_related_selections
django.db.models.sql.datastructures.BaseTable.equals
django.db.models.sql.datastructures.BaseTable.identity
django.db.models.sql.datastructures.Join.equals
django.db.models.sql.datastructures.Join.identity
django.db.models.sql.query.Query.__init__
django.db.models.sql.query.Query.add_annotation
Expand Down
16 changes: 0 additions & 16 deletions scripts/stubtest/allowlist_todo_django50.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,11 @@ django.contrib.gis.db.models.Case.allowed_default
django.contrib.gis.db.models.ExpressionWrapper.allowed_default
django.contrib.gis.db.models.F.allowed_default
django.contrib.gis.db.models.Field._get_flatchoices
django.contrib.gis.db.models.Field.generated
django.contrib.gis.db.models.FilteredRelation.relabeled_clone
django.contrib.gis.db.models.FilteredRelation.resolve_expression
django.contrib.gis.db.models.ForeignKey.cast_db_type
django.contrib.gis.db.models.ForeignObject.get_joining_fields
django.contrib.gis.db.models.ForeignObject.get_reverse_joining_fields
django.contrib.gis.db.models.ForeignObjectRel.get_joining_fields
django.contrib.gis.db.models.Func.allowed_default
django.contrib.gis.db.models.Lookup.allowed_default
django.contrib.gis.db.models.Prefetch.get_current_querysets
django.contrib.gis.db.models.Q.identity
django.contrib.gis.db.models.When.allowed_default
django.contrib.gis.geos.prototypes.io.DEFAULT_TRIM_VALUE
Expand All @@ -38,16 +33,11 @@ django.db.models.Case.allowed_default
django.db.models.ExpressionWrapper.allowed_default
django.db.models.F.allowed_default
django.db.models.Field._get_flatchoices
django.db.models.Field.generated
django.db.models.FilteredRelation.relabeled_clone
django.db.models.FilteredRelation.resolve_expression
django.db.models.ForeignKey.cast_db_type
django.db.models.ForeignObject.get_joining_fields
django.db.models.ForeignObject.get_reverse_joining_fields
django.db.models.ForeignObjectRel.get_joining_fields
django.db.models.Func.allowed_default
django.db.models.Lookup.allowed_default
django.db.models.Prefetch.get_current_querysets
django.db.models.Q.identity
django.db.models.When.allowed_default
django.db.models.expressions.Case.allowed_default
Expand All @@ -57,16 +47,10 @@ django.db.models.expressions.F.allowed_default
django.db.models.expressions.Func.allowed_default
django.db.models.expressions.When.allowed_default
django.db.models.fields.Field._get_flatchoices
django.db.models.fields.Field.generated
django.db.models.fields.related.ForeignKey.cast_db_type
django.db.models.fields.related.ForeignObject.get_joining_fields
django.db.models.fields.related.ForeignObject.get_reverse_joining_fields
django.db.models.fields.related.ForeignObjectRel.get_joining_fields
django.db.models.fields.reverse_related.ForeignObjectRel.get_joining_fields
django.db.models.functions.Now.as_oracle
django.db.models.functions.datetime.Now.as_oracle
django.db.models.lookups.Lookup.allowed_default
django.db.models.query.Prefetch.get_current_querysets
django.db.models.query_utils.FilteredRelation.relabeled_clone
django.db.models.query_utils.FilteredRelation.resolve_expression
django.db.models.query_utils.Q.identity
Expand Down
33 changes: 33 additions & 0 deletions tests/typecheck/fields/test_related.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1340,3 +1340,36 @@
class MyModel(ConcreteParent, AbstractParent):
m2m_5 = models.ManyToManyField(Other, related_name="mymodel")
- case: test_m2m_related_managers_supports_renamed_imports
main: |
from myapp.models import MyModel
from other.models import Other
reveal_type(MyModel.m2m_1.through.objects) # N: Revealed type is "django.db.models.manager.Manager[myapp.models.MyModel_m2m_1]"
reveal_type(Other.auto_through.through.objects) # N: Revealed type is "django.db.models.manager.Manager[myapp.models.MyModel_m2m_1]"
reveal_type(MyModel.m2m_2.through.objects) # N: Revealed type is "django.db.models.manager.Manager[myapp.models.Through]"
reveal_type(Other.custom_through.through.objects) # N: Revealed type is "django.db.models.manager.Manager[myapp.models.Through]"
installed_apps:
- other
- myapp
files:
- path: other/__init__.py
- path: other/models.py
content: |
from django.db import models
class Other(models.Model):
...
- path: myapp/__init__.py
- path: myapp/models.py
content: |
from django.db import models
from other import models as other_models
class Through(models.Model):
mymodel = models.ForeignKey("myapp.MyModel", on_delete=models.CASCADE)
other = models.ForeignKey(other_models.Other, on_delete=models.CASCADE)
class MyModel(models.Model):
m2m_1 = models.ManyToManyField(other_models.Other, related_name="auto_through")
m2m_2 = models.ManyToManyField(other_models.Other, related_name="custom_through", through=Through)

0 comments on commit 3ab49c2

Please sign in to comment.