Skip to content

Commit

Permalink
Add stubs for django-import-export (#11709)
Browse files Browse the repository at this point in the history
  • Loading branch information
Viicos authored Dec 28, 2024
1 parent ff4237f commit eb8af63
Show file tree
Hide file tree
Showing 19 changed files with 766 additions and 0 deletions.
1 change: 1 addition & 0 deletions pyrightconfig.stricter.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"stubs/corus",
"stubs/dateparser",
"stubs/defusedxml",
"stubs/django-import-export",
"stubs/docker",
"stubs/docutils",
"stubs/Flask-SocketIO",
Expand Down
6 changes: 6 additions & 0 deletions stubs/django-import-export/METADATA.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version = "3.3.*"
upstream_repository = "https://github.com/django-import-export/django-import-export"
requires = ["django-stubs"] # Add tablib when typed, and update _Incomplete aliases in stubs

[tool.stubtest]
skip = true # Django requires configured settings at runtime
1 change: 1 addition & 0 deletions stubs/django-import-export/import_export/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__: str
114 changes: 114 additions & 0 deletions stubs/django-import-export/import_export/admin.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
from _typeshed import Incomplete
from collections.abc import Callable
from logging import Logger
from typing import Any, TypeVar
from typing_extensions import TypeAlias, deprecated

from django.contrib import admin
from django.contrib.admin.helpers import ActionForm
from django.core.files import File
from django.db.models import Model, QuerySet
from django.forms import Form, Media
from django.http.request import HttpRequest
from django.http.response import HttpResponse
from django.template.response import TemplateResponse
from django.urls import URLPattern

from .formats.base_formats import Format
from .mixins import BaseExportMixin, BaseImportMixin
from .results import Result
from .tmp_storages import BaseStorage

Dataset: TypeAlias = Incomplete # tablib.Dataset
logger: Logger

_ModelT = TypeVar("_ModelT", bound=Model)

class ImportExportMixinBase:
base_change_list_template: str
change_list_template: str
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
def init_change_list_template(self) -> None: ...
def get_model_info(self) -> tuple[str, str]: ...
def changelist_view(self, request: HttpRequest, extra_context: dict[str, Any] | None = None) -> HttpResponse: ...

class ImportMixin(BaseImportMixin[_ModelT], ImportExportMixinBase):
import_export_change_list_template: str
import_template_name: str
import_form_class: type[Form] = ...
confirm_form_class: type[Form] = ...
from_encoding: str
skip_admin_log: bool | None
tmp_storage_class: str | type[BaseStorage]
def get_skip_admin_log(self) -> bool: ...
def get_tmp_storage_class(self) -> type[BaseStorage]: ...
def has_import_permission(self, request: HttpRequest) -> bool: ...
def get_urls(self) -> list[URLPattern]: ...
def process_import(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: ...
def process_dataset(
self,
dataset: Dataset,
confirm_form: Form,
request: HttpRequest,
*args: Any,
rollback_on_validation_errors: bool = False,
**kwargs: Any,
) -> Result: ...
def process_result(self, result: Result, request: HttpRequest) -> HttpResponse: ...
def generate_log_entries(self, result: Result, request: HttpRequest) -> None: ...
def add_success_message(self, result: Result, request: HttpRequest) -> None: ...
def get_import_context_data(self, **kwargs: Any) -> dict[str, Any]: ...
def get_context_data(self, **kwargs: Any) -> dict[str, Any]: ...
@deprecated("Use get_import_form_class instead")
def get_import_form(self) -> type[Form]: ...
@deprecated("Use get_confirm_form_class instead")
def get_confirm_import_form(self) -> type[Form]: ...
@deprecated("Use get_import_form_kwargs or get_confirm_form_kwargs")
def get_form_kwargs(self, form: Form, *args: Any, **kwargs: Any) -> dict[str, Any]: ...
def create_import_form(self, request: HttpRequest) -> Form: ...
def get_import_form_class(self, request: HttpRequest) -> type[Form]: ...
def get_import_form_kwargs(self, request: HttpRequest) -> dict[str, Any]: ...
def get_import_form_initial(self, request: HttpRequest) -> dict[str, Any]: ...
def create_confirm_form(self, request: HttpRequest, import_form: Form | None = None) -> Form: ...
def get_confirm_form_class(self, request: HttpRequest) -> type[Form]: ...
def get_confirm_form_kwargs(self, request: HttpRequest, import_form: Form | None = None) -> dict[str, Any]: ...
def get_confirm_form_initial(self, request: HttpRequest, import_form: Form | None) -> dict[str, Any]: ...
def get_import_data_kwargs(self, request: HttpRequest, *args: Any, **kwargs: Any) -> dict[str, Any]: ...
def write_to_tmp_storage(self, import_file: File[bytes], input_format: Format) -> BaseStorage: ...
def add_data_read_fail_error_to_form(self, form: Form, e: Exception) -> None: ...
def import_action(self, request: HttpRequest, *args: Any, **kwargs: Any) -> TemplateResponse: ...
def changelist_view(self, request: HttpRequest, extra_context: dict[str, Any] | None = None) -> HttpResponse: ...

class ExportMixin(BaseExportMixin[_ModelT], ImportExportMixinBase):
import_export_change_list_template: str | None
export_template_name: str
to_encoding: str | None
export_form_class: type[Form] = ...
def get_urls(self) -> list[URLPattern]: ...
def has_export_permission(self, request: HttpRequest) -> bool: ...
def get_export_queryset(self, request: HttpRequest) -> QuerySet[_ModelT]: ...
def get_export_data(self, file_format: Format, queryset: QuerySet[_ModelT], *args: Any, **kwargs: Any) -> str | bytes: ...
def get_export_context_data(self, **kwargs: Any) -> dict[str, Any]: ...
def get_context_data(self, **kwargs: Any) -> dict[str, Any]: ...
@deprecated("Use get_export_form_class or use the export_form_class attribute")
def get_export_form(self) -> Form: ...
def get_export_form_class(self) -> type[Form]: ...
def export_action(self, request: HttpRequest, *args: Any, **kwargs: Any) -> TemplateResponse: ...
def changelist_view(self, request: HttpRequest, extra_context: dict[str, Any] | None = None) -> HttpResponse: ...
def get_export_filename(self, request: HttpRequest, queryset: QuerySet[_ModelT], file_format: Format) -> str: ... # type: ignore[override]

class ImportExportMixin(ImportMixin[_ModelT], ExportMixin[_ModelT]):
import_export_change_list_template: str

class ImportExportModelAdmin(ImportExportMixin[_ModelT], admin.ModelAdmin[_ModelT]): ... # type: ignore[misc]

class ExportActionMixin(ExportMixin[_ModelT]):
action_form: type[ActionForm]
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
def export_admin_action(self, request: HttpRequest, queryset: QuerySet[_ModelT]): ...
def get_actions(self, request: HttpRequest) -> dict[str, tuple[Callable[..., str], str, str] | None]: ...
@property
def media(self) -> Media: ...

class ExportActionModelAdmin(ExportActionMixin[_ModelT], admin.ModelAdmin[_ModelT]): ... # type: ignore[misc]
class ImportExportActionModelAdmin(ImportMixin[_ModelT], ExportActionModelAdmin[_ModelT]): ... # type: ignore[misc]
2 changes: 2 additions & 0 deletions stubs/django-import-export/import_export/exceptions.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class ImportExportError(Exception): ...
class FieldError(ImportExportError): ...
34 changes: 34 additions & 0 deletions stubs/django-import-export/import_export/fields.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from collections.abc import Callable, Mapping
from typing import Any, ClassVar

from django.db.models import Model
from django.db.models.fields import NOT_PROVIDED

from .widgets import Widget

class Field:
empty_values: ClassVar[list[str | None]]
attribute: str | None
default: type[NOT_PROVIDED] | Callable[[], Any] | Any
column_name: str | None
widget: Widget
readonly: bool
saves_null_values: bool
dehydrate_method: str
m2m_add: bool
def __init__(
self,
attribute: str | None = None,
column_name: str | None = None,
widget: Widget | None = None,
default: type[NOT_PROVIDED] | Callable[[], Any] | Any = ...,
readonly: bool = False,
saves_null_values: bool = True,
dehydrate_method: str | None = None,
m2m_add: bool = False,
) -> None: ...
def clean(self, data: Mapping[str, Any], **kwargs: Any) -> Any: ...
def get_value(self, obj: Model) -> Any: ...
def save(self, obj: Model, data: Mapping[str, Any], is_m2m: bool = False, **kwargs: Any) -> None: ...
def export(self, obj: Model) -> str: ...
def get_dehydrate_method(self, field_name: str | None = None) -> str: ...
Empty file.
57 changes: 57 additions & 0 deletions stubs/django-import-export/import_export/formats/base_formats.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from _typeshed import Incomplete, ReadableBuffer
from typing import IO, Any, ClassVar
from typing_extensions import Self, TypeAlias

Dataset: TypeAlias = Incomplete # tablib.Dataset

class Format:
def get_title(self) -> type[Self]: ...
def create_dataset(self, in_stream: str | bytes | IO[Any]) -> Dataset: ...
def export_data(self, dataset: Dataset, **kwargs: Any) -> Any: ...
def is_binary(self) -> bool: ...
def get_read_mode(self) -> str: ...
def get_extension(self) -> str: ...
def get_content_type(self) -> str: ...
@classmethod
def is_available(cls) -> bool: ...
def can_import(self) -> bool: ...
def can_export(self) -> bool: ...

class TablibFormat(Format):
TABLIB_MODULE: ClassVar[str]
CONTENT_TYPE: ClassVar[str]
encoding: str | None
def __init__(self, encoding: str | None = None) -> None: ...
def get_format(self) -> type[Any]: ...
def get_title(self) -> str: ... # type: ignore[override]
def create_dataset(self, in_stream: str | bytes | IO[Any], **kwargs: Any) -> Dataset: ... # type: ignore[override]

class TextFormat(TablibFormat): ...

class CSV(TextFormat):
def export_data(self, dataset: Dataset, **kwargs: Any) -> str: ...

class JSON(TextFormat):
def export_data(self, dataset: Dataset, **kwargs: Any) -> str: ...

class YAML(TextFormat):
def export_data(self, dataset: Dataset, **kwargs: Any) -> str: ...

class TSV(TextFormat):
def export_data(self, dataset: Dataset, **kwargs: Any) -> str: ...

class ODS(TextFormat):
def export_data(self, dataset: Dataset, **kwargs: Any) -> bytes: ...

class HTML(TextFormat):
def export_data(self, dataset: Dataset, **kwargs: Any) -> str: ...

class XLS(TablibFormat):
def export_data(self, dataset: Dataset, **kwargs: Any) -> bytes: ...
def create_dataset(self, in_stream: bytes) -> Dataset: ... # type: ignore[override]

class XLSX(TablibFormat):
def export_data(self, dataset: Dataset, **kwargs: Any) -> bytes: ...
def create_dataset(self, in_stream: ReadableBuffer) -> Dataset: ... # type: ignore[override]

DEFAULT_FORMATS: list[type[Format]]
31 changes: 31 additions & 0 deletions stubs/django-import-export/import_export/forms.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from typing import Any

from django import forms
from django.contrib.admin.helpers import ActionForm

from .formats.base_formats import Format
from .resources import Resource

class ImportExportFormBase(forms.Form):
resource: forms.ChoiceField
def __init__(self, *args: Any, resources: list[type[Resource[Any]]] | None = None, **kwargs: Any) -> None: ...

class ImportForm(ImportExportFormBase):
import_file: forms.FileField
input_format: forms.ChoiceField
def __init__(self, import_formats: list[Format], *args: Any, **kwargs: Any) -> None: ...
@property
def media(self) -> forms.Media: ...

class ConfirmImportForm(forms.Form):
import_file_name: forms.CharField
original_file_name: forms.CharField
input_format: forms.CharField
resource: forms.CharField
def clean_import_file_name(self) -> str: ...

class ExportForm(ImportExportFormBase):
file_format: forms.ChoiceField
def __init__(self, formats: list[Format], *args: Any, **kwargs: Any) -> None: ...

def export_action_form_factory(formats: list[tuple[str, str]]) -> type[ActionForm]: ...
23 changes: 23 additions & 0 deletions stubs/django-import-export/import_export/instance_loaders.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from _typeshed import Incomplete
from typing import Any
from typing_extensions import TypeAlias

from django.db.models import Model, QuerySet

from .fields import Field
from .resources import Resource

Dataset: TypeAlias = Incomplete # tablib.Dataset

class BaseInstanceLoader:
resource: Resource[Any]
dataset: Dataset | None
def __init__(self, resource: Resource[Any], dataset: Dataset | None = None) -> None: ...
def get_instance(self, row: dict[str, Any]) -> Model | None: ...

class ModelInstanceLoader(BaseInstanceLoader):
def get_queryset(self) -> QuerySet[Any]: ...

class CachedInstanceLoader(ModelInstanceLoader):
pk_field: Field
all_instances: dict[Any, Model]
66 changes: 66 additions & 0 deletions stubs/django-import-export/import_export/mixins.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from _typeshed import Incomplete, SupportsGetItem
from logging import Logger
from typing import Any, Generic, TypeVar
from typing_extensions import TypeAlias

from django.db.models import Model, QuerySet
from django.forms import BaseForm, Form
from django.http.request import HttpRequest
from django.http.response import HttpResponse
from django.views.generic.edit import FormView

from .formats.base_formats import Format
from .resources import Resource

Dataset: TypeAlias = Incomplete # tablib.Dataset

logger: Logger

_ModelT = TypeVar("_ModelT", bound=Model)

class BaseImportExportMixin(Generic[_ModelT]):
resource_class: type[Resource[_ModelT]]
resource_classes: SupportsGetItem[int, type[Resource[_ModelT]]]
@property
def formats(self) -> list[type[Format]]: ...
@property
def export_formats(self) -> list[type[Format]]: ...
@property
def import_formats(self) -> list[type[Format]]: ...
def check_resource_classes(self, resource_classes: SupportsGetItem[int, type[Resource[_ModelT]]]) -> None: ...
def get_resource_classes(self) -> list[type[Resource[_ModelT]]]: ...
def get_resource_kwargs(self, request: HttpRequest, *args: Any, **kwargs: Any) -> dict[str, Any]: ...
def get_resource_index(self, form: Form) -> int: ...

class BaseImportMixin(BaseImportExportMixin[_ModelT]):
def get_import_resource_classes(self) -> list[type[Resource[_ModelT]]]: ...
def get_import_formats(self) -> list[Format]: ...
def get_import_resource_kwargs(self, request: HttpRequest, *args: Any, **kwargs: Any) -> dict[str, Any]: ...
def choose_import_resource_class(self, form: Form) -> type[Resource[_ModelT]]: ...

class BaseExportMixin(BaseImportExportMixin[_ModelT]):
model: Model
escape_exported_data: bool
escape_html: bool
escape_formulae: bool
@property
def should_escape_html(self) -> bool: ...
@property
def should_escape_formulae(self) -> bool: ...
def get_export_formats(self) -> list[Format]: ...
def get_export_resource_classes(self) -> list[Resource[_ModelT]]: ...
def choose_export_resource_class(self, form: Form) -> Resource[_ModelT]: ...
def get_export_resource_kwargs(self, request: HttpRequest, *args: Any, **kwargs: Any) -> dict[str, Any]: ...
def get_data_for_export(self, request: HttpRequest, queryset: QuerySet[_ModelT], *args: Any, **kwargs: Any) -> Dataset: ...
def get_export_filename(self, file_format: Format) -> str: ...

class ExportViewMixin(BaseExportMixin[_ModelT]):
form_class: type[BaseForm] = ...
def get_export_data(self, file_format: Format, queryset: QuerySet[_ModelT], *args: Any, **kwargs: Any) -> str | bytes: ...
def get_context_data(self, **kwargs: Any) -> dict[str, Any]: ...
def get_form_kwargs(self) -> dict[str, Any]: ...

_FormT = TypeVar("_FormT", bound=BaseForm)

class ExportViewFormMixin(ExportViewMixin[_ModelT], FormView[_FormT]): # type: ignore[misc]
def form_valid(self, form: _FormT) -> HttpResponse: ...
Loading

0 comments on commit eb8af63

Please sign in to comment.