From eecf13a2fe35ca4628b2ef9b1096070e96ce055f Mon Sep 17 00:00:00 2001 From: William Schwartz Date: Tue, 1 Dec 2020 00:42:56 -0600 Subject: [PATCH 1/2] Fix loaddata.pyi - Added some of the instance attributes from command arguments: ignore, using, app_label, verbosity, format. - Added class attribute: help. - Fixed return type of find_fixtures. --- django-stubs/core/management/commands/loaddata.pyi | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/django-stubs/core/management/commands/loaddata.pyi b/django-stubs/core/management/commands/loaddata.pyi index 7ca630a..57541c0 100644 --- a/django-stubs/core/management/commands/loaddata.pyi +++ b/django-stubs/core/management/commands/loaddata.pyi @@ -6,10 +6,16 @@ from django.core.management.base import BaseCommand READ_STDIN: str = ... class Command(BaseCommand): + ignore: bool = ... + using: str = ... + app_label: str = ... + verbosity: int = ... + format: str = ... missing_args_message: str = ... + help: str = ... def loaddata(self, fixture_labels: Iterable[str]) -> None: ... def load_label(self, fixture_label: str) -> None: ... - def find_fixtures(self, fixture_label: str) -> List[Optional[str]]: ... + def find_fixtures(self, fixture_label: str) -> List[Tuple[str, str, str]]: ... @property def fixture_dirs(self) -> List[str]: ... def parse_name(self, fixture_name: str) -> Tuple[str, str, str]: ... From d3ff5415db9306b2d5a766b2167a9d2e1a548ce2 Mon Sep 17 00:00:00 2001 From: William Schwartz Date: Tue, 1 Dec 2020 11:32:59 -0600 Subject: [PATCH 2/2] Finish loaddata.pyi This incorporates all type information I could glean from loaddata at django/django@adb40d217ec57ade46b1394cfbf3c513dc669445. - Remove `help` per review comment: https://github.com/typeddjango/django-stubs/pull/536#discussion_r533179013 - Add `exclude_models` and `exclude_apps` based on the return type of `..utils.parse_apps_and_model_labels`. - Change `loaddata`'s `fixture_labels` to `Sequence` of `str` instead of `Iterable` because in practice it's a tuple, but at a type level, the important thing is that `loaddata` iterates over `fixture_labels` more than once. General iterables (which include iterators) need not support iteration more than once. - Correct the return type of `parse_name` to account for the possibility that the data and compression formats are `None`. - Correct the return type of `find_fixtures` to be a list of the same type that `parse_name` returns. - Add a type annotation for `SingleZipReader.read`. Django implements the method in a way that actually conflicts with `zipfile.ZipFile.read`'s type. This necessitates a `type: ignore[override]` to keep the tests passing. Mypy is correct that there is an override error, but Django's code is what it is. (And that method's signature was introduced way back in Django version 1.1, commit django/django@089ab18c025917f38a2e3731ae4024d4810df1ec.) --- .../core/management/commands/loaddata.pyi | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/django-stubs/core/management/commands/loaddata.pyi b/django-stubs/core/management/commands/loaddata.pyi index 57541c0..be9a963 100644 --- a/django-stubs/core/management/commands/loaddata.pyi +++ b/django-stubs/core/management/commands/loaddata.pyi @@ -1,7 +1,9 @@ import zipfile -from typing import Iterable, List, Optional, Tuple +from typing import List, Optional, Set, Sequence, Tuple, Type +from django.apps.config import AppConfig from django.core.management.base import BaseCommand +from django.db.models.base import Model READ_STDIN: str = ... @@ -10,16 +12,24 @@ class Command(BaseCommand): using: str = ... app_label: str = ... verbosity: int = ... + excluded_models: Set[Type[Model]] = ... + excluded_apps: Set[AppConfig] = ... format: str = ... missing_args_message: str = ... - help: str = ... - def loaddata(self, fixture_labels: Iterable[str]) -> None: ... + def loaddata(self, fixture_labels: Sequence[str]) -> None: ... def load_label(self, fixture_label: str) -> None: ... - def find_fixtures(self, fixture_label: str) -> List[Tuple[str, str, str]]: ... + def find_fixtures(self, fixture_label: str) -> List[Tuple[str, Optional[str], Optional[str]]]: ... @property def fixture_dirs(self) -> List[str]: ... - def parse_name(self, fixture_name: str) -> Tuple[str, str, str]: ... + def parse_name(self, fixture_name: str) -> Tuple[str, Optional[str], Optional[str]]: ... -class SingleZipReader(zipfile.ZipFile): ... +class SingleZipReader(zipfile.ZipFile): + # Incompatible override + # zipfile.ZipFile.read( + # self, + # name: typing.Union[typing.Text, zipfile.ZipInfo], + # pwd: Optional[bytes] = ..., + # ) -> bytes: ... + def read(self) -> bytes: ... # type: ignore[override] def humanize(dirname: str) -> str: ...