Bump django-import-export to 4.3.4 (#13414)

This commit is contained in:
Victorien
2025-02-03 09:02:58 +01:00
committed by GitHub
parent 983fc03a9f
commit e26219d41f
17 changed files with 218 additions and 183 deletions

View File

@@ -1,14 +1,14 @@
from _typeshed import Incomplete
from collections.abc import Callable
from collections.abc import Callable, Sequence
from logging import Logger
from typing import Any, TypeVar
from typing import Any, Literal, 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.forms import Form
from django.http.request import HttpRequest
from django.http.response import HttpResponse
from django.template.response import TemplateResponse
@@ -38,33 +38,21 @@ class ImportMixin(BaseImportMixin[_ModelT], ImportExportMixinBase):
import_form_class: type[Form] = ...
confirm_form_class: type[Form] = ...
from_encoding: str
import_error_display: Sequence[Literal["message", "row", "traceback"]]
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 get_tmp_storage_class_kwargs(self) -> dict[str, Any]: ...
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_import(self, request: HttpRequest, **kwargs: Any) -> HttpResponse: ...
def process_dataset(self, dataset: Dataset, form: Form, request: HttpRequest, **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]: ...
@@ -73,42 +61,49 @@ class ImportMixin(BaseImportMixin[_ModelT], ImportExportMixinBase):
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 get_import_data_kwargs(self, **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 import_action(self, request: HttpRequest, **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
import_export_change_list_template: str
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_data(
self, file_format: Format, request: HttpRequest, queryset: QuerySet[_ModelT], **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 export_action(self, request: HttpRequest) -> TemplateResponse: ...
@deprecated(
"The 'get_valid_export_item_pks()' method is deprecated and will be removed in a future release. "
"Overwrite 'get_queryset()' or 'get_export_queryset()' instead."
)
def get_valid_export_item_pks(self, request: HttpRequest) -> list[str]: ...
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]
def init_request_context_data(self, request: HttpRequest, form: Form) -> dict[str, Any]: ...
class ImportExportMixin(ImportMixin[_ModelT], ExportMixin[_ModelT]):
import_export_change_list_template: str
class ImportExportMixin(ImportMixin[_ModelT], ExportMixin[_ModelT]): ...
class ImportExportModelAdmin(ImportExportMixin[_ModelT], admin.ModelAdmin[_ModelT]): ... # type: ignore[misc]
class ExportActionMixin(ExportMixin[_ModelT]):
change_form_template: str
show_change_form_export: bool
action_form: type[ActionForm]
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
def change_view(
self, request: HttpRequest, object_id: str, form_url: str = "", extra_context: dict[str, Any] | None = None
) -> HttpResponse: ...
def response_change(self, request: HttpRequest, obj: _ModelT) -> HttpResponse: ...
def export_admin_action(self, request: HttpRequest, queryset: QuerySet[_ModelT]) -> HttpResponse: ...
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]

View File

@@ -0,0 +1,12 @@
from _typeshed import StrPath
from typing import Any
from .formats.base_formats import Format
from .resources import ModelResource
def get_resource_class(model_or_resource_class: str) -> ModelResource[Any]: ...
MIME_TYPE_FORMAT_MAPPING: dict[str, type[Format]]
def get_format_class(format_name: str, file_name: StrPath, encoding: str | None = None) -> Format: ...
def get_default_format_names() -> str: ...

View File

@@ -0,0 +1,11 @@
import _typeshed
from logging import Logger
from typing import Any
logger: Logger
class DeclarativeMetaclass(type):
def __new__(cls: type[_typeshed.Self], name: str, bases: tuple[type[Any], ...], attrs: dict[str, Any]) -> _typeshed.Self: ...
class ModelDeclarativeMetaclass(DeclarativeMetaclass):
def __new__(cls: type[_typeshed.Self], name: str, bases: tuple[type[Any], ...], attrs: dict[str, Any]) -> _typeshed.Self: ...

View File

@@ -1,2 +1,11 @@
from typing import Any
class ImportExportError(Exception): ...
class FieldError(ImportExportError): ...
class WidgetError(ImportExportError): ...
class ImportError(ImportExportError):
error: Exception
number: int | None
row: dict[str, Any] | None
def __init__(self, error: Exception, number: int | None = None, row: dict[str, Any] | None = None) -> None: ...

View File

@@ -27,8 +27,8 @@ class Field:
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 clean(self, row: Mapping[str, Any], **kwargs: Any) -> Any: ...
def get_value(self, instance: Model) -> Any: ...
def save(self, instance: Model, row: Mapping[str, Any], is_m2m: bool = False, **kwargs: Any) -> None: ...
def export(self, instance: Model, **kwargs: Any) -> str: ...
def get_dehydrate_method(self, field_name: str | None = None) -> str: ...

View File

@@ -1,9 +1,12 @@
from _typeshed import Incomplete, ReadableBuffer
from logging import Logger
from typing import IO, Any, ClassVar
from typing_extensions import Self, TypeAlias
Dataset: TypeAlias = Incomplete # tablib.Dataset
logger: Logger
class Format:
def get_title(self) -> type[Self]: ...
def create_dataset(self, in_stream: str | bytes | IO[Any]) -> Dataset: ...
@@ -43,8 +46,7 @@ class TSV(TextFormat):
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 HTML(TextFormat): ...
class XLS(TablibFormat):
def export_data(self, dataset: Dataset, **kwargs: Any) -> bytes: ...
@@ -55,3 +57,4 @@ class XLSX(TablibFormat):
def create_dataset(self, in_stream: ReadableBuffer) -> Dataset: ... # type: ignore[override]
DEFAULT_FORMATS: list[type[Format]]
BINARY_FORMATS: list[type[Format]]

View File

@@ -1,31 +1,38 @@
from collections.abc import Iterable, Sequence
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
from .resources import ModelResource, Resource
class ImportExportFormBase(forms.Form):
resource: forms.ChoiceField
def __init__(self, *args: Any, resources: list[type[Resource[Any]]] | None = None, **kwargs: Any) -> None: ...
format: forms.ChoiceField
def __init__(
self, formats: list[type[Format]], 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: ...
field_order: Sequence[str]
@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: ...
export_items: forms.MultipleChoiceField
def export_action_form_factory(formats: list[tuple[str, str]]) -> type[ActionForm]: ...
class SelectableFieldsExportForm(ExportForm):
resources: Iterable[ModelResource[Any]]
is_selectable_fields_form: bool
resource_fields: dict[str, list[str]]
@staticmethod
def create_boolean_field_name(resource: ModelResource[Any], field_name: str) -> str: ...
def get_selected_resource(self) -> ModelResource[Any]: ...
def get_selected_resource_export_fields(self) -> list[str]: ...

View File

@@ -1,7 +1,7 @@
from _typeshed import Incomplete, SupportsGetItem
from logging import Logger
from typing import Any, Generic, TypeVar
from typing_extensions import TypeAlias
from typing_extensions import TypeAlias, deprecated
from django.db.models import Model, QuerySet
from django.forms import BaseForm, Form
@@ -19,7 +19,6 @@ 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]]: ...
@@ -28,39 +27,39 @@ class BaseImportExportMixin(Generic[_ModelT]):
@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_classes(self, request: HttpRequest) -> 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]]]: ...
skip_import_confirm: bool
def get_import_resource_classes(self, request: HttpRequest) -> 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]]: ...
def get_import_resource_kwargs(self, request: HttpRequest, **kwargs: Any) -> dict[str, Any]: ...
def choose_import_resource_class(self, form: Form, request: HttpRequest) -> type[Resource[_ModelT]]: ...
def is_skip_import_confirm_enabled(self) -> bool: ...
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: ...
skip_export_form: bool
skip_export_form_from_action: 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_resource_classes(self, request: HttpRequest) -> list[Resource[_ModelT]]: ...
def choose_export_resource_class(self, form: Form, request: HttpRequest) -> Resource[_ModelT]: ...
def get_export_resource_kwargs(self, request: HttpRequest, **kwargs: Any) -> dict[str, Any]: ...
def get_data_for_export(self, request: HttpRequest, queryset: QuerySet[_ModelT], **kwargs: Any) -> Dataset: ...
def get_export_filename(self, file_format: Format) -> str: ...
def is_skip_export_form_enabled(self) -> bool: ...
def is_skip_export_form_from_action_enabled(self) -> bool: ...
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_export_data(self, file_format: Format, queryset: QuerySet[_ModelT], **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)
@deprecated("ExportViewFormMixin is deprecated and will be removed in a future release.")
class ExportViewFormMixin(ExportViewMixin[_ModelT], FormView[_FormT]): # type: ignore[misc]
def form_valid(self, form: _FormT) -> HttpResponse: ...

View File

@@ -0,0 +1,32 @@
from collections.abc import Sequence
from typing import Any, Generic, TypeVar
from django.db.models import Model
from .instance_loaders import BaseInstanceLoader
_ModelT = TypeVar("_ModelT", bound=Model)
class ResourceOptions(Generic[_ModelT]):
model: _ModelT | str
fields: Sequence[str] | None
exclude: Sequence[str] | None
instance_loader_class: type[BaseInstanceLoader] | None
import_id_fields: Sequence[str]
export_order: Sequence[str] | None
import_order: Sequence[str] | None
widgets: dict[str, Any] | None
use_transactions: bool | None
skip_unchanged: bool
report_skipped: bool
clean_model_instances: bool
chunk_size: int | None
skip_diff: bool
skip_html_diff: bool
use_bulk: bool
batch_size: int
force_init_instance: bool
using_db: str | None
store_row_values: bool
store_instance: bool
use_natural_foreign_keys: bool

View File

@@ -6,49 +6,21 @@ from logging import Logger
from typing import Any, ClassVar, Generic, Literal, NoReturn, TypeVar, overload
from typing_extensions import TypeAlias, deprecated
from django.db.models import Field as DjangoField, ForeignObjectRel, Model, QuerySet
from django.db.models import Field as DjangoField, Model, QuerySet
from django.utils.safestring import SafeString
from .declarative import DeclarativeMetaclass, ModelDeclarativeMetaclass
from .fields import Field
from .instance_loaders import BaseInstanceLoader
from .options import ResourceOptions
from .results import Error, Result, RowResult
from .widgets import ForeignKeyWidget, ManyToManyWidget, Widget
Dataset: TypeAlias = _typeshed.Incomplete # tablib.Dataset
logger: Logger
@overload
def get_related_model(field: ForeignObjectRel) -> Model: ...
@overload
def get_related_model(field: DjangoField[Any, Any]) -> Model | None: ...
def has_natural_foreign_key(model: Model) -> bool: ...
class ResourceOptions(Generic[_ModelT]):
model: _ModelT
fields: Sequence[str] | None
exclude: Sequence[str] | None
instance_loader_class: type[BaseInstanceLoader] | None
import_id_fields: Sequence[str]
export_order: Sequence[str] | None
widgets: dict[str, Any] | None
use_transactions: bool | None
skip_unchanged: bool
report_skipped: bool
clean_model_instances: bool
chunk_size: int | None
skip_diff: bool
skip_html_diff: bool
use_bulk: bool
batch_size: int
force_init_instance: bool
using_db: str | None
store_row_values: bool
store_instance: bool
use_natural_foreign_keys: bool
class DeclarativeMetaclass(type):
def __new__(cls: type[_typeshed.Self], name: str, bases: tuple[type[Any], ...], attrs: dict[str, Any]) -> _typeshed.Self: ...
class Diff:
left: list[str]
right: list[str]
@@ -78,6 +50,7 @@ class Resource(Generic[_ModelT], metaclass=DeclarativeMetaclass):
def get_db_connection_name(self) -> str: ...
def get_use_transactions(self) -> bool: ...
def get_chunk_size(self) -> int: ...
@deprecated("The 'get_fields()' method is deprecated and will be removed in a future release.")
def get_fields(self, **kwargs: Any) -> list[Field]: ...
def get_field_name(self, field: Field) -> str: ...
def init_instance(self, row: dict[str, Any] | None = None) -> _ModelT: ...
@@ -105,56 +78,35 @@ class Resource(Generic[_ModelT], metaclass=DeclarativeMetaclass):
def validate_instance(
self, instance: _ModelT, import_validation_errors: dict[str, Any] | None = None, validate_unique: bool = True
) -> None: ...
def save_instance(
self, instance: _ModelT, is_create: bool, using_transactions: bool = True, dry_run: bool = False
) -> None: ...
def before_save_instance(self, instance: _ModelT, using_transactions: bool, dry_run: bool) -> None: ...
def after_save_instance(self, instance: _ModelT, using_transactions: bool, dry_run: bool) -> None: ...
def delete_instance(self, instance: _ModelT, using_transactions: bool = True, dry_run: bool = False) -> None: ...
def before_delete_instance(self, instance: _ModelT, dry_run: bool) -> None: ...
def after_delete_instance(self, instance: _ModelT, dry_run: bool) -> None: ...
def import_field(self, field: Field, obj: _ModelT, data: dict[str, Any], is_m2m: bool = False, **kwargs: Any) -> None: ...
# For all the definitions below (from `save_instance()` to `import_row()`), `**kwargs` should contain:
# dry_run: bool, use_transactions: bool, row_number: int, retain_instance_in_row_result: bool.
# Users are free to pass extra arguments in `import_data()`so PEP 728 can probably be leveraged here.
def save_instance(self, instance: _ModelT, is_create: bool, row: dict[str, Any], **kwargs: Any) -> None: ...
def do_instance_save(self, instance: _ModelT) -> None: ...
def before_save_instance(self, instance: _ModelT, row: dict[str, Any], **kwargs: Any) -> None: ...
def after_save_instance(self, instance: _ModelT, row: dict[str, Any], **kwargs: Any) -> None: ...
def delete_instance(self, instance: _ModelT, row: dict[str, Any], **kwargs: Any) -> None: ...
def before_delete_instance(self, instance: _ModelT, row: dict[str, Any], **kwargs: Any) -> None: ...
def after_delete_instance(self, instance: _ModelT, row: dict[str, Any], **kwargs: Any) -> None: ...
def import_field(self, field: Field, instance: _ModelT, row: dict[str, Any], is_m2m: bool = False, **kwargs: Any) -> None: ...
def get_import_fields(self) -> list[Field]: ...
def import_obj(self, obj: _ModelT, data: dict[str, Any], dry_run: bool, **kwargs: Any) -> None: ...
def save_m2m(self, obj: _ModelT, data: dict[str, Any], using_transactions: bool, dry_run: bool) -> None: ...
def import_instance(self, instance: _ModelT, row: dict[str, Any], **kwargs: Any) -> None: ...
def save_m2m(self, instance: _ModelT, row: dict[str, Any], **kwargs: Any) -> None: ...
def for_delete(self, row: dict[str, Any], instance: _ModelT) -> bool: ...
def skip_row(
self, instance: _ModelT, original: _ModelT, row: dict[str, Any], import_validation_errors: dict[str, Any] | None = None
) -> bool: ...
def get_diff_headers(self) -> list[str]: ...
def before_import(self, dataset: Dataset, using_transactions: bool, dry_run: bool, **kwargs: Any) -> None: ...
def after_import(self, dataset: Dataset, result: Result, using_transactions: bool, dry_run: bool, **kwargs: Any) -> None: ...
def before_import_row(self, row: dict[str, Any], row_number: int | None = None, **kwargs: Any) -> None: ...
def after_import_row(
self, row: dict[str, Any], row_result: RowResult, row_number: int | None = None, **kwargs: Any
) -> None: ...
def after_import_instance(self, instance: _ModelT, new: bool, row_number: int | None = None, **kwargs: Any) -> None: ...
def before_import(self, dataset: Dataset, **kwargs: Any) -> None: ...
def after_import(self, dataset: Dataset, result: Result, **kwargs: Any) -> None: ...
def before_import_row(self, row: dict[str, Any], **kwargs: Any) -> None: ...
def after_import_row(self, row: dict[str, Any], row_result: RowResult, **kwargs: Any) -> None: ...
def after_init_instance(self, instance: _ModelT, new: bool, row: dict[str, Any], **kwargs: Any) -> None: ...
@overload
def handle_import_error(self, result: Result, error: Exception, raise_errors: Literal[True]) -> NoReturn: ...
@overload
def handle_import_error(self, result: Result, error: Exception, raise_errors: Literal[False] = ...) -> None: ...
@overload
@deprecated("raise_errors argument is deprecated and will be removed in a future release.")
def import_row(
self,
row: dict[str, Any],
instance_loader: BaseInstanceLoader,
using_transactions: bool = True,
dry_run: bool = False,
*,
raise_errors: bool,
**kwargs: Any,
) -> RowResult: ...
@overload
def import_row(
self,
row: dict[str, Any],
instance_loader: BaseInstanceLoader,
using_transactions: bool = True,
dry_run: bool = False,
raise_errors: None = None,
**kwargs: Any,
) -> RowResult: ...
def import_row(self, row: dict[str, Any], instance_loader: BaseInstanceLoader, **kwargs: Any) -> RowResult: ...
def import_data(
self,
dataset: Dataset,
@@ -165,8 +117,6 @@ class Resource(Generic[_ModelT], metaclass=DeclarativeMetaclass):
rollback_on_validation_errors: bool = False,
**kwargs: Any,
) -> Result: ...
@overload
@deprecated("rollback_on_validation_errors argument is deprecated and will be removed in a future release.")
def import_data_inner(
self,
dataset: Dataset,
@@ -174,35 +124,21 @@ class Resource(Generic[_ModelT], metaclass=DeclarativeMetaclass):
raise_errors: bool,
using_transactions: bool,
collect_failed_rows: bool,
rollback_on_validation_errors: bool,
**kwargs: Any,
) -> Result: ...
@overload
def import_data_inner(
self,
dataset: Dataset,
dry_run: bool,
raise_errors: bool,
using_transactions: bool,
collect_failed_rows: bool,
rollback_on_validation_errors: None = None,
**kwargs: Any,
) -> Result: ...
def get_import_order(self) -> tuple[str, ...]: ...
def get_export_order(self) -> tuple[str, ...]: ...
def before_export(self, queryset: QuerySet[_ModelT], *args: Any, **kwargs: Any) -> None: ...
def after_export(self, queryset: QuerySet[_ModelT], data: Dataset, *args: Any, **kwargs: Any) -> None: ...
def filter_export(self, queryset: QuerySet[_ModelT], *args: Any, **kwargs: Any) -> QuerySet[_ModelT]: ...
def export_field(self, field: Field, obj: _ModelT) -> str: ...
def get_export_fields(self) -> list[Field]: ...
def export_resource(self, obj: _ModelT) -> list[str]: ...
def get_export_headers(self) -> list[str]: ...
def before_export(self, queryset: QuerySet[_ModelT], **kwargs: Any) -> None: ...
def after_export(self, queryset: QuerySet[_ModelT], dataset: Dataset, **kwargs: Any) -> None: ...
def filter_export(self, queryset: QuerySet[_ModelT], **kwargs: Any) -> QuerySet[_ModelT]: ...
def export_field(self, field: Field, instance: _ModelT, **kwargs: Any) -> str: ...
def get_export_fields(self, selected_fields: Sequence[str] | None = None) -> list[Field]: ...
def export_resource(self, instance: _ModelT, selected_fields: Sequence[str] | None = None, **kwargs: Any) -> list[str]: ...
def get_export_headers(self, selected_fields: Sequence[str] | None = None) -> list[str]: ...
def get_user_visible_headers(self) -> list[str]: ...
def get_user_visible_fields(self) -> list[str]: ...
def iter_queryset(self, queryset: QuerySet[_ModelT]) -> Iterator[_ModelT]: ...
def export(self, *args: Any, queryset: QuerySet[_ModelT] | None = None, **kwargs: Any) -> Dataset: ...
class ModelDeclarativeMetaclass(DeclarativeMetaclass):
def __new__(cls: type[_typeshed.Self], name: str, bases: tuple[type[Any], ...], attrs: dict[str, Any]) -> _typeshed.Self: ...
def export(self, queryset: QuerySet[_ModelT] | None = None, **kwargs: Any) -> Dataset: ...
class ModelResource(Resource[_ModelT], metaclass=ModelDeclarativeMetaclass):
DEFAULT_RESOURCE_FIELD: ClassVar[type[Field]] = ...
@@ -214,12 +150,12 @@ class ModelResource(Resource[_ModelT], metaclass=ModelDeclarativeMetaclass):
@classmethod
def widget_from_django_field(cls, f: DjangoField[Any, Any], default: type[Widget] = ...) -> type[Widget]: ...
@classmethod
def widget_kwargs_for_field(self, field_name: str) -> dict[str, Any]: ...
def widget_kwargs_for_field(cls, field_name: str, django_field: DjangoField[Any, Any]) -> dict[str, Any]: ...
@classmethod
def field_from_django_field(cls, field_name: str, django_field: DjangoField[Any, Any], readonly: bool) -> Field: ...
def get_queryset(self) -> QuerySet[_ModelT]: ...
def init_instance(self, row: dict[str, Any] | None = None) -> _ModelT: ...
def after_import(self, dataset: Dataset, result: Result, using_transactions: bool, dry_run: bool, **kwargs: Any) -> None: ...
def after_import(self, dataset: Dataset, result: Result, **kwargs: Any) -> None: ...
@classmethod
def get_display_name(cls) -> str: ...

View File

@@ -1,6 +1,7 @@
from _typeshed import Incomplete
from collections import OrderedDict
from collections.abc import Iterator
from functools import cached_property
from typing import Any, ClassVar, Literal
from typing_extensions import TypeAlias
@@ -11,9 +12,11 @@ Dataset: TypeAlias = Incomplete # tablib.Dataset
class Error:
error: Exception
traceback: str
row: dict[str, Any]
def __init__(self, error: Exception, traceback: str | None = None, row: dict[str, Any] | None = None) -> None: ...
number: int | None
def __init__(self, error: Exception, row: dict[str, Any] | None = None, number: int | None = None) -> None: ...
@cached_property
def traceback(self) -> str: ...
_ImportType: TypeAlias = Literal["update", "new", "delete", "skip", "error", "invalid"]
@@ -34,9 +37,20 @@ class RowResult:
object_repr: str | None
instance: Model
original: Model
new_record: bool | None
def __init__(self) -> None: ...
def add_instance_info(self, instance: Model) -> None: ...
def is_update(self) -> bool: ...
def is_new(self) -> bool: ...
def is_delete(self) -> bool: ...
def is_skip(self) -> bool: ...
def is_error(self) -> bool: ...
def is_invalid(self) -> bool: ...
def is_valid(self) -> bool: ...
class ErrorRow:
number: int
errors: list[Error]
def __init__(self, number: int, errors: list[Error]) -> None: ...
class InvalidRow:
number: int
@@ -56,6 +70,7 @@ class Result:
diff_headers: list[str]
rows: list[RowResult]
invalid_rows: list[InvalidRow]
error_rows: list[ErrorRow]
failed_dataset: Dataset
totals: OrderedDict[_ImportType, int]
total_rows: int
@@ -66,6 +81,7 @@ class Result:
def add_dataset_headers(self, headers: list[str] | None) -> None: ...
def append_failed_row(self, row: dict[str, Any], error: Exception) -> None: ...
def append_invalid_row(self, number: int, row: dict[str, Any], validation_error: ValidationError) -> None: ...
def append_error_row(self, number: int, row: dict[str, Any], errors: list[Error]) -> None: ...
def increment_row_result_total(self, row_result: RowResult) -> None: ...
def row_errors(self) -> list[tuple[int, Any]]: ...
def has_errors(self) -> bool: ...

View File

@@ -1,11 +1,9 @@
from collections.abc import Callable
from types import TracebackType
from typing import Any, TypeVar
from typing import Any, overload
from django.db.models import Field as DjangoField, ForeignObjectRel, Model
from django.db.transaction import Atomic
_C = TypeVar("_C", bound=Callable[..., Any])
class atomic_if_using_transaction:
using_transactions: bool
context_manager: Atomic
@@ -15,4 +13,7 @@ class atomic_if_using_transaction:
self, exc_type: type[BaseException] | None, exc_value: BaseException | None, exc_tb: TracebackType | None
) -> None: ...
def original(method: _C) -> _C: ...
@overload
def get_related_model(field: ForeignObjectRel) -> Model: ...
@overload
def get_related_model(field: DjangoField[Any, Any]) -> Model | None: ...

View File

@@ -1,52 +1,56 @@
from collections.abc import Mapping
from datetime import datetime
from typing import Any, ClassVar, Generic, TypeVar
from typing import Any, ClassVar, Generic, TypeVar, overload
from typing_extensions import deprecated
from django.db.models import Model, QuerySet
def format_datetime(value: datetime, datetime_format: str) -> str: ...
class Widget:
coerce_to_string: bool
def __init__(self, coerce_to_string: bool = True) -> None: ...
def clean(self, value: Any, row: Mapping[str, Any] | None = None, **kwargs: Any) -> Any: ...
def render(self, value: Any, obj: Model | None = None) -> Any: ...
@overload
@deprecated("The 'obj' parameter is deprecated and will be removed in a future release.")
def render(self, value: Any, obj: Model, **kwargs: Any) -> Any: ...
@overload
def render(self, value: Any, obj: None = None, **kwargs: Any) -> Any: ...
class NumberWidget(Widget):
coerce_to_string: bool
def __init__(self, coerce_to_string: bool = False) -> None: ...
def is_empty(self, value: Any) -> bool: ...
def render(self, value: Any, obj: Model | None = None) -> Any: ...
class FloatWidget(NumberWidget): ...
class IntegerWidget(NumberWidget): ...
class DecimalWidget(NumberWidget): ...
class CharWidget(Widget):
coerce_to_string: bool
allow_blank: bool
def __init__(self, coerce_to_string: bool = False, allow_blank: bool = False) -> None: ...
def __init__(self, coerce_to_string: bool = True, allow_blank: bool = True) -> None: ...
class BooleanWidget(Widget):
TRUE_VALUES: ClassVar[list[str | int | bool]]
FALSE_VALUES: ClassVar[list[str | int | bool]]
NULL_VALUES: ClassVar[list[str | None]]
def __init__(self, coerce_to_string: bool = True) -> None: ...
class DateWidget(Widget):
formats: tuple[str, ...]
def __init__(self, format: str | None = None) -> None: ...
def __init__(self, format: str | None = None, coerce_to_string: bool = True) -> None: ...
class DateTimeWidget(Widget):
formats: tuple[str, ...]
def __init__(self, format: str | None = None) -> None: ...
def __init__(self, format: str | None = None, coerce_to_string: bool = True) -> None: ...
class TimeWidget(Widget):
formats: tuple[str, ...]
def __init__(self, format: str | None = None) -> None: ...
def __init__(self, format: str | None = None, coerce_to_string: bool = True) -> None: ...
class DurationWidget(Widget): ...
class SimpleArrayWidget(Widget):
separator: str
def __init__(self, separator: str | None = None) -> None: ...
def __init__(self, separator: str | None = None, coerce_to_string: bool = True) -> None: ...
class JSONWidget(Widget): ...
@@ -55,9 +59,13 @@ _ModelT = TypeVar("_ModelT", bound=Model)
class ForeignKeyWidget(Widget, Generic[_ModelT]):
model: _ModelT
field: str
key_is_id: bool
use_natural_foreign_keys: bool
def __init__(self, model: _ModelT, field: str = "pk", use_natural_foreign_keys: bool = False, **kwargs: Any) -> None: ...
def __init__(
self, model: _ModelT, field: str = "pk", use_natural_foreign_keys: bool = False, key_is_id: bool = False, **kwargs: Any
) -> None: ...
def get_queryset(self, value: Any, row: Mapping[str, Any], *args: Any, **kwargs: Any) -> QuerySet[_ModelT]: ...
def get_lookup_kwargs(self, value: Any, row: Mapping[str, Any] | None = None, **kwargs: Any) -> dict[str, Any]: ...
class ManyToManyWidget(Widget, Generic[_ModelT]):
model: _ModelT

View File

@@ -0,0 +1,3 @@
from django.core.management.base import BaseCommand
class Command(BaseCommand): ...

View File

@@ -0,0 +1,3 @@
from django.core.management.base import BaseCommand
class Command(BaseCommand): ...