From a0e86f2aba484bf9b76ab0dae219141e1f2b3b95 Mon Sep 17 00:00:00 2001 From: Denis Kislinskiy Date: Wed, 23 Mar 2022 12:57:42 +0700 Subject: [PATCH 01/93] fix TypeError: NoneType takes no arguments issues #36 --- import_export_celery/models/exportjob.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/import_export_celery/models/exportjob.py b/import_export_celery/models/exportjob.py index 7fa2efa..26f6eb5 100644 --- a/import_export_celery/models/exportjob.py +++ b/import_export_celery/models/exportjob.py @@ -23,6 +23,7 @@ from django.conf import settings from django.contrib.contenttypes.models import ContentType from django.db import models +from django.db import transaction from django.dispatch import receiver from django.db.models.signals import post_save @@ -131,4 +132,4 @@ def exportjob_post_save(sender, instance, **kwargs): if instance.resource and not instance.processing_initiated: instance.processing_initiated = timezone.now() instance.save() - run_export_job.delay(instance.pk) + transaction.on_commit(lambda: run_export_job.delay(instance.pk)) From 883eb555949a7c585d8dafc2099d9fabbe5929a2 Mon Sep 17 00:00:00 2001 From: dk Date: Thu, 24 Mar 2022 08:27:13 +0700 Subject: [PATCH 02/93] black reformat --- import_export_celery/models/exportjob.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/import_export_celery/models/exportjob.py b/import_export_celery/models/exportjob.py index 26f6eb5..8ac7631 100644 --- a/import_export_celery/models/exportjob.py +++ b/import_export_celery/models/exportjob.py @@ -20,7 +20,6 @@ from author.decorators import with_author -from django.conf import settings from django.contrib.contenttypes.models import ContentType from django.db import models from django.db import transaction @@ -132,4 +131,4 @@ def exportjob_post_save(sender, instance, **kwargs): if instance.resource and not instance.processing_initiated: instance.processing_initiated = timezone.now() instance.save() - transaction.on_commit(lambda: run_export_job.delay(instance.pk)) + transaction.on_commit(lambda: run_export_job.delay(instance.pk)) From 618b38216dcd9f6e24a3d212df8cabbd1dd0b1d4 Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Mon, 28 Mar 2022 17:06:05 +0100 Subject: [PATCH 03/93] Add apps file to avoid underscores in admin app label. --- import_export_celery/apps.py | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 import_export_celery/apps.py diff --git a/import_export_celery/apps.py b/import_export_celery/apps.py new file mode 100644 index 0000000..424f3c0 --- /dev/null +++ b/import_export_celery/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig +from django.utils.translation import gettext_lazy as _ + + +class ImportExportCeleryConfig(AppConfig): + name = 'import_export_celery' + verbose_name = _("Import Export Celery") From a4716ea0055b0c8cafad2de4e137bab356b3491a Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Mon, 28 Mar 2022 20:43:36 +0100 Subject: [PATCH 04/93] Load celery model choices in the form, not the model. Fix #52 --- import_export_celery/admin.py | 4 ++++ import_export_celery/models/importjob.py | 4 +--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/import_export_celery/admin.py b/import_export_celery/admin.py index 04f0d05..2dc4b73 100644 --- a/import_export_celery/admin.py +++ b/import_export_celery/admin.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # Copyright (C) 2019 o.s. Auto*Mat from django import forms +from django.conf import settings from django.contrib import admin from django.core.cache import cache @@ -23,6 +24,9 @@ class Meta: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) + self.fields['model'].choices = [ + (x, x) for x in getattr(settings, "IMPORT_EXPORT_CELERY_MODELS", {}).keys() + ] self.fields["format"].widget = forms.Select( choices=self.instance.get_format_choices() ) diff --git a/import_export_celery/models/importjob.py b/import_export_celery/models/importjob.py index c5b6517..b8f976c 100644 --- a/import_export_celery/models/importjob.py +++ b/import_export_celery/models/importjob.py @@ -71,9 +71,7 @@ class ImportJob(models.Model): model = models.CharField( verbose_name=_("Name of model to import to"), max_length=160, - choices=[ - (x, x) for x in getattr(settings, "IMPORT_EXPORT_CELERY_MODELS", {}).keys() - ], + choices=[], ) job_status = models.CharField( From 28df6955804c681819f69af2c7039246a3e2931b Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Mon, 28 Mar 2022 21:06:22 +0100 Subject: [PATCH 05/93] Specify a choice field on the form to avoid a text input. --- import_export_celery/admin.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/import_export_celery/admin.py b/import_export_celery/admin.py index 2dc4b73..1661234 100644 --- a/import_export_celery/admin.py +++ b/import_export_celery/admin.py @@ -4,6 +4,7 @@ from django.conf import settings from django.contrib import admin from django.core.cache import cache +from django.utils.translation import gettext_lazy as _ from . import admin_actions, models @@ -18,6 +19,11 @@ def job_status_info(self, obj): class ImportJobForm(forms.ModelForm): + + model = forms.ChoiceField( + label=_("Name of model to import to") + ) + class Meta: model = models.ImportJob fields = "__all__" From e9f9dab8a05505a44eb9c0ec743cd80afeca647c Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Mon, 28 Mar 2022 22:05:29 +0100 Subject: [PATCH 06/93] Ran black. --- example/project/settings.py | 12 ++++-- example/winners/models.py | 7 ++- example/winners/urls.py | 6 +-- import_export_celery/admin.py | 6 +-- import_export_celery/admin_actions.py | 7 ++- import_export_celery/apps.py | 2 +- import_export_celery/models/exportjob.py | 27 ++++++++---- import_export_celery/models/importjob.py | 14 ++++-- import_export_celery/tasks.py | 5 ++- setup.py | 54 ++++++++++++------------ 10 files changed, 88 insertions(+), 52 deletions(-) diff --git a/example/project/settings.py b/example/project/settings.py index 16a1956..ca89a8a 100644 --- a/example/project/settings.py +++ b/example/project/settings.py @@ -97,9 +97,15 @@ { "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", }, - {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",}, - {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",}, - {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",}, + { + "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", + }, ] diff --git a/example/winners/models.py b/example/winners/models.py index be311e9..137708c 100644 --- a/example/winners/models.py +++ b/example/winners/models.py @@ -6,7 +6,12 @@ class Winner(models.Model): - name = models.CharField(max_length=80, null=False, blank=False, default="",) + name = models.CharField( + max_length=80, + null=False, + blank=False, + default="", + ) @classmethod def export_resource_classes(cls): diff --git a/example/winners/urls.py b/example/winners/urls.py index 65c9303..20e4cd9 100644 --- a/example/winners/urls.py +++ b/example/winners/urls.py @@ -19,6 +19,6 @@ from django.contrib import admin from django.views.generic import TemplateView -urlpatterns = [url(r"^admin/", admin.site.urls),] + static( - settings.MEDIA_URL, document_root=settings.MEDIA_ROOT -) +urlpatterns = [ + url(r"^admin/", admin.site.urls), +] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/import_export_celery/admin.py b/import_export_celery/admin.py index 1661234..0aa720c 100644 --- a/import_export_celery/admin.py +++ b/import_export_celery/admin.py @@ -20,9 +20,7 @@ def job_status_info(self, obj): class ImportJobForm(forms.ModelForm): - model = forms.ChoiceField( - label=_("Name of model to import to") - ) + model = forms.ChoiceField(label=_("Name of model to import to")) class Meta: model = models.ImportJob @@ -30,7 +28,7 @@ class Meta: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.fields['model'].choices = [ + self.fields["model"].choices = [ (x, x) for x in getattr(settings, "IMPORT_EXPORT_CELERY_MODELS", {}).keys() ] self.fields["format"].widget = forms.Select( diff --git a/import_export_celery/admin_actions.py b/import_export_celery/admin_actions.py index 8f7f4ed..76b3097 100644 --- a/import_export_celery/admin_actions.py +++ b/import_export_celery/admin_actions.py @@ -54,7 +54,12 @@ def create_export_job_action(modeladmin, request, queryset): site_of_origin=request.scheme + "://" + request.get_host(), ) rurl = reverse( - "admin:%s_%s_change" % (ej._meta.app_label, ej._meta.model_name,), args=[ej.pk], + "admin:%s_%s_change" + % ( + ej._meta.app_label, + ej._meta.model_name, + ), + args=[ej.pk], ) return redirect(rurl) diff --git a/import_export_celery/apps.py b/import_export_celery/apps.py index 424f3c0..26d5701 100644 --- a/import_export_celery/apps.py +++ b/import_export_celery/apps.py @@ -3,5 +3,5 @@ class ImportExportCeleryConfig(AppConfig): - name = 'import_export_celery' + name = "import_export_celery" verbose_name = _("Import Export Celery") diff --git a/import_export_celery/models/exportjob.py b/import_export_celery/models/exportjob.py index 8ac7631..94a866a 100644 --- a/import_export_celery/models/exportjob.py +++ b/import_export_celery/models/exportjob.py @@ -55,7 +55,9 @@ def __init__(self, *args, **kwargs): ) job_status = models.CharField( - verbose_name=_("Status of the job"), max_length=160, blank=True, + verbose_name=_("Status of the job"), + max_length=160, + blank=True, ) format = models.CharField( @@ -66,19 +68,24 @@ def __init__(self, *args, **kwargs): ) app_label = models.CharField( - verbose_name=_("App label of model to export from"), max_length=160, + verbose_name=_("App label of model to export from"), + max_length=160, ) model = models.CharField( - verbose_name=_("Name of model to export from"), max_length=160, + verbose_name=_("Name of model to export from"), + max_length=160, ) resource = models.CharField( - verbose_name=_("Resource to use when exporting"), max_length=255, default="", + verbose_name=_("Resource to use when exporting"), + max_length=255, + default="", ) queryset = models.TextField( - verbose_name=_("JSON list of pks to export"), null=False, + verbose_name=_("JSON list of pks to export"), + null=False, ) email_on_completion = models.BooleanField( @@ -86,7 +93,10 @@ def __init__(self, *args, **kwargs): default=True, ) - site_of_origin = models.TextField(max_length=255, default="",) + site_of_origin = models.TextField( + max_length=255, + default="", + ) def get_resource_class(self): if self.resource: @@ -99,7 +109,8 @@ def get_resource_class(self): def get_content_type(self): if not self._content_type: self._content_type = ContentType.objects.get( - app_label=self.app_label, model=self.model, + app_label=self.app_label, + model=self.model, ) return self._content_type @@ -118,7 +129,7 @@ def get_resource_choices(self): @staticmethod def get_format_choices(): - """ returns choices of available export formats """ + """returns choices of available export formats""" return [ (f.CONTENT_TYPE, f().get_title()) for f in DEFAULT_FORMATS diff --git a/import_export_celery/models/importjob.py b/import_export_celery/models/importjob.py index b8f976c..e8c3af1 100644 --- a/import_export_celery/models/importjob.py +++ b/import_export_celery/models/importjob.py @@ -56,7 +56,8 @@ class ImportJob(models.Model): ) format = models.CharField( - verbose_name=_("Format of file to be imported"), max_length=255, + verbose_name=_("Format of file to be imported"), + max_length=255, ) change_summary = models.FileField( @@ -66,7 +67,10 @@ class ImportJob(models.Model): null=True, ) - errors = models.TextField(default="", blank=True,) + errors = models.TextField( + default="", + blank=True, + ) model = models.CharField( verbose_name=_("Name of model to import to"), @@ -75,12 +79,14 @@ class ImportJob(models.Model): ) job_status = models.CharField( - verbose_name=_("Status of the job"), max_length=160, blank=True, + verbose_name=_("Status of the job"), + max_length=160, + blank=True, ) @staticmethod def get_format_choices(): - """ returns choices of available import formats """ + """returns choices of available import formats""" return [ (f.CONTENT_TYPE, f().get_title()) for f in DEFAULT_FORMATS diff --git a/import_export_celery/tasks.py b/import_export_celery/tasks.py index 873dc63..85a6fad 100644 --- a/import_export_celery/tasks.py +++ b/import_export_celery/tasks.py @@ -242,7 +242,10 @@ def export_resource(self, *args, **kwargs): link=export_job.site_of_origin + reverse( "admin:%s_%s_change" - % (export_job._meta.app_label, export_job._meta.model_name,), + % ( + export_job._meta.app_label, + export_job._meta.model_name, + ), args=[export_job.pk], ), ), diff --git a/setup.py b/setup.py index a7a48fa..26aa5a5 100644 --- a/setup.py +++ b/setup.py @@ -6,33 +6,35 @@ here = os.path.abspath(os.path.dirname(__file__)) import codecs -requires = ['Django', 'django-import-export', 'django-author'] +requires = ["Django", "django-import-export", "django-author"] -version = subprocess.check_output(['git','describe','--abbrev=0','--tags']).decode("utf-8") +version = subprocess.check_output(["git", "describe", "--abbrev=0", "--tags"]).decode( + "utf-8" +) setup( - name='django-import-export-celery', - version=version, - author='Timothy Hobbs', - author_email='timothy.hobbs@auto-mat.cz', - url='https://github.com/auto-mat/django-import-export-celery', - download_url="http://pypi.python.org/pypi/django-import-export-celery/", - description="Process long running django imports and exports in celery", - long_description=codecs.open( - os.path.join( - here, 'README.rst'), 'r', 'utf-8').read(), - license='License :: OSI Approved :: GNU Lesser General Public License v3.0 or later (LGPLv3.0+)', - install_requires=requires, - packages=find_packages(), - include_package_data=True, - zip_safe=False, - classifiers=['Topic :: Utilities', - 'Natural Language :: English', - 'Operating System :: OS Independent', - 'Intended Audience :: Developers', - 'Environment :: Web Environment', - 'Framework :: Django', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5'], + name="django-import-export-celery", + version=version, + author="Timothy Hobbs", + author_email="timothy.hobbs@auto-mat.cz", + url="https://github.com/auto-mat/django-import-export-celery", + download_url="http://pypi.python.org/pypi/django-import-export-celery/", + description="Process long running django imports and exports in celery", + long_description=codecs.open(os.path.join(here, "README.rst"), "r", "utf-8").read(), + license="License :: OSI Approved :: GNU Lesser General Public License v3.0 or later (LGPLv3.0+)", + install_requires=requires, + packages=find_packages(), + include_package_data=True, + zip_safe=False, + classifiers=[ + "Topic :: Utilities", + "Natural Language :: English", + "Operating System :: OS Independent", + "Intended Audience :: Developers", + "Environment :: Web Environment", + "Framework :: Django", + "Programming Language :: Python :: 3.3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + ], ) From d2fdeb07ec34de5c87d75bf7014af8038f81270e Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Mon, 28 Mar 2022 22:05:52 +0100 Subject: [PATCH 07/93] Added editorconfig and pre-commit black hook. --- .editorconfig | 23 +++++++++++++++++++++++ .pre-commit-config.yaml | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 .editorconfig create mode 100644 .pre-commit-config.yaml diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..e2ebaf9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,23 @@ +# editorconfig.org + +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.py] +max_line_length = 150 + +[*.{scss,js,html}] +max_line_length = 150 + +[*.rst] +max_line_length = 150 + +[*.yml] +indent_size = 2 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..4695bd1 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,33 @@ +default_language_version: + python: python3.7 + +repos: +#- repo: https://github.com/pre-commit/pre-commit-hooks +# rev: v4.1.0 +# hooks: +# - id: check-added-large-files +# - id: check-case-conflict +# - id: check-merge-conflict +# - id: end-of-file-fixer +# - id: trailing-whitespace +# +#- repo: https://github.com/asottile/pyupgrade +# rev: v2.31.1 +# hooks: +# - id: pyupgrade +# args: [--py37-plus] + +- repo: https://github.com/psf/black + rev: 22.3.0 + hooks: + - id: black + +#- repo: https://github.com/PyCQA/flake8 +# rev: 4.0.1 +# hooks: +# - id: flake8 +# additional_dependencies: +# - flake8-bugbear +# - flake8-comprehensions +# - flake8-tidy-imports +# - flake8-typing-imports From 09745def1a2578f9fbf62f296bbf026d2b8072b1 Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Mon, 28 Mar 2022 22:06:42 +0100 Subject: [PATCH 08/93] Added pyupgrade & ran it for 3.7+ --- .pre-commit-config.yaml | 12 ++++++------ example/project/celery.py | 2 -- example/winners/admin.py | 1 - import_export_celery/__init__.py | 1 - import_export_celery/admin.py | 1 - import_export_celery/models/__init__.py | 1 - import_export_celery/models/exportjob.py | 2 -- import_export_celery/models/importjob.py | 2 -- import_export_celery/tasks.py | 13 ++++++------- 9 files changed, 12 insertions(+), 23 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4695bd1..1dfc72e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,12 +10,12 @@ repos: # - id: check-merge-conflict # - id: end-of-file-fixer # - id: trailing-whitespace -# -#- repo: https://github.com/asottile/pyupgrade -# rev: v2.31.1 -# hooks: -# - id: pyupgrade -# args: [--py37-plus] + +- repo: https://github.com/asottile/pyupgrade + rev: v2.31.1 + hooks: + - id: pyupgrade + args: [--py37-plus] - repo: https://github.com/psf/black rev: 22.3.0 diff --git a/example/project/celery.py b/example/project/celery.py index 30eaa2d..41e393c 100644 --- a/example/project/celery.py +++ b/example/project/celery.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import os import sys diff --git a/example/winners/admin.py b/example/winners/admin.py index 9112d3b..9e7a117 100644 --- a/example/winners/admin.py +++ b/example/winners/admin.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (C) 2016 o.s. Auto*Mat from django.contrib import admin diff --git a/import_export_celery/__init__.py b/import_export_celery/__init__.py index 8b13789..e69de29 100644 --- a/import_export_celery/__init__.py +++ b/import_export_celery/__init__.py @@ -1 +0,0 @@ - diff --git a/import_export_celery/admin.py b/import_export_celery/admin.py index 0aa720c..52807c7 100644 --- a/import_export_celery/admin.py +++ b/import_export_celery/admin.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (C) 2019 o.s. Auto*Mat from django import forms from django.conf import settings diff --git a/import_export_celery/models/__init__.py b/import_export_celery/models/__init__.py index 727c613..55d1682 100644 --- a/import_export_celery/models/__init__.py +++ b/import_export_celery/models/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (C) 2019 o.s. Auto*Mat """Import all models.""" diff --git a/import_export_celery/models/exportjob.py b/import_export_celery/models/exportjob.py index 94a866a..b83439f 100644 --- a/import_export_celery/models/exportjob.py +++ b/import_export_celery/models/exportjob.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - # Copyright (C) 2019 o.s. Auto*Mat # # This program is free software; you can redistribute it and/or modify diff --git a/import_export_celery/models/importjob.py b/import_export_celery/models/importjob.py index e8c3af1..9663b76 100644 --- a/import_export_celery/models/importjob.py +++ b/import_export_celery/models/importjob.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - # Copyright (C) 2019 o.s. Auto*Mat # # This program is free software; you can redistribute it and/or modify diff --git a/import_export_celery/tasks.py b/import_export_celery/tasks.py index 85a6fad..6c49b14 100644 --- a/import_export_celery/tasks.py +++ b/import_export_celery/tasks.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Author: Timothy Hobbs hobbs.cz> from django.utils import timezone import os @@ -84,17 +83,17 @@ def before_import_row(self, row, **kwargs): change_job_status( import_job, "import", - "3/5 Importing row %s/%s" % (row_number, len(dataset)), + f"3/5 Importing row {row_number}/{len(dataset)}", dry_run, ) - return super(Resource, self).before_import_row(row, **kwargs) + return super().before_import_row(row, **kwargs) resource = Resource(import_job=import_job) result = resource.import_data(dataset, dry_run=dry_run) change_job_status(import_job, "import", "4/5 Generating import summary", dry_run) for error in result.base_errors: - import_job.errors += "\n%s\n%s\n" % (error.error, error.traceback) + import_job.errors += f"\n{error.error}\n{error.traceback}\n" for line, errors in result.row_errors(): for error in errors: import_job.errors += _("Line: %s - %s\n\t%s\n%s") % ( @@ -181,7 +180,7 @@ def before_import_row(self, row, **kwargs): @shared_task(bind=False) def run_import_job(pk, dry_run=True): - log.info("Importing %s dry-run %s" % (pk, dry_run)) + log.info(f"Importing {pk} dry-run {dry_run}") import_job = models.ImportJob.objects.get(pk=pk) try: _run_import_job(import_job, dry_run) @@ -211,10 +210,10 @@ def export_resource(self, *args, **kwargs): change_job_status( export_job, "export", - "Exporting row %s/%s" % (self.row_number, qs_len), + f"Exporting row {self.row_number}/{qs_len}", ) self.row_number += 1 - return super(Resource, self).export_resource(*args, **kwargs) + return super().export_resource(*args, **kwargs) resource = Resource(export_job=export_job) From 05627f8fa63f14029fda0c32e41a7cc85eae9be6 Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Mon, 28 Mar 2022 22:07:56 +0100 Subject: [PATCH 09/93] Added & ran pre-commit-hooks with useful checks --- .pre-commit-config.yaml | 16 ++++++++-------- README.rst | 4 +--- example/README.rst | 2 +- example/pyproject.toml | 2 +- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1dfc72e..d9f61bb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,14 +2,14 @@ default_language_version: python: python3.7 repos: -#- repo: https://github.com/pre-commit/pre-commit-hooks -# rev: v4.1.0 -# hooks: -# - id: check-added-large-files -# - id: check-case-conflict -# - id: check-merge-conflict -# - id: end-of-file-fixer -# - id: trailing-whitespace +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.1.0 + hooks: + - id: check-added-large-files + - id: check-case-conflict + - id: check-merge-conflict + - id: end-of-file-fixer + - id: trailing-whitespace - repo: https://github.com/asottile/pyupgrade rev: v2.31.1 diff --git a/README.rst b/README.rst index 4b9dab5..1e964a2 100644 --- a/README.rst +++ b/README.rst @@ -61,7 +61,7 @@ You will find an example django application that uses django-import-export-celer .. image:: screenshots/import_jobs.png -3. Create a new import job. There is an example import CSV file in the example/example-data directory. Select that file. Select csv as the file format. We'll be importing to the Winner's model table. +3. Create a new import job. There is an example import CSV file in the example/example-data directory. Select that file. Select csv as the file format. We'll be importing to the Winner's model table. .. image:: screenshots/new_import_job.png @@ -134,5 +134,3 @@ Performing exports with celery 5. You will receive an email when the export is done, click on the link in the email 6. Click on the link near the bottom of the page titled `Exported file`. - - diff --git a/example/README.rst b/example/README.rst index 36310c5..36d6c97 100644 --- a/example/README.rst +++ b/example/README.rst @@ -69,6 +69,6 @@ Actually run the server python manage.py runserver 0.0.0.0:8000 -The example app will be available from http://127.0.0.1:8001/admin +The example app will be available from http://127.0.0.1:8001/admin Note: parts of this example app were taken from the [djano-leaflet](https://github.com/makinacorpus/django-leaflet/tree/master/example) example app. diff --git a/example/pyproject.toml b/example/pyproject.toml index 513fccc..436a029 100644 --- a/example/pyproject.toml +++ b/example/pyproject.toml @@ -21,4 +21,4 @@ black = "^19.10b0" [build-system] requires = ["poetry>=0.12"] -build-backend = "poetry.masonry.api" \ No newline at end of file +build-backend = "poetry.masonry.api" From 14e50e682eb541e0d6dbb89370ada85caf5e544d Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Mon, 28 Mar 2022 22:16:20 +0100 Subject: [PATCH 10/93] Added & ran flake8 --- .pre-commit-config.yaml | 18 +++++++++--------- example/manage.py | 2 +- example/winners/models.py | 1 - example/winners/tests/test_admin.py | 5 +---- example/winners/urls.py | 5 ++--- import_export_celery/models/importjob.py | 3 +-- import_export_celery/tasks.py | 3 ++- setup.cfg | 2 +- setup.py | 4 ++-- 9 files changed, 19 insertions(+), 24 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d9f61bb..0e90cc9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,12 +22,12 @@ repos: hooks: - id: black -#- repo: https://github.com/PyCQA/flake8 -# rev: 4.0.1 -# hooks: -# - id: flake8 -# additional_dependencies: -# - flake8-bugbear -# - flake8-comprehensions -# - flake8-tidy-imports -# - flake8-typing-imports +- repo: https://github.com/PyCQA/flake8 + rev: 4.0.1 + hooks: + - id: flake8 + additional_dependencies: + - flake8-bugbear + - flake8-comprehensions + - flake8-tidy-imports + - flake8-typing-imports diff --git a/example/manage.py b/example/manage.py index df611ff..f78a6d2 100755 --- a/example/manage.py +++ b/example/manage.py @@ -13,7 +13,7 @@ # issue is really that Django is missing to avoid masking other # exceptions on Python 2. try: - import django + import django # noqa except ImportError: raise ImportError( "Couldn't import Django. Are you sure it's installed and " diff --git a/example/winners/models.py b/example/winners/models.py index 137708c..d3962e7 100644 --- a/example/winners/models.py +++ b/example/winners/models.py @@ -1,5 +1,4 @@ from django.db import models -from django.contrib.auth.models import User from import_export.resources import ModelResource from import_export.fields import Field diff --git a/example/winners/tests/test_admin.py b/example/winners/tests/test_admin.py index e739ade..5d2288d 100644 --- a/example/winners/tests/test_admin.py +++ b/example/winners/tests/test_admin.py @@ -1,16 +1,13 @@ -from django.contrib.auth.models import User from django.contrib.messages.storage.fallback import FallbackStorage from django_admin_smoke_tests import tests -from import_export_celery.models import ExportJob, ImportJob - class AdminSmokeTest(tests.AdminSiteSmokeTest): exclude_apps = [] fixtures = [] - def post_request(self, post_data={}, params=None): + def post_request(self, post_data=dict, params=None): request = self.factory.post("/", data=post_data) request.user = self.superuser request._dont_enforce_csrf_checks = True diff --git a/example/winners/urls.py b/example/winners/urls.py index 20e4cd9..620353e 100644 --- a/example/winners/urls.py +++ b/example/winners/urls.py @@ -14,11 +14,10 @@ 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ from django.conf import settings -from django.conf.urls import url from django.conf.urls.static import static from django.contrib import admin -from django.views.generic import TemplateView +from django.urls import path urlpatterns = [ - url(r"^admin/", admin.site.urls), + path("admin", admin.site.urls), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/import_export_celery/models/importjob.py b/import_export_celery/models/importjob.py index 9663b76..e337386 100644 --- a/import_export_celery/models/importjob.py +++ b/import_export_celery/models/importjob.py @@ -17,12 +17,11 @@ from author.decorators import with_author -from django.conf import settings from django.db import models, transaction from django.dispatch import receiver from django.db.models.signals import post_save -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from import_export.formats.base_formats import DEFAULT_FORMATS diff --git a/import_export_celery/tasks.py b/import_export_celery/tasks.py index 6c49b14..7548f54 100644 --- a/import_export_celery/tasks.py +++ b/import_export_celery/tasks.py @@ -52,7 +52,8 @@ def _run_import_job(import_job, dry_run=True): import_job.errors = "" model_config = ModelConfig(**importables[import_job.model]) import_format = get_format(import_job) - try: # Copied from https://github.com/django-import-export/django-import-export/blob/3c082f98afe7996e79f936418fced3094f141c26/import_export/admin.py#L260 sorry + # Copied from https://github.com/django-import-export/django-import-export/blob/3c082f98afe7996e79f936418fced3094f141c26/import_export/admin.py#L260 sorry # noqa + try: data = import_job.file.read() if not import_format.is_binary(): data = force_text(data, "utf8") diff --git a/setup.cfg b/setup.cfg index 987b3e5..406b63e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -23,4 +23,4 @@ exclude = *.xml max-complexity = 10 enable-extensions = import-order, blind-except -ignore = C000, W504 +ignore = C000, C416, C901, E731, W503, W504 diff --git a/setup.py b/setup.py index 26aa5a5..43a686a 100644 --- a/setup.py +++ b/setup.py @@ -1,10 +1,9 @@ +import codecs import os from setuptools import setup, find_packages -import sys import subprocess here = os.path.abspath(os.path.dirname(__file__)) -import codecs requires = ["Django", "django-import-export", "django-author"] @@ -21,6 +20,7 @@ download_url="http://pypi.python.org/pypi/django-import-export-celery/", description="Process long running django imports and exports in celery", long_description=codecs.open(os.path.join(here, "README.rst"), "r", "utf-8").read(), + long_description_content_type="text/x-rst", license="License :: OSI Approved :: GNU Lesser General Public License v3.0 or later (LGPLv3.0+)", install_requires=requires, packages=find_packages(), From 7161243eaaf8c0191d37ced73865b5de970dec25 Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Mon, 28 Mar 2022 22:36:47 +0100 Subject: [PATCH 11/93] Remove unnecessary choices from import job model. --- import_export_celery/models/importjob.py | 1 - 1 file changed, 1 deletion(-) diff --git a/import_export_celery/models/importjob.py b/import_export_celery/models/importjob.py index e337386..22d9717 100644 --- a/import_export_celery/models/importjob.py +++ b/import_export_celery/models/importjob.py @@ -72,7 +72,6 @@ class ImportJob(models.Model): model = models.CharField( verbose_name=_("Name of model to import to"), max_length=160, - choices=[], ) job_status = models.CharField( From 3bba5449ab2cef1f03811de3310ce4ca324778b1 Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Mon, 28 Mar 2022 22:56:27 +0100 Subject: [PATCH 12/93] Add github action for flake8 checks and more python testing for travis --- .github/workflows/linters.yml | 26 ++++++++++++++++++++++++++ .travis.yml | 5 ++++- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/linters.yml diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml new file mode 100644 index 0000000..2cc1b0c --- /dev/null +++ b/.github/workflows/linters.yml @@ -0,0 +1,26 @@ +name: Flake8 + +on: [push, pull_request] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + flake8: + name: flake8 + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: 3.9 + cache: 'pip' + - run: pip install --upgrade flake8 + - name: flake8 + uses: liskin/gh-problem-matcher-wrap@v1 + with: + linters: flake8 + run: flake8 diff --git a/.travis.yml b/.travis.yml index 82dcea6..efa0026 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,9 +10,12 @@ env: - SECRET_KEY="sadfjasasdfasdfsadfsadfsadfeq" matrix: - - DJANGO_VERSION="Django==3.1" + - DJANGO_VERSION="Django==3.2" python: - "3.7" + - "3.8" + - "3.9" + - "3.10" install: - pip install poetry - cd example From 0568578be9636a426dbb8d827734172d8961fb54 Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Mon, 28 Mar 2022 22:59:37 +0100 Subject: [PATCH 13/93] Remove python 3.10 from travis - not available --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index efa0026..89992ad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,8 +14,7 @@ env: python: - "3.7" - "3.8" - - "3.9" - - "3.10" + - "3.9" # python 3.10 not available install: - pip install poetry - cd example From 5de5236fb3fc2d023acd0344baba366842ef3558 Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Mon, 28 Mar 2022 23:32:09 +0100 Subject: [PATCH 14/93] Updated black to match pre-commit --- example/poetry.lock | 196 +++++++++++++++++++---------------------- example/pyproject.toml | 2 +- 2 files changed, 92 insertions(+), 106 deletions(-) diff --git a/example/poetry.lock b/example/poetry.lock index 257d678..fdb9872 100644 --- a/example/poetry.lock +++ b/example/poetry.lock @@ -9,14 +9,6 @@ python-versions = ">=3.6" [package.dependencies] vine = "5.0.0" -[[package]] -name = "appdirs" -version = "1.4.4" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" -optional = false -python-versions = "*" - [[package]] name = "asgiref" version = "3.4.1" @@ -31,20 +23,6 @@ typing-extensions = {version = "*", markers = "python_version < \"3.8\""} [package.extras] tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"] -[[package]] -name = "attrs" -version = "21.2.0" -description = "Classes Without Boilerplate" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"] -docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"] - [[package]] name = "billiard" version = "3.6.4.0" @@ -55,23 +33,26 @@ python-versions = "*" [[package]] name = "black" -version = "19.10b0" +version = "22.3.0" description = "The uncompromising code formatter." category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.6.2" [package.dependencies] -appdirs = "*" -attrs = ">=18.1.0" -click = ">=6.5" -pathspec = ">=0.6,<1" -regex = "*" -toml = ">=0.9.4" -typed-ast = ">=1.4.0" +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""} +typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} [package.extras] -d = ["aiohttp (>=3.3.2)", "aiohttp-cors"] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "cached-property" @@ -307,6 +288,14 @@ category = "main" optional = false python-versions = "*" +[[package]] +name = "mypy-extensions" +version = "0.4.3" +description = "Experimental type system extensions for programs checked with the mypy typechecker." +category = "dev" +optional = false +python-versions = "*" + [[package]] name = "odfpy" version = "1.4.1" @@ -337,6 +326,18 @@ category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +[[package]] +name = "platformdirs" +version = "2.5.1" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] +test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] + [[package]] name = "prompt-toolkit" version = "3.0.20" @@ -403,14 +404,6 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [package.extras] hiredis = ["hiredis (>=0.1.3)"] -[[package]] -name = "regex" -version = "2021.8.28" -description = "Alternative regular expression module, to replace re." -category = "dev" -optional = false -python-versions = "*" - [[package]] name = "setuptools-git" version = "1.2" @@ -437,11 +430,11 @@ python-versions = ">=3.5" [[package]] name = "tablib" -version = "3.0.0" +version = "3.2.0" description = "Format agnostic tabular data library (XLS, JSON, YAML, CSV)" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] markuppy = {version = "*", optional = true, markers = "extra == \"html\""} @@ -462,12 +455,12 @@ xlsx = ["openpyxl (>=2.6.0)"] yaml = ["pyyaml"] [[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" category = "dev" optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = ">=3.7" [[package]] name = "typed-ast" @@ -545,32 +538,45 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytes [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "ff6bc8b6226fe4cda9ac55e605e2f8e31a1d3d9ca1f9c9d1608b9a0f829ddb2c" +content-hash = "3803687c30191b8f372989a64507765e2f5ebe438ff55483db56e242d3a33488" [metadata.files] amqp = [ {file = "amqp-5.0.6-py3-none-any.whl", hash = "sha256:493a2ac6788ce270a2f6a765b017299f60c1998f5a8617908ee9be082f7300fb"}, {file = "amqp-5.0.6.tar.gz", hash = "sha256:03e16e94f2b34c31f8bf1206d8ddd3ccaa4c315f7f6a1879b7b1210d229568c2"}, ] -appdirs = [ - {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, - {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, -] asgiref = [ {file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"}, {file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"}, ] -attrs = [ - {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, - {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, -] billiard = [ {file = "billiard-3.6.4.0-py3-none-any.whl", hash = "sha256:87103ea78fa6ab4d5c751c4909bcff74617d985de7fa8b672cf8618afd5a875b"}, {file = "billiard-3.6.4.0.tar.gz", hash = "sha256:299de5a8da28a783d51b197d496bef4f1595dd023a93a4f59dde1886ae905547"}, ] black = [ - {file = "black-19.10b0-py36-none-any.whl", hash = "sha256:1b30e59be925fafc1ee4565e5e08abef6b03fe455102883820fe5ee2e4734e0b"}, - {file = "black-19.10b0.tar.gz", hash = "sha256:c2edb73a08e9e0e6f65a0e6af18b059b8b1cdd5bef997d7a0b181df93dc81539"}, + {file = "black-22.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09"}, + {file = "black-22.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb"}, + {file = "black-22.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a"}, + {file = "black-22.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968"}, + {file = "black-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d"}, + {file = "black-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cc1e1de68c8e5444e8f94c3670bb48a2beef0e91dddfd4fcc29595ebd90bb9ce"}, + {file = "black-22.3.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2fc92002d44746d3e7db7cf9313cf4452f43e9ea77a2c939defce3b10b5c82"}, + {file = "black-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:a6342964b43a99dbc72f72812bf88cad8f0217ae9acb47c0d4f141a6416d2d7b"}, + {file = "black-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:328efc0cc70ccb23429d6be184a15ce613f676bdfc85e5fe8ea2a9354b4e9015"}, + {file = "black-22.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06f9d8846f2340dfac80ceb20200ea5d1b3f181dd0556b47af4e8e0b24fa0a6b"}, + {file = "black-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4efa5fad66b903b4a5f96d91461d90b9507a812b3c5de657d544215bb7877a"}, + {file = "black-22.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8477ec6bbfe0312c128e74644ac8a02ca06bcdb8982d4ee06f209be28cdf163"}, + {file = "black-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:637a4014c63fbf42a692d22b55d8ad6968a946b4a6ebc385c5505d9625b6a464"}, + {file = "black-22.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:863714200ada56cbc366dc9ae5291ceb936573155f8bf8e9de92aef51f3ad0f0"}, + {file = "black-22.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10dbe6e6d2988049b4655b2b739f98785a884d4d6b85bc35133a8fb9a2233176"}, + {file = "black-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:cee3e11161dde1b2a33a904b850b0899e0424cc331b7295f2a9698e79f9a69a0"}, + {file = "black-22.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20"}, + {file = "black-22.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a"}, + {file = "black-22.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad"}, + {file = "black-22.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21"}, + {file = "black-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265"}, + {file = "black-22.3.0-py3-none-any.whl", hash = "sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72"}, + {file = "black-22.3.0.tar.gz", hash = "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79"}, ] cached-property = [ {file = "cached-property-1.5.2.tar.gz", hash = "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130"}, @@ -632,6 +638,10 @@ kombu = [ markuppy = [ {file = "MarkupPy-1.14.tar.gz", hash = "sha256:1adee2c0a542af378fe84548ff6f6b0168f3cb7f426b46961038a2bcfaad0d5f"}, ] +mypy-extensions = [ + {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, + {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, +] odfpy = [ {file = "odfpy-1.4.1-py2.7.egg", hash = "sha256:fc3b8d1bc098eba4a0fda865a76d9d1e577c4ceec771426bcb169a82c5e9dfe0"}, {file = "odfpy-1.4.1.tar.gz", hash = "sha256:db766a6e59c5103212f3cc92ec8dd50a0f3a02790233ed0b52148b70d3c438ec"}, @@ -644,12 +654,23 @@ pathspec = [ {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, ] +platformdirs = [ + {file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"}, + {file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"}, +] prompt-toolkit = [ {file = "prompt_toolkit-3.0.20-py3-none-any.whl", hash = "sha256:6076e46efae19b1e0ca1ec003ed37a933dc94b4d20f486235d436e64771dcd5c"}, {file = "prompt_toolkit-3.0.20.tar.gz", hash = "sha256:eb71d5a6b72ce6db177af4a7d4d7085b99756bf656d98ffcc4fecd36850eea6c"}, ] psycopg2-binary = [ {file = "psycopg2-binary-2.9.1.tar.gz", hash = "sha256:b0221ca5a9837e040ebf61f48899926b5783668b7807419e4adae8175a31f773"}, + {file = "psycopg2_binary-2.9.1-cp310-cp310-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:24b0b6688b9f31a911f2361fe818492650795c9e5d3a1bc647acbd7440142a4f"}, + {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:542875f62bc56e91c6eac05a0deadeae20e1730be4c6334d8f04c944fcd99759"}, + {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:661509f51531ec125e52357a489ea3806640d0ca37d9dada461ffc69ee1e7b6e"}, + {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:d92272c7c16e105788efe2cfa5d680f07e34e0c29b03c1908f8636f55d5f915a"}, + {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_24_ppc64le.whl", hash = "sha256:736b8797b58febabb85494142c627bd182b50d2a7ec65322983e71065ad3034c"}, + {file = "psycopg2_binary-2.9.1-cp310-cp310-win32.whl", hash = "sha256:ebccf1123e7ef66efc615a68295bf6fdba875a75d5bba10a05073202598085fc"}, + {file = "psycopg2_binary-2.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:1f6ca4a9068f5c5c57e744b4baa79f40e83e3746875cac3c45467b16326bab45"}, {file = "psycopg2_binary-2.9.1-cp36-cp36m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:c250a7ec489b652c892e4f0a5d122cc14c3780f9f643e1a326754aedf82d9a76"}, {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aef9aee84ec78af51107181d02fe8773b100b01c5dfde351184ad9223eab3698"}, {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:123c3fb684e9abfc47218d3784c7b4c47c8587951ea4dd5bc38b6636ac57f616"}, @@ -697,18 +718,26 @@ pyyaml = [ {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"}, {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"}, {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"}, + {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347"}, + {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541"}, {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"}, {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"}, {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"}, {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"}, + {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa"}, + {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"}, {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"}, {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"}, {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"}, {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"}, + {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247"}, + {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc"}, {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"}, {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"}, {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"}, {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"}, + {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122"}, + {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6"}, {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"}, {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"}, {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"}, @@ -717,49 +746,6 @@ redis = [ {file = "redis-3.5.3-py2.py3-none-any.whl", hash = "sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24"}, {file = "redis-3.5.3.tar.gz", hash = "sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2"}, ] -regex = [ - {file = "regex-2021.8.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9d05ad5367c90814099000442b2125535e9d77581855b9bee8780f1b41f2b1a2"}, - {file = "regex-2021.8.28-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3bf1bc02bc421047bfec3343729c4bbbea42605bcfd6d6bfe2c07ade8b12d2a"}, - {file = "regex-2021.8.28-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f6a808044faae658f546dd5f525e921de9fa409de7a5570865467f03a626fc0"}, - {file = "regex-2021.8.28-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a617593aeacc7a691cc4af4a4410031654f2909053bd8c8e7db837f179a630eb"}, - {file = "regex-2021.8.28-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79aef6b5cd41feff359acaf98e040844613ff5298d0d19c455b3d9ae0bc8c35a"}, - {file = "regex-2021.8.28-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0fc1f8f06977c2d4f5e3d3f0d4a08089be783973fc6b6e278bde01f0544ff308"}, - {file = "regex-2021.8.28-cp310-cp310-win32.whl", hash = "sha256:6eebf512aa90751d5ef6a7c2ac9d60113f32e86e5687326a50d7686e309f66ed"}, - {file = "regex-2021.8.28-cp310-cp310-win_amd64.whl", hash = "sha256:ac88856a8cbccfc14f1b2d0b829af354cc1743cb375e7f04251ae73b2af6adf8"}, - {file = "regex-2021.8.28-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c206587c83e795d417ed3adc8453a791f6d36b67c81416676cad053b4104152c"}, - {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8690ed94481f219a7a967c118abaf71ccc440f69acd583cab721b90eeedb77c"}, - {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:328a1fad67445550b982caa2a2a850da5989fd6595e858f02d04636e7f8b0b13"}, - {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c7cb4c512d2d3b0870e00fbbac2f291d4b4bf2634d59a31176a87afe2777c6f0"}, - {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66256b6391c057305e5ae9209941ef63c33a476b73772ca967d4a2df70520ec1"}, - {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8e44769068d33e0ea6ccdf4b84d80c5afffe5207aa4d1881a629cf0ef3ec398f"}, - {file = "regex-2021.8.28-cp36-cp36m-win32.whl", hash = "sha256:08d74bfaa4c7731b8dac0a992c63673a2782758f7cfad34cf9c1b9184f911354"}, - {file = "regex-2021.8.28-cp36-cp36m-win_amd64.whl", hash = "sha256:abb48494d88e8a82601af905143e0de838c776c1241d92021e9256d5515b3645"}, - {file = "regex-2021.8.28-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b4c220a1fe0d2c622493b0a1fd48f8f991998fb447d3cd368033a4b86cf1127a"}, - {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4a332404baa6665b54e5d283b4262f41f2103c255897084ec8f5487ce7b9e8e"}, - {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c61dcc1cf9fd165127a2853e2c31eb4fb961a4f26b394ac9fe5669c7a6592892"}, - {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ee329d0387b5b41a5dddbb6243a21cb7896587a651bebb957e2d2bb8b63c0791"}, - {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f60667673ff9c249709160529ab39667d1ae9fd38634e006bec95611f632e759"}, - {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b844fb09bd9936ed158ff9df0ab601e2045b316b17aa8b931857365ea8586906"}, - {file = "regex-2021.8.28-cp37-cp37m-win32.whl", hash = "sha256:4cde065ab33bcaab774d84096fae266d9301d1a2f5519d7bd58fc55274afbf7a"}, - {file = "regex-2021.8.28-cp37-cp37m-win_amd64.whl", hash = "sha256:1413b5022ed6ac0d504ba425ef02549a57d0f4276de58e3ab7e82437892704fc"}, - {file = "regex-2021.8.28-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ed4b50355b066796dacdd1cf538f2ce57275d001838f9b132fab80b75e8c84dd"}, - {file = "regex-2021.8.28-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28fc475f560d8f67cc8767b94db4c9440210f6958495aeae70fac8faec631797"}, - {file = "regex-2021.8.28-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdc178caebd0f338d57ae445ef8e9b737ddf8fbc3ea187603f65aec5b041248f"}, - {file = "regex-2021.8.28-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:999ad08220467b6ad4bd3dd34e65329dd5d0df9b31e47106105e407954965256"}, - {file = "regex-2021.8.28-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:808ee5834e06f57978da3e003ad9d6292de69d2bf6263662a1a8ae30788e080b"}, - {file = "regex-2021.8.28-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d5111d4c843d80202e62b4fdbb4920db1dcee4f9366d6b03294f45ed7b18b42e"}, - {file = "regex-2021.8.28-cp38-cp38-win32.whl", hash = "sha256:473858730ef6d6ff7f7d5f19452184cd0caa062a20047f6d6f3e135a4648865d"}, - {file = "regex-2021.8.28-cp38-cp38-win_amd64.whl", hash = "sha256:31a99a4796bf5aefc8351e98507b09e1b09115574f7c9dbb9cf2111f7220d2e2"}, - {file = "regex-2021.8.28-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:04f6b9749e335bb0d2f68c707f23bb1773c3fb6ecd10edf0f04df12a8920d468"}, - {file = "regex-2021.8.28-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b006628fe43aa69259ec04ca258d88ed19b64791693df59c422b607b6ece8bb"}, - {file = "regex-2021.8.28-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:121f4b3185feaade3f85f70294aef3f777199e9b5c0c0245c774ae884b110a2d"}, - {file = "regex-2021.8.28-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a577a21de2ef8059b58f79ff76a4da81c45a75fe0bfb09bc8b7bb4293fa18983"}, - {file = "regex-2021.8.28-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1743345e30917e8c574f273f51679c294effba6ad372db1967852f12c76759d8"}, - {file = "regex-2021.8.28-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e1e8406b895aba6caa63d9fd1b6b1700d7e4825f78ccb1e5260551d168db38ed"}, - {file = "regex-2021.8.28-cp39-cp39-win32.whl", hash = "sha256:ed283ab3a01d8b53de3a05bfdf4473ae24e43caee7dcb5584e86f3f3e5ab4374"}, - {file = "regex-2021.8.28-cp39-cp39-win_amd64.whl", hash = "sha256:610b690b406653c84b7cb6091facb3033500ee81089867ee7d59e675f9ca2b73"}, - {file = "regex-2021.8.28.tar.gz", hash = "sha256:f585cbbeecb35f35609edccb95efd95a3e35824cd7752b586503f7e6087303f1"}, -] setuptools-git = [ {file = "setuptools-git-1.2.tar.gz", hash = "sha256:ff64136da01aabba76ae88b050e7197918d8b2139ccbf6144e14d472b9c40445"}, {file = "setuptools_git-1.2-py2.py3-none-any.whl", hash = "sha256:e7764dccce7d97b4b5a330d7b966aac6f9ac026385743fd6cedad553f2494cfa"}, @@ -773,12 +759,12 @@ sqlparse = [ {file = "sqlparse-0.4.1.tar.gz", hash = "sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8"}, ] tablib = [ - {file = "tablib-3.0.0-py3-none-any.whl", hash = "sha256:41aa40981cddd7ec4d1fabeae7c38d271601b306386bd05b5c3bcae13e5aeb20"}, - {file = "tablib-3.0.0.tar.gz", hash = "sha256:f83cac08454f225a34a305daa20e2110d5e6335135d505f93bc66583a5f9c10d"}, + {file = "tablib-3.2.0-py3-none-any.whl", hash = "sha256:1ba12da7b0b17e33f5997fb1bc8ed560aae3535f5892ae5e5c01a056c47d4d78"}, + {file = "tablib-3.2.0.tar.gz", hash = "sha256:12d8686454c721de88d8ca5adf07e1f419ef6dbcecedf65e8950d4a329daf3a0"}, ] -toml = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +tomli = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] typed-ast = [ {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"}, diff --git a/example/pyproject.toml b/example/pyproject.toml index 436a029..dfd7f27 100644 --- a/example/pyproject.toml +++ b/example/pyproject.toml @@ -17,7 +17,7 @@ psycopg2-binary = "^2.8.4" [tool.poetry.dev-dependencies] django-admin-smoke-tests = "^0.3.0" pudb = "^2019.2" -black = "^19.10b0" +black = "^22.3.0" [build-system] requires = ["poetry>=0.12"] From ef6528b11eba571a07b214b1867c12e4fcad16d3 Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Mon, 28 Mar 2022 23:36:33 +0100 Subject: [PATCH 15/93] Revert change in smoke test, now with noqa --- example/winners/tests/test_admin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/winners/tests/test_admin.py b/example/winners/tests/test_admin.py index 5d2288d..939a652 100644 --- a/example/winners/tests/test_admin.py +++ b/example/winners/tests/test_admin.py @@ -7,7 +7,7 @@ class AdminSmokeTest(tests.AdminSiteSmokeTest): exclude_apps = [] fixtures = [] - def post_request(self, post_data=dict, params=None): + def post_request(self, post_data={}, params=None): # noqa request = self.factory.post("/", data=post_data) request.user = self.superuser request._dont_enforce_csrf_checks = True From 99c429aef19917b2983696f4e9697c614793a7fc Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Mon, 28 Mar 2022 23:42:30 +0100 Subject: [PATCH 16/93] Change travis distro for python 3.10 --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 89992ad..67bebcf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ +dist: focal sudo: false language: python env: @@ -14,7 +15,8 @@ env: python: - "3.7" - "3.8" - - "3.9" # python 3.10 not available + - "3.9" + - "3.10" install: - pip install poetry - cd example From 997b0d97a7f54c9716d211f392487c12ea09360a Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Mon, 28 Mar 2022 23:47:37 +0100 Subject: [PATCH 17/93] Update postgres port for focal distro --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 67bebcf..3f00613 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ env: - DATABASE_USER="postgres" - DATABASE_HOST="" - DATABASE_PASSWORD="" + - DATABASE_PORT=5433 - DJANGO_SETTINGS_MODULE="project.settings" - SECRET_KEY="sadfjasasdfasdfsadfsadfsadfeq" From 4cf747ac31ddc72717072e5f61b3e1f14413a37e Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Tue, 29 Mar 2022 00:06:41 +0100 Subject: [PATCH 18/93] Travis database user/port changes --- .travis.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3f00613..cc75a27 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,15 @@ dist: focal sudo: false language: python +services: + - postgresql env: global: - DATABASE_NAME="travis_ci" - - DATABASE_USER="postgres" + - DATABASE_USER="travis" + - DATABASE_PORT=5433 - DATABASE_HOST="" - DATABASE_PASSWORD="" - - DATABASE_PORT=5433 - DJANGO_SETTINGS_MODULE="project.settings" - SECRET_KEY="sadfjasasdfasdfsadfsadfsadfeq" @@ -31,7 +33,7 @@ script: after_script: - coveralls addons: - postgresql: "9.6" + postgresql: "12.2" # default focal version matrix: allow_failures: - env: DJANGO_VERSION='https://github.com/django/django/archive/master.tar.gz' From 013067674f81edf64457664c497c3573f1f7faa3 Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Tue, 29 Mar 2022 00:10:52 +0100 Subject: [PATCH 19/93] Revert move to ubuntu 20.04 --- .travis.yml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index cc75a27..d44624a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,10 @@ -dist: focal sudo: false language: python -services: - - postgresql env: global: - DATABASE_NAME="travis_ci" - - DATABASE_USER="travis" - - DATABASE_PORT=5433 + - DATABASE_USER="postgres" + - DATABASE_PORT=5432 - DATABASE_HOST="" - DATABASE_PASSWORD="" - DJANGO_SETTINGS_MODULE="project.settings" @@ -19,7 +16,7 @@ python: - "3.7" - "3.8" - "3.9" - - "3.10" +# - "3.10" install: - pip install poetry - cd example @@ -33,7 +30,7 @@ script: after_script: - coveralls addons: - postgresql: "12.2" # default focal version + postgresql: "9.6" matrix: allow_failures: - env: DJANGO_VERSION='https://github.com/django/django/archive/master.tar.gz' From a7f556bf3101acd6489e5fd6ff54e3290e4ccb40 Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Tue, 29 Mar 2022 00:19:18 +0100 Subject: [PATCH 20/93] Remove pip cache from github action --- .github/workflows/linters.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 2cc1b0c..43caacd 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -17,7 +17,6 @@ jobs: uses: actions/setup-python@v2 with: python-version: 3.9 - cache: 'pip' - run: pip install --upgrade flake8 - name: flake8 uses: liskin/gh-problem-matcher-wrap@v1 From e9ab6e0d8bfb37d67686eb62a7490b8526482ae0 Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Tue, 29 Mar 2022 00:20:08 +0100 Subject: [PATCH 21/93] Update python trove classifiers to match those tested against. --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 43a686a..e6abb9d 100644 --- a/setup.py +++ b/setup.py @@ -33,8 +33,8 @@ "Intended Audience :: Developers", "Environment :: Web Environment", "Framework :: Django", - "Programming Language :: Python :: 3.3", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", ], ) From 1ef2ae61f6546764786435387851a7155afd1a46 Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Tue, 29 Mar 2022 10:04:00 +0100 Subject: [PATCH 22/93] Added pypi workflows --- .github/workflows/publish-to-live-pypi.yml | 39 +++++++++++++++++++++ .github/workflows/publish-to-test-pypi.yml | 40 ++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 .github/workflows/publish-to-live-pypi.yml create mode 100644 .github/workflows/publish-to-test-pypi.yml diff --git a/.github/workflows/publish-to-live-pypi.yml b/.github/workflows/publish-to-live-pypi.yml new file mode 100644 index 0000000..1607f77 --- /dev/null +++ b/.github/workflows/publish-to-live-pypi.yml @@ -0,0 +1,39 @@ +name: Publish Python 🐍 distributions 📦 to pypi + +on: + release: + types: + - published + +jobs: + build-n-publish: + name: Build and publish Python 🐍 distributions 📦 to pypi + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Set up Python 3.9 + uses: actions/setup-python@v1 + with: + python-version: 3.9 + + - name: Install pypa/build + run: >- + python -m + pip install + build + --user + - name: Build a binary wheel and a source tarball + run: >- + python -m + build + --sdist + --wheel + --outdir dist/ + . + + - name: Publish distribution 📦 to PyPI + if: startsWith(github.ref, 'refs/tags') + uses: pypa/gh-action-pypi-publish@master + with: + user: __token__ + password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.github/workflows/publish-to-test-pypi.yml b/.github/workflows/publish-to-test-pypi.yml new file mode 100644 index 0000000..d590f48 --- /dev/null +++ b/.github/workflows/publish-to-test-pypi.yml @@ -0,0 +1,40 @@ +name: Publish Python 🐍 distributions 📦 to TestPyPI + +on: + push: + branches: + - master + +jobs: + build-n-publish: + name: Build and publish Python 🐍 distributions 📦 to TestPyPI + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Set up Python 3.9 + uses: actions/setup-python@v1 + with: + python-version: 3.9 + + - name: Install pypa/build + run: >- + python -m + pip install + build + --user + - name: Build a binary wheel and a source tarball + run: >- + python -m + build + --sdist + --wheel + --outdir dist/ + . + + - name: Publish distribution 📦 to Test PyPI + uses: pypa/gh-action-pypi-publish@master + with: + user: __token__ + password: ${{ secrets.TEST_PYPI_API_TOKEN }} + repository_url: https://test.pypi.org/legacy/ + skip_existing: true From 839e592f4b1b3682e10f1e33733da8d3cf551e1c Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Wed, 30 Mar 2022 21:20:10 +0100 Subject: [PATCH 23/93] Fix for dry_run when diff is skipped (#63) --- import_export_celery/tasks.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/import_export_celery/tasks.py b/import_export_celery/tasks.py index 7548f54..dbae463 100644 --- a/import_export_celery/tasks.py +++ b/import_export_celery/tasks.py @@ -91,6 +91,8 @@ def before_import_row(self, row, **kwargs): resource = Resource(import_job=import_job) + skip_diff = resource._meta.skip_diff or resource._meta.skip_html_diff + result = resource.import_data(dataset, dry_run=dry_run) change_job_status(import_job, "import", "4/5 Generating import summary", dry_run) for error in result.base_errors: @@ -112,7 +114,7 @@ def before_import_row(self, row, **kwargs): summary += "" summary += '' # TODO refactor the existing template so we can use it for this # https://github.com/django-import-export/django-import-export/blob/6575c3e1d89725701e918696fbc531aeb192a6f7/import_export/templates/admin/import_export/import.html - if not result.invalid_rows: + if not result.invalid_rows and not skip_diff: cols = lambda row: "
".join([field for field in row.diff]) summary += ( "
change_type" From 26683311483293f5f58dd8d89ff79c943d921cc5 Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Fri, 1 Apr 2022 22:34:30 +0200 Subject: [PATCH 24/93] Create SHOWCASE_AND_THANKS.md --- SHOWCASE_AND_THANKS.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 SHOWCASE_AND_THANKS.md diff --git a/SHOWCASE_AND_THANKS.md b/SHOWCASE_AND_THANKS.md new file mode 100644 index 0000000..2ddbfde --- /dev/null +++ b/SHOWCASE_AND_THANKS.md @@ -0,0 +1,12 @@ +User showcase and thankyous +---------------------------- + +Do you use `django-import-export-celery`? Do you want to promote your project or just say thanks? Place a pull request and get included in the showcase and thanks. + + + +[Do Práce na Kole](https://www.dopracenakole.cz/) (Open source on [github](https://github.com/auto-mat/do-prace-na-kole)) + +Do Práce na Kole is a month long bike to work challenge in the Czech Republic. It is run by the non profit [Auto-mat z.s.](https://auto-mat.cz). django-import-export-celery is used to import discount codes from our eshop and export lists of users for data-anaylsis using jupyter. + +Auto-mat z.s. also uses django-import-export-celery for its internal donor database [klub přatel](https://github.com/auto-mat/klub) (also open source). From 581b4adaa7f358b480faefb03f7b48f398c087f3 Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Fri, 1 Apr 2022 22:42:11 +0200 Subject: [PATCH 25/93] Update README.rst --- README.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.rst b/README.rst index 1e964a2..9ede2aa 100644 --- a/README.rst +++ b/README.rst @@ -134,3 +134,8 @@ Performing exports with celery 5. You will receive an email when the export is done, click on the link in the email 6. Click on the link near the bottom of the page titled `Exported file`. + +Credits +------- + +`django-import-export-celery` was developed by the Czech non-profit `auto*mat z.s. `_. From 0eba680a9c5cc36e61dcd101dc87bcfee9a949d5 Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Sat, 2 Apr 2022 00:43:01 +0100 Subject: [PATCH 26/93] Fix for git describe during the automated pypi builds --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index e6abb9d..4ab144e 100644 --- a/setup.py +++ b/setup.py @@ -7,9 +7,9 @@ requires = ["Django", "django-import-export", "django-author"] -version = subprocess.check_output(["git", "describe", "--abbrev=0", "--tags"]).decode( - "utf-8" -) +version = subprocess.check_output( + ["git", "describe", "--abbrev=0", "--tags", "--always"] +).decode("utf-8") setup( name="django-import-export-celery", From 2b75e2b28c3b7b9e4844ae7f08e585a091258898 Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sat, 2 Apr 2022 12:14:44 +0200 Subject: [PATCH 27/93] Update publish-to-test-pypi.yml --- .github/workflows/publish-to-test-pypi.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish-to-test-pypi.yml b/.github/workflows/publish-to-test-pypi.yml index d590f48..7fb6eb1 100644 --- a/.github/workflows/publish-to-test-pypi.yml +++ b/.github/workflows/publish-to-test-pypi.yml @@ -8,6 +8,7 @@ on: jobs: build-n-publish: name: Build and publish Python 🐍 distributions 📦 to TestPyPI + environment: pypi runs-on: ubuntu-latest steps: - uses: actions/checkout@master From 7f2c5ba6d2bd76127f358d19ed7b479fa8312368 Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sat, 2 Apr 2022 12:41:06 +0200 Subject: [PATCH 28/93] Update setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 4ab144e..34e8d26 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ version = subprocess.check_output( ["git", "describe", "--abbrev=0", "--tags", "--always"] -).decode("utf-8") +).decode("utf-8").strip() setup( name="django-import-export-celery", From 154ff83d8f1097eb11ba8d124d20dba9b591adcc Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sat, 2 Apr 2022 12:50:24 +0200 Subject: [PATCH 29/93] Update setup.py --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 34e8d26..8c19ab1 100644 --- a/setup.py +++ b/setup.py @@ -2,6 +2,7 @@ import os from setuptools import setup, find_packages import subprocess +import datetime here = os.path.abspath(os.path.dirname(__file__)) @@ -9,7 +10,7 @@ version = subprocess.check_output( ["git", "describe", "--abbrev=0", "--tags", "--always"] -).decode("utf-8").strip() +).decode("utf-8").strip() + ".dev" + datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S") setup( name="django-import-export-celery", From ea56fc6dd404517f449626a03afa09a4260e3cd0 Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sat, 2 Apr 2022 12:53:03 +0200 Subject: [PATCH 30/93] Update setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 8c19ab1..2231b3b 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ version = subprocess.check_output( ["git", "describe", "--abbrev=0", "--tags", "--always"] -).decode("utf-8").strip() + ".dev" + datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S") +).decode("utf-8").strip() + ".dev" + datetime.datetime.now().strftime("%Y%m%d%H%M%S") setup( name="django-import-export-celery", From 9ba068a817b4dc9f26806afbde30972ab2dc49d9 Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sat, 2 Apr 2022 13:02:28 +0200 Subject: [PATCH 31/93] Update setup.py --- setup.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 2231b3b..f64ad1b 100644 --- a/setup.py +++ b/setup.py @@ -9,8 +9,11 @@ requires = ["Django", "django-import-export", "django-author"] version = subprocess.check_output( - ["git", "describe", "--abbrev=0", "--tags", "--always"] -).decode("utf-8").strip() + ".dev" + datetime.datetime.now().strftime("%Y%m%d%H%M%S") + ["git", "describe", "--abbrev=0", "--tags"] +).decode("utf-8").strip() + +if not version: + version = "0.dev" + datetime.datetime.now().strftime("%Y%m%d%H%M%S") setup( name="django-import-export-celery", From 5b59dcf16632715e4b863dc5769f21352aa1d260 Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sat, 2 Apr 2022 13:12:34 +0200 Subject: [PATCH 32/93] Update setup.py --- setup.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index f64ad1b..df41556 100644 --- a/setup.py +++ b/setup.py @@ -8,11 +8,11 @@ requires = ["Django", "django-import-export", "django-author"] -version = subprocess.check_output( - ["git", "describe", "--abbrev=0", "--tags"] -).decode("utf-8").strip() - -if not version: +try: + version = subprocess.check_output( + ["git", "describe", "--abbrev=0", "--tags"] + ).decode("utf-8").strip() +except subprocess.CalledProcessError: version = "0.dev" + datetime.datetime.now().strftime("%Y%m%d%H%M%S") setup( From 98c4ea62e179a0abeeef94aaf018b4621bb5b163 Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sat, 2 Apr 2022 13:28:42 +0200 Subject: [PATCH 33/93] Update publish-to-test-pypi.yml --- .github/workflows/publish-to-test-pypi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-to-test-pypi.yml b/.github/workflows/publish-to-test-pypi.yml index 7fb6eb1..509eddc 100644 --- a/.github/workflows/publish-to-test-pypi.yml +++ b/.github/workflows/publish-to-test-pypi.yml @@ -8,7 +8,7 @@ on: jobs: build-n-publish: name: Build and publish Python 🐍 distributions 📦 to TestPyPI - environment: pypi + environment: pypi-test runs-on: ubuntu-latest steps: - uses: actions/checkout@master From 292254e9a806841b9cc3347bcd9096d2d2d00a47 Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sat, 2 Apr 2022 13:29:40 +0200 Subject: [PATCH 34/93] Update publish-to-live-pypi.yml --- .github/workflows/publish-to-live-pypi.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish-to-live-pypi.yml b/.github/workflows/publish-to-live-pypi.yml index 1607f77..61617c5 100644 --- a/.github/workflows/publish-to-live-pypi.yml +++ b/.github/workflows/publish-to-live-pypi.yml @@ -9,6 +9,7 @@ jobs: build-n-publish: name: Build and publish Python 🐍 distributions 📦 to pypi runs-on: ubuntu-latest + environment: pypi steps: - uses: actions/checkout@master - name: Set up Python 3.9 From cb40cbb0069dafe6defbf4fa5efd886efe234d92 Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sat, 2 Apr 2022 13:50:52 +0200 Subject: [PATCH 35/93] Add pypi badge to readme --- README.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.rst b/README.rst index 9ede2aa..92911a9 100644 --- a/README.rst +++ b/README.rst @@ -1,3 +1,6 @@ +.. image:: https://img.shields.io/pypi/v/django-import-export-celery.svg + :target: https://pypi.org/manage/project/django-import-export-celery/releases/ + django-import-export-celery: process slow django imports and exports in celery ============================================================================== From 9698a569ecc74b162652845bf0f9b344f6e04ce4 Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Sat, 2 Apr 2022 12:58:53 +0100 Subject: [PATCH 36/93] Checkout all history and tags. --- .github/workflows/publish-to-live-pypi.yml | 52 +++++++++++---------- .github/workflows/publish-to-test-pypi.yml | 54 +++++++++++----------- 2 files changed, 55 insertions(+), 51 deletions(-) diff --git a/.github/workflows/publish-to-live-pypi.yml b/.github/workflows/publish-to-live-pypi.yml index 61617c5..95ff909 100644 --- a/.github/workflows/publish-to-live-pypi.yml +++ b/.github/workflows/publish-to-live-pypi.yml @@ -11,30 +11,32 @@ jobs: runs-on: ubuntu-latest environment: pypi steps: - - uses: actions/checkout@master - - name: Set up Python 3.9 - uses: actions/setup-python@v1 - with: - python-version: 3.9 + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Set up Python 3.9 + uses: actions/setup-python@v3 + with: + python-version: 3.9 - - name: Install pypa/build - run: >- - python -m - pip install - build - --user - - name: Build a binary wheel and a source tarball - run: >- - python -m - build - --sdist - --wheel - --outdir dist/ - . + - name: Install pypa/build + run: >- + python -m + pip install + build + --user + - name: Build a binary wheel and a source tarball + run: >- + python -m + build + --sdist + --wheel + --outdir dist/ + . - - name: Publish distribution 📦 to PyPI - if: startsWith(github.ref, 'refs/tags') - uses: pypa/gh-action-pypi-publish@master - with: - user: __token__ - password: ${{ secrets.PYPI_API_TOKEN }} + - name: Publish distribution 📦 to PyPI + if: startsWith(github.ref, 'refs/tags') + uses: pypa/gh-action-pypi-publish@master + with: + user: __token__ + password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.github/workflows/publish-to-test-pypi.yml b/.github/workflows/publish-to-test-pypi.yml index 509eddc..f11b035 100644 --- a/.github/workflows/publish-to-test-pypi.yml +++ b/.github/workflows/publish-to-test-pypi.yml @@ -11,31 +11,33 @@ jobs: environment: pypi-test runs-on: ubuntu-latest steps: - - uses: actions/checkout@master - - name: Set up Python 3.9 - uses: actions/setup-python@v1 - with: - python-version: 3.9 + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Set up Python 3.9 + uses: actions/setup-python@v3 + with: + python-version: 3.9 - - name: Install pypa/build - run: >- - python -m - pip install - build - --user - - name: Build a binary wheel and a source tarball - run: >- - python -m - build - --sdist - --wheel - --outdir dist/ - . + - name: Install pypa/build + run: >- + python -m + pip install + build + --user + - name: Build a binary wheel and a source tarball + run: >- + python -m + build + --sdist + --wheel + --outdir dist/ + . - - name: Publish distribution 📦 to Test PyPI - uses: pypa/gh-action-pypi-publish@master - with: - user: __token__ - password: ${{ secrets.TEST_PYPI_API_TOKEN }} - repository_url: https://test.pypi.org/legacy/ - skip_existing: true + - name: Publish distribution 📦 to Test PyPI + uses: pypa/gh-action-pypi-publish@master + with: + user: __token__ + password: ${{ secrets.TEST_PYPI_API_TOKEN }} + repository_url: https://test.pypi.org/legacy/ + skip_existing: true From 4754b99dd27238cf2ede8eab24f1456afe43d636 Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sat, 2 Apr 2022 16:16:26 +0200 Subject: [PATCH 37/93] Header was wrong its LGPL3 --- import_export_celery/models/exportjob.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/import_export_celery/models/exportjob.py b/import_export_celery/models/exportjob.py index b83439f..33f9482 100644 --- a/import_export_celery/models/exportjob.py +++ b/import_export_celery/models/exportjob.py @@ -1,18 +1,4 @@ # Copyright (C) 2019 o.s. Auto*Mat -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA from django.utils import timezone import json From 7f1b2b2fda52f27e74a1a86fae5e8b67de5271aa Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sat, 2 Apr 2022 16:16:51 +0200 Subject: [PATCH 38/93] Header was wrong its LGPL3 --- import_export_celery/models/importjob.py | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/import_export_celery/models/importjob.py b/import_export_celery/models/importjob.py index 22d9717..057d192 100644 --- a/import_export_celery/models/importjob.py +++ b/import_export_celery/models/importjob.py @@ -1,18 +1,5 @@ # Copyright (C) 2019 o.s. Auto*Mat -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + from django.utils import timezone from author.decorators import with_author From d52a8b63793ef5edda425995402aef6c50706262 Mon Sep 17 00:00:00 2001 From: Mahmudul Hasan Date: Fri, 8 Apr 2022 21:25:05 +0600 Subject: [PATCH 39/93] Added queryset customisation for celery export job --- .gitignore | 1 + example/winners/models.py | 4 ++++ import_export_celery/models/exportjob.py | 6 ++++++ 3 files changed, 11 insertions(+) diff --git a/.gitignore b/.gitignore index b8fc03c..4c5c2a5 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ example/django-import-export-celery-export-jobs/ pipenv/ django_import_export_celery.egg-info/ db/ +.idea/ diff --git a/example/winners/models.py b/example/winners/models.py index d3962e7..0609d60 100644 --- a/example/winners/models.py +++ b/example/winners/models.py @@ -27,6 +27,10 @@ class WinnersResource(ModelResource): class Meta: model = Winner + def get_export_queryset(self): + """To customise the queryset of the model resource with annotation override""" + return self.Meta.model.objects.all() + class WinnersWithAllCapsResource(WinnersResource): name_all_caps = Field() diff --git a/import_export_celery/models/exportjob.py b/import_export_celery/models/exportjob.py index 33f9482..9007982 100644 --- a/import_export_celery/models/exportjob.py +++ b/import_export_celery/models/exportjob.py @@ -100,6 +100,12 @@ def get_content_type(self): def get_queryset(self): pks = json.loads(self.queryset) + # If customised queryset for the model exists + # then it'll apply filter on that otherwise it'll + # apply filter directly on the model. + resource_class = self.get_resource_class() + if hasattr(resource_class, "get_export_queryset"): + return resource_class().get_export_queryset().filter(pk__in=pks) return self.get_content_type().model_class().objects.filter(pk__in=pks) def get_resource_choices(self): From 1ecd38a85d5c86e10bc2176e8d4bdeeb81dcb7b8 Mon Sep 17 00:00:00 2001 From: Mahmudul Hasan Date: Sat, 9 Apr 2022 00:41:03 +0600 Subject: [PATCH 40/93] Documentation added for customising model queryset for celery export job --- README.rst | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 92911a9..31fafd5 100644 --- a/README.rst +++ b/README.rst @@ -121,7 +121,18 @@ As with imports, a fully configured example project can be found in the `example create_export_job_action, ) -3. Done! +3. To customise export queryset you need to add `get_export_queryset` to the `ModelResource`. + :: + + class WinnersResource(ModelResource): + class Meta: + model = Winner + + def get_export_queryset(self): + """To customise the queryset of the model resource with annotation override""" + return self.Meta.model.objects.annotate(device_type=Subquery(FCMDevice.objects.filter( + user=OuterRef("pk")).values("type")[:1]) +4. Done! Performing exports with celery ------------------------------ From 20073134f4e0b6dfb55de5ebce059270d06b31b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Apr 2022 22:32:22 +0000 Subject: [PATCH 41/93] Bump django from 3.2.7 to 3.2.13 in /example Bumps [django](https://github.com/django/django) from 3.2.7 to 3.2.13. - [Release notes](https://github.com/django/django/releases) - [Commits](https://github.com/django/django/compare/3.2.7...3.2.13) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- example/poetry.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/example/poetry.lock b/example/poetry.lock index fdb9872..21d441a 100644 --- a/example/poetry.lock +++ b/example/poetry.lock @@ -174,7 +174,7 @@ python-versions = ">=2.7" [[package]] name = "django" -version = "3.2.7" +version = "3.2.13" description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design." category = "main" optional = false @@ -430,7 +430,7 @@ python-versions = ">=3.5" [[package]] name = "tablib" -version = "3.2.0" +version = "3.2.1" description = "Format agnostic tabular data library (XLS, JSON, YAML, CSV)" category = "main" optional = false @@ -610,8 +610,8 @@ diff-match-patch = [ {file = "diff_match_patch-20200713-py3-none-any.whl", hash = "sha256:8bf9d9c4e059d917b5c6312bac0c137971a32815ddbda9c682b949f2986b4d34"}, ] django = [ - {file = "Django-3.2.7-py3-none-any.whl", hash = "sha256:e93c93565005b37ddebf2396b4dc4b6913c1838baa82efdfb79acedd5816c240"}, - {file = "Django-3.2.7.tar.gz", hash = "sha256:95b318319d6997bac3595517101ad9cc83fe5672ac498ba48d1a410f47afecd2"}, + {file = "Django-3.2.13-py3-none-any.whl", hash = "sha256:b896ca61edc079eb6bbaa15cf6071eb69d6aac08cce5211583cfb41515644fdf"}, + {file = "Django-3.2.13.tar.gz", hash = "sha256:6d93497a0a9bf6ba0e0b1a29cccdc40efbfc76297255b1309b3a884a688ec4b6"}, ] django-admin-smoke-tests = [ {file = "django-admin-smoke-tests-0.3.0.tar.gz", hash = "sha256:5dc35c61610d4e762bc21a6d2ba4599d67491ff5260e576e0454c14b341a2be9"}, @@ -759,8 +759,8 @@ sqlparse = [ {file = "sqlparse-0.4.1.tar.gz", hash = "sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8"}, ] tablib = [ - {file = "tablib-3.2.0-py3-none-any.whl", hash = "sha256:1ba12da7b0b17e33f5997fb1bc8ed560aae3535f5892ae5e5c01a056c47d4d78"}, - {file = "tablib-3.2.0.tar.gz", hash = "sha256:12d8686454c721de88d8ca5adf07e1f419ef6dbcecedf65e8950d4a329daf3a0"}, + {file = "tablib-3.2.1-py3-none-any.whl", hash = "sha256:870d7e688f738531a14937a055e8bba404fbc388e77d4d500b2c904075d1019c"}, + {file = "tablib-3.2.1.tar.gz", hash = "sha256:a57f2770b8c225febec1cb1e65012a69cf30dd28be810e0ff98d024768c7d0f1"}, ] tomli = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, From 2967833af9bf0f568902257a41513c685b4f96ea Mon Sep 17 00:00:00 2001 From: Franklin Bynum Date: Wed, 27 Apr 2022 18:30:06 -0500 Subject: [PATCH 42/93] Use gettext_lazy for Django 4 #67 --- import_export_celery/admin_actions.py | 2 +- import_export_celery/models/exportjob.py | 2 +- import_export_celery/tasks.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/import_export_celery/admin_actions.py b/import_export_celery/admin_actions.py index 76b3097..2c06434 100644 --- a/import_export_celery/admin_actions.py +++ b/import_export_celery/admin_actions.py @@ -2,7 +2,7 @@ import json from uuid import UUID -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext_lazy as _ from django.urls import reverse from django.shortcuts import redirect diff --git a/import_export_celery/models/exportjob.py b/import_export_celery/models/exportjob.py index 9007982..c7324c0 100644 --- a/import_export_celery/models/exportjob.py +++ b/import_export_celery/models/exportjob.py @@ -10,7 +10,7 @@ from django.dispatch import receiver from django.db.models.signals import post_save -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from import_export.formats.base_formats import DEFAULT_FORMATS diff --git a/import_export_celery/tasks.py b/import_export_celery/tasks.py index dbae463..35cfa4b 100644 --- a/import_export_celery/tasks.py +++ b/import_export_celery/tasks.py @@ -11,7 +11,7 @@ from django.urls import reverse from django.utils.encoding import force_text -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext_lazy as _ from import_export.formats.base_formats import DEFAULT_FORMATS From e9cd01b761b2716d37de7049df887f3e3f76a1a4 Mon Sep 17 00:00:00 2001 From: Franklin Bynum Date: Wed, 27 Apr 2022 19:07:03 -0500 Subject: [PATCH 43/93] Replace deprecated force_text with force_str --- import_export_celery/tasks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/import_export_celery/tasks.py b/import_export_celery/tasks.py index 35cfa4b..c7e9b93 100644 --- a/import_export_celery/tasks.py +++ b/import_export_celery/tasks.py @@ -10,7 +10,7 @@ from django.core.mail import send_mail from django.urls import reverse -from django.utils.encoding import force_text +from django.utils.encoding import force_str from django.utils.translation import gettext_lazy as _ from import_export.formats.base_formats import DEFAULT_FORMATS @@ -56,7 +56,7 @@ def _run_import_job(import_job, dry_run=True): try: data = import_job.file.read() if not import_format.is_binary(): - data = force_text(data, "utf8") + data = force_str(data, "utf8") dataset = import_format.create_dataset(data) except UnicodeDecodeError as e: import_job.errors += _("Imported file has a wrong encoding: %s" % e) + "\n" From f5d88718b3b63a6ddfbfaa29ac1bd329dd30befe Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Mon, 30 May 2022 17:46:43 +0000 Subject: [PATCH 44/93] Improve and document docker-compose development environment --- .gitignore | 2 +- Dockerfile | 3 ++- Makefile | 37 +++++++------------------------------ README.rst | 9 +++++++++ dev-entrypoint.sh | 3 +++ develop.sh | 4 ++++ docker-compose.yaml | 6 +++--- setup-dev-env.sh | 4 ++++ 8 files changed, 33 insertions(+), 35 deletions(-) create mode 100755 dev-entrypoint.sh create mode 100755 develop.sh create mode 100755 setup-dev-env.sh diff --git a/.gitignore b/.gitignore index 4c5c2a5..9fd409b 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,7 @@ dist/ example/django-import-export-celery-import-change-summaries/ example/django-import-export-celery-import-jobs/ example/django-import-export-celery-export-jobs/ -pipenv/ +pyenv/ django_import_export_celery.egg-info/ db/ .idea/ diff --git a/Dockerfile b/Dockerfile index 2892bd8..5cd24d7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,6 @@ FROM python:3.7 RUN pip3 install poetry celery RUN apt-get update ; apt-get install -yq python3-psycopg2 gdal-bin -RUN useradd test +ARG UID +RUN useradd test --uid $UID RUN chsh test -s /bin/bash diff --git a/Makefile b/Makefile index 459dfa2..01ff748 100644 --- a/Makefile +++ b/Makefile @@ -1,31 +1,8 @@ -VERSION = $(shell git describe --abbrev=0 --tags) -REPO_FILES ?= git ls-files -z | xargs --null -I '{}' find '{}' -type f -print0 -REPO_TXT_FILES ?= git ls-files -z | xargs --null -I '{}' find '{}' -type f -print0 | egrep -zZv '(png|svg)$$' +docker-compose: Dockerfile + mkdir -p pyenv + mkdir -p db + sudo docker-compose build --build-arg UID=$(shell id -u) + sudo docker-compose up -d web postgres + sudo docker exec -it django-import-export-celery_web_1 /proj/setup-dev-env.sh + sudo docker-compose down -packages: clean - python3 setup.py bdist_wheel - git archive --format=tar.gz $(VERSION) > dist/django-import-export-celery-$(VERSION).tar.gz - cd dist ; gpg --detach-sign -a *.whl - cd dist ; gpg --detach-sign -a *.tar.gz - -deploy-pypi: - twine upload dist/*.whl - twine upload dist/*.whl.asc - -deploy: deploy-pypi - echo Deployed - -clean: - rm -r dist ; exit 0 - rm -r django_import_export_celery.egg-info ; exit 0 - rm -r build ; exit 0 - -qa: qa-miscellaneous qa-https-everywhere - -qa-miscellaneous: - $(REPO_TXT_FILES) | grep -zZv 'setup.py$$' | xargs --null sed -i 's#LGPL\s*v3#LGPL-3.0#g;' - -qa-https-everywhere: - $(REPO_TXT_FILES) | xargs --null sed --regexp-extended --in-place 's#http(:\\?/\\?/)(momentjs\.com|overpass-turbo\.eu|www\.gnu\.org|stackoverflow\.com|(:?www\.)?openstreetmap\.(org|de)|nominatim\.openstreetmap\.org|taginfo\.openstreetmap\.org|wiki\.openstreetmap\.org|josm.openstreetmap.de|www.openstreetmap.org\\/copyright|github\.com|xkcd\.com|www\.heise\.de|www\.readthedocs\.org|askubuntu\.com|xpra\.org|docker\.com|linuxcontainers\.org|www\.ecma-international\.org|www\.w3\.org|example\.com|www\.example\.com)#https\1\2#g;' - $(REPO_TXT_FILES) | xargs --null sed -i 's#http://overpass-api\.de#https://overpass-api.de#g;' - $(REPO_TXT_FILES) | xargs --null sed --regexp-extended --in-place 's#http://(\w+\.wikipedia\.org)#https://\1#g;' diff --git a/README.rst b/README.rst index 31fafd5..1f9e8dd 100644 --- a/README.rst +++ b/README.rst @@ -149,6 +149,15 @@ Performing exports with celery 6. Click on the link near the bottom of the page titled `Exported file`. +For developers of this library +------------------------------ + +You can enter a preconfigured dev environment by first running `make` and then launching `./develop.sh` to get into a docker compose environment packed with **redis**, **celery**, **postgres** and everything you need to run and test django-import-export-celery. + +Before submitting a PR please run `flake8` and (in the examples directory) `python3 manange.py test`. + +Please note, that you need to restart celery for changes to propogate to the workers. Do this with `docker-compose down celery`, `docker-compose up celery`. + Credits ------- diff --git a/dev-entrypoint.sh b/dev-entrypoint.sh new file mode 100755 index 0000000..f1ce914 --- /dev/null +++ b/dev-entrypoint.sh @@ -0,0 +1,3 @@ +#!/bin/bash +cd example +poetry shell diff --git a/develop.sh b/develop.sh new file mode 100755 index 0000000..86897e3 --- /dev/null +++ b/develop.sh @@ -0,0 +1,4 @@ +#!/bin/bash +docker-compose down +docker-compose up -d +exec docker exec -u test -it django-import-export-celery_web_1 bash --init-file "/proj/dev-entrypoint.sh" diff --git a/docker-compose.yaml b/docker-compose.yaml index 3b377a9..4b55d6e 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -14,10 +14,10 @@ services: user: test volumes: - ./:/proj/ - - ./pipenv:/home/test + - ./pyenv:/home/test celery: build: . - entrypoint: poetry run celery worker -A project.celery + entrypoint: poetry run celery -A project.celery worker links: - postgres - redis @@ -27,7 +27,7 @@ services: user: test volumes: - ./:/proj/ - - ./pipenv:/home/test + - ./pyenv:/home/test redis: image: redis postgres: diff --git a/setup-dev-env.sh b/setup-dev-env.sh new file mode 100755 index 0000000..58bd72f --- /dev/null +++ b/setup-dev-env.sh @@ -0,0 +1,4 @@ +#!/bin/bash +cd example +poetry install +poetry run python3 manage.py migrate From 34b319cdb9409abba400e75fd94ca2149258fb75 Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sun, 12 Jun 2022 13:04:52 +0200 Subject: [PATCH 45/93] Update README.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 1f9e8dd..3fccbe7 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,5 @@ .. image:: https://img.shields.io/pypi/v/django-import-export-celery.svg - :target: https://pypi.org/manage/project/django-import-export-celery/releases/ + :target: https://pypi.org/project/django-import-export-celery/#history django-import-export-celery: process slow django imports and exports in celery ============================================================================== From aaf4e47764274f943dfd9d4ef67cfd5f0920284d Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sun, 12 Jun 2022 14:11:54 +0200 Subject: [PATCH 46/93] Create CODE_OF_CONDUCT.md --- CODE_OF_CONDUCT.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..bb32606 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1 @@ +Please follow the spirit of [The PSF code of conduct](https://www.python.org/psf/conduct/) and try not to be nice. From 645283aab8734404fd18bc114a108b10388cefdd Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sun, 12 Jun 2022 19:18:06 +0000 Subject: [PATCH 47/93] Advertise commercial support --- README.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.rst b/README.rst index 3fccbe7..737d4be 100644 --- a/README.rst +++ b/README.rst @@ -158,6 +158,11 @@ Before submitting a PR please run `flake8` and (in the examples directory) `pyth Please note, that you need to restart celery for changes to propogate to the workers. Do this with `docker-compose down celery`, `docker-compose up celery`. +Comercial support +----------------- + +Comercial support is provided by [gradesta s.r.o](https://gradesta.com/support/). + Credits ------- From 272cbcb941243308be2b6301f489308073d9dc6e Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sun, 12 Jun 2022 19:18:39 +0000 Subject: [PATCH 48/93] Update README.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 737d4be..6aec0eb 100644 --- a/README.rst +++ b/README.rst @@ -161,7 +161,7 @@ Please note, that you need to restart celery for changes to propogate to the wor Comercial support ----------------- -Comercial support is provided by [gradesta s.r.o](https://gradesta.com/support/). +Comercial support is provided by `gradesta s.r.o `_. Credits ------- From 9cb6b206db233ac8943aa2e29a1ce23a4d3d0ac5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Aug 2022 16:04:55 +0000 Subject: [PATCH 49/93] Bump django from 3.2.13 to 3.2.15 in /example Bumps [django](https://github.com/django/django) from 3.2.13 to 3.2.15. - [Release notes](https://github.com/django/django/releases) - [Commits](https://github.com/django/django/compare/3.2.13...3.2.15) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- example/poetry.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/example/poetry.lock b/example/poetry.lock index 21d441a..9f691c2 100644 --- a/example/poetry.lock +++ b/example/poetry.lock @@ -49,10 +49,10 @@ typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implem typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} [package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] +jupyter = ["tokenize-rt (>=3.2.0)", "ipython (>=7.8.0)"] +d = ["aiohttp (>=3.7.4)"] +colorama = ["colorama (>=0.4.3)"] [[package]] name = "cached-property" @@ -174,7 +174,7 @@ python-versions = ">=2.7" [[package]] name = "django" -version = "3.2.13" +version = "3.2.15" description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design." category = "main" optional = false @@ -186,8 +186,8 @@ pytz = "*" sqlparse = ">=0.2.2" [package.extras] -argon2 = ["argon2-cffi (>=19.1.0)"] bcrypt = ["bcrypt"] +argon2 = ["argon2-cffi (>=19.1.0)"] [[package]] name = "django-admin-smoke-tests" @@ -511,9 +511,9 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" [package.extras] -build = ["wheel", "twine"] +test = ["pytest-cov", "pytest"] docs = ["sphinx"] -test = ["pytest", "pytest-cov"] +build = ["twine", "wheel"] [[package]] name = "xlwt" @@ -610,8 +610,8 @@ diff-match-patch = [ {file = "diff_match_patch-20200713-py3-none-any.whl", hash = "sha256:8bf9d9c4e059d917b5c6312bac0c137971a32815ddbda9c682b949f2986b4d34"}, ] django = [ - {file = "Django-3.2.13-py3-none-any.whl", hash = "sha256:b896ca61edc079eb6bbaa15cf6071eb69d6aac08cce5211583cfb41515644fdf"}, - {file = "Django-3.2.13.tar.gz", hash = "sha256:6d93497a0a9bf6ba0e0b1a29cccdc40efbfc76297255b1309b3a884a688ec4b6"}, + {file = "Django-3.2.15-py3-none-any.whl", hash = "sha256:115baf5049d5cf4163e43492cdc7139c306ed6d451e7d3571fe9612903903713"}, + {file = "Django-3.2.15.tar.gz", hash = "sha256:f71934b1a822f14a86c9ac9634053689279cd04ae69cb6ade4a59471b886582b"}, ] django-admin-smoke-tests = [ {file = "django-admin-smoke-tests-0.3.0.tar.gz", hash = "sha256:5dc35c61610d4e762bc21a6d2ba4599d67491ff5260e576e0454c14b341a2be9"}, From dfad399adba223f92dfd244ebf34321b7b45b3dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Dec 2022 18:46:01 +0000 Subject: [PATCH 50/93] Bump django from 3.2.15 to 3.2.16 in /example Bumps [django](https://github.com/django/django) from 3.2.15 to 3.2.16. - [Release notes](https://github.com/django/django/releases) - [Commits](https://github.com/django/django/compare/3.2.15...3.2.16) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- example/poetry.lock | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/example/poetry.lock b/example/poetry.lock index 9f691c2..4cf73af 100644 --- a/example/poetry.lock +++ b/example/poetry.lock @@ -21,7 +21,7 @@ python-versions = ">=3.6" typing-extensions = {version = "*", markers = "python_version < \"3.8\""} [package.extras] -tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"] +tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] [[package]] name = "billiard" @@ -49,10 +49,10 @@ typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implem typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} [package.extras] -uvloop = ["uvloop (>=0.15.2)"] -jupyter = ["tokenize-rt (>=3.2.0)", "ipython (>=7.8.0)"] -d = ["aiohttp (>=3.7.4)"] colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "cached-property" @@ -82,7 +82,7 @@ vine = ">=5.0.0,<6.0" [package.extras] arangodb = ["pyArango (>=1.3.2)"] auth = ["cryptography"] -azureblockblob = ["azure-storage (==0.36.0)", "azure-common (==1.1.5)", "azure-storage-common (==1.1.0)"] +azureblockblob = ["azure-common (==1.1.5)", "azure-storage (==0.36.0)", "azure-storage-common (==1.1.0)"] brotli = ["brotli (>=1.0.0)", "brotlipy (>=0.7.0)"] cassandra = ["cassandra-driver (<3.21.0)"] consul = ["python-consul"] @@ -174,7 +174,7 @@ python-versions = ">=2.7" [[package]] name = "django" -version = "3.2.15" +version = "3.2.16" description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design." category = "main" optional = false @@ -186,8 +186,8 @@ pytz = "*" sqlparse = ">=0.2.2" [package.extras] -bcrypt = ["bcrypt"] argon2 = ["argon2-cffi (>=19.1.0)"] +bcrypt = ["bcrypt"] [[package]] name = "django-admin-smoke-tests" @@ -246,9 +246,9 @@ typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} zipp = ">=0.5" [package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] +docs = ["jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "sphinx"] perf = ["ipython"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pep517", "pyfakefs", "pytest (>=4.6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy", "pytest-perf (>=0.9.2)"] [[package]] name = "kombu" @@ -511,9 +511,9 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" [package.extras] -test = ["pytest-cov", "pytest"] -docs = ["sphinx"] build = ["twine", "wheel"] +docs = ["sphinx"] +test = ["pytest", "pytest-cov"] [[package]] name = "xlwt" @@ -532,8 +532,8 @@ optional = false python-versions = ">=3.6" [package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] +docs = ["jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "sphinx"] +testing = ["func-timeout", "jaraco.itertools", "pytest (>=4.6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy"] [metadata] lock-version = "1.1" @@ -610,8 +610,8 @@ diff-match-patch = [ {file = "diff_match_patch-20200713-py3-none-any.whl", hash = "sha256:8bf9d9c4e059d917b5c6312bac0c137971a32815ddbda9c682b949f2986b4d34"}, ] django = [ - {file = "Django-3.2.15-py3-none-any.whl", hash = "sha256:115baf5049d5cf4163e43492cdc7139c306ed6d451e7d3571fe9612903903713"}, - {file = "Django-3.2.15.tar.gz", hash = "sha256:f71934b1a822f14a86c9ac9634053689279cd04ae69cb6ade4a59471b886582b"}, + {file = "Django-3.2.16-py3-none-any.whl", hash = "sha256:18ba8efa36b69cfcd4b670d0fa187c6fe7506596f0ababe580e16909bcdec121"}, + {file = "Django-3.2.16.tar.gz", hash = "sha256:3adc285124244724a394fa9b9839cc8cd116faf7d159554c43ecdaa8cdf0b94d"}, ] django-admin-smoke-tests = [ {file = "django-admin-smoke-tests-0.3.0.tar.gz", hash = "sha256:5dc35c61610d4e762bc21a6d2ba4599d67491ff5260e576e0454c14b341a2be9"}, @@ -643,7 +643,6 @@ mypy-extensions = [ {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] odfpy = [ - {file = "odfpy-1.4.1-py2.7.egg", hash = "sha256:fc3b8d1bc098eba4a0fda865a76d9d1e577c4ceec771426bcb169a82c5e9dfe0"}, {file = "odfpy-1.4.1.tar.gz", hash = "sha256:db766a6e59c5103212f3cc92ec8dd50a0f3a02790233ed0b52148b70d3c438ec"}, ] openpyxl = [ From a1e01f376a16b3f14d6b922ceeeb81978042edee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Feb 2023 19:36:22 +0000 Subject: [PATCH 51/93] Bump django from 3.2.16 to 3.2.18 in /example Bumps [django](https://github.com/django/django) from 3.2.16 to 3.2.18. - [Release notes](https://github.com/django/django/releases) - [Commits](https://github.com/django/django/compare/3.2.16...3.2.18) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- example/poetry.lock | 576 ++++++++++++++++++++++---------------------- 1 file changed, 288 insertions(+), 288 deletions(-) diff --git a/example/poetry.lock b/example/poetry.lock index 4cf73af..8ca7557 100644 --- a/example/poetry.lock +++ b/example/poetry.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Poetry and should not be changed by hand. + [[package]] name = "amqp" version = "5.0.6" @@ -5,6 +7,10 @@ description = "Low-level AMQP client for Python (fork of amqplib)." category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "amqp-5.0.6-py3-none-any.whl", hash = "sha256:493a2ac6788ce270a2f6a765b017299f60c1998f5a8617908ee9be082f7300fb"}, + {file = "amqp-5.0.6.tar.gz", hash = "sha256:03e16e94f2b34c31f8bf1206d8ddd3ccaa4c315f7f6a1879b7b1210d229568c2"}, +] [package.dependencies] vine = "5.0.0" @@ -16,6 +22,10 @@ description = "ASGI specs, helper code, and adapters" category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"}, + {file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"}, +] [package.dependencies] typing-extensions = {version = "*", markers = "python_version < \"3.8\""} @@ -30,6 +40,10 @@ description = "Python multiprocessing fork with improvements and bugfixes" category = "main" optional = false python-versions = "*" +files = [ + {file = "billiard-3.6.4.0-py3-none-any.whl", hash = "sha256:87103ea78fa6ab4d5c751c4909bcff74617d985de7fa8b672cf8618afd5a875b"}, + {file = "billiard-3.6.4.0.tar.gz", hash = "sha256:299de5a8da28a783d51b197d496bef4f1595dd023a93a4f59dde1886ae905547"}, +] [[package]] name = "black" @@ -38,6 +52,31 @@ description = "The uncompromising code formatter." category = "dev" optional = false python-versions = ">=3.6.2" +files = [ + {file = "black-22.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09"}, + {file = "black-22.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb"}, + {file = "black-22.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a"}, + {file = "black-22.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968"}, + {file = "black-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d"}, + {file = "black-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cc1e1de68c8e5444e8f94c3670bb48a2beef0e91dddfd4fcc29595ebd90bb9ce"}, + {file = "black-22.3.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2fc92002d44746d3e7db7cf9313cf4452f43e9ea77a2c939defce3b10b5c82"}, + {file = "black-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:a6342964b43a99dbc72f72812bf88cad8f0217ae9acb47c0d4f141a6416d2d7b"}, + {file = "black-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:328efc0cc70ccb23429d6be184a15ce613f676bdfc85e5fe8ea2a9354b4e9015"}, + {file = "black-22.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06f9d8846f2340dfac80ceb20200ea5d1b3f181dd0556b47af4e8e0b24fa0a6b"}, + {file = "black-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4efa5fad66b903b4a5f96d91461d90b9507a812b3c5de657d544215bb7877a"}, + {file = "black-22.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8477ec6bbfe0312c128e74644ac8a02ca06bcdb8982d4ee06f209be28cdf163"}, + {file = "black-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:637a4014c63fbf42a692d22b55d8ad6968a946b4a6ebc385c5505d9625b6a464"}, + {file = "black-22.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:863714200ada56cbc366dc9ae5291ceb936573155f8bf8e9de92aef51f3ad0f0"}, + {file = "black-22.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10dbe6e6d2988049b4655b2b739f98785a884d4d6b85bc35133a8fb9a2233176"}, + {file = "black-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:cee3e11161dde1b2a33a904b850b0899e0424cc331b7295f2a9698e79f9a69a0"}, + {file = "black-22.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20"}, + {file = "black-22.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a"}, + {file = "black-22.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad"}, + {file = "black-22.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21"}, + {file = "black-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265"}, + {file = "black-22.3.0-py3-none-any.whl", hash = "sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72"}, + {file = "black-22.3.0.tar.gz", hash = "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79"}, +] [package.dependencies] click = ">=8.0.0" @@ -61,6 +100,10 @@ description = "A decorator for caching properties in classes." category = "main" optional = false python-versions = "*" +files = [ + {file = "cached-property-1.5.2.tar.gz", hash = "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130"}, + {file = "cached_property-1.5.2-py2.py3-none-any.whl", hash = "sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0"}, +] [[package]] name = "celery" @@ -69,6 +112,10 @@ description = "Distributed Task Queue." category = "main" optional = false python-versions = ">=3.6," +files = [ + {file = "celery-5.0.2-py3-none-any.whl", hash = "sha256:930c3acd55349d028c4e7104a7d377729cbcca19d9fce470c17172d9e7f9a8b6"}, + {file = "celery-5.0.2.tar.gz", hash = "sha256:012c814967fe89e3f5d2cf49df2dba3de5f29253a7f4f2270e8fce6b901b4ebf"}, +] [package.dependencies] billiard = ">=3.6.3.0,<4.0" @@ -119,6 +166,10 @@ description = "Composable command line interface toolkit" category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "click-8.0.1-py3-none-any.whl", hash = "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"}, + {file = "click-8.0.1.tar.gz", hash = "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a"}, +] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} @@ -131,6 +182,9 @@ description = "Enable git-like did-you-mean feature in click." category = "main" optional = false python-versions = "*" +files = [ + {file = "click-didyoumean-0.0.3.tar.gz", hash = "sha256:112229485c9704ff51362fe34b2d4f0b12fc71cc20f6d2b3afabed4b8bfa6aeb"}, +] [package.dependencies] click = "*" @@ -142,6 +196,10 @@ description = "REPL plugin for Click" category = "main" optional = false python-versions = "*" +files = [ + {file = "click-repl-0.2.0.tar.gz", hash = "sha256:cd12f68d745bf6151210790540b4cb064c7b13e571bc64b6957d98d120dacfd8"}, + {file = "click_repl-0.2.0-py3-none-any.whl", hash = "sha256:94b3fbbc9406a236f176e0506524b2937e4b23b6f4c0c0b2a0a83f8a64e9194b"}, +] [package.dependencies] click = "*" @@ -155,6 +213,10 @@ description = "Cross-platform colored terminal text." category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, + {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, +] [[package]] name = "defusedxml" @@ -163,6 +225,10 @@ description = "XML bomb protection for Python stdlib modules" category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, + {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, +] [[package]] name = "diff-match-patch" @@ -171,14 +237,22 @@ description = "Repackaging of Google's Diff Match and Patch libraries. Offers ro category = "main" optional = false python-versions = ">=2.7" +files = [ + {file = "diff-match-patch-20200713.tar.gz", hash = "sha256:da6f5a01aa586df23dfc89f3827e1cafbb5420be9d87769eeb079ddfd9477a18"}, + {file = "diff_match_patch-20200713-py3-none-any.whl", hash = "sha256:8bf9d9c4e059d917b5c6312bac0c137971a32815ddbda9c682b949f2986b4d34"}, +] [[package]] name = "django" -version = "3.2.16" +version = "3.2.18" description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design." category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "Django-3.2.18-py3-none-any.whl", hash = "sha256:4d492d9024c7b3dfababf49f94511ab6a58e2c9c3c7207786f1ba4eb77750706"}, + {file = "Django-3.2.18.tar.gz", hash = "sha256:08208dfe892eb64fff073ca743b3b952311104f939e7f6dae954fe72dcc533ba"}, +] [package.dependencies] asgiref = ">=3.3.2,<4" @@ -196,6 +270,9 @@ description = "Runs some quick tests on your admin site objects to make sure the category = "dev" optional = false python-versions = "*" +files = [ + {file = "django-admin-smoke-tests-0.3.0.tar.gz", hash = "sha256:5dc35c61610d4e762bc21a6d2ba4599d67491ff5260e576e0454c14b341a2be9"}, +] [package.dependencies] django = ">=1.6" @@ -208,6 +285,9 @@ description = "Add special User ForeignKey fields which update automatically" category = "main" optional = false python-versions = "*" +files = [ + {file = "django-author-1.0.2.tar.gz", hash = "sha256:0238b6280f66a8ba6d1c730ab4acc52bc2bf37686940fd4db42e7af458c96635"}, +] [package.dependencies] setuptools-git = "*" @@ -219,6 +299,10 @@ description = "Django application and library for importing and exporting data w category = "main" optional = false python-versions = ">=3.5" +files = [ + {file = "django-import-export-2.5.0.tar.gz", hash = "sha256:c39c003bfc803fb63ba7742562f1667603a4a8d7426261845d75ce8582d40f48"}, + {file = "django_import_export-2.5.0-py3-none-any.whl", hash = "sha256:cf6f3dabdd4f32dcb26e25c7ddcba7aee3168b55d380b0da79f0349afa17c011"}, +] [package.dependencies] diff-match-patch = "*" @@ -232,6 +316,10 @@ description = "An implementation of lxml.xmlfile for the standard library" category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "et_xmlfile-1.1.0-py3-none-any.whl", hash = "sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada"}, + {file = "et_xmlfile-1.1.0.tar.gz", hash = "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c"}, +] [[package]] name = "importlib-metadata" @@ -240,6 +328,10 @@ description = "Read metadata from Python packages" category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "importlib_metadata-4.8.1-py3-none-any.whl", hash = "sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15"}, + {file = "importlib_metadata-4.8.1.tar.gz", hash = "sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1"}, +] [package.dependencies] typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} @@ -257,6 +349,10 @@ description = "Messaging library for Python." category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "kombu-5.1.0-py3-none-any.whl", hash = "sha256:e2dedd8a86c9077c350555153825a31e456a0dc20c15d5751f00137ec9c75f0a"}, + {file = "kombu-5.1.0.tar.gz", hash = "sha256:01481d99f4606f6939cdc9b637264ed353ee9e3e4f62cfb582324142c41a572d"}, +] [package.dependencies] amqp = ">=5.0.6,<6.0.0" @@ -287,6 +383,9 @@ description = "An HTML/XML generator" category = "main" optional = false python-versions = "*" +files = [ + {file = "MarkupPy-1.14.tar.gz", hash = "sha256:1adee2c0a542af378fe84548ff6f6b0168f3cb7f426b46961038a2bcfaad0d5f"}, +] [[package]] name = "mypy-extensions" @@ -295,6 +394,10 @@ description = "Experimental type system extensions for programs checked with the category = "dev" optional = false python-versions = "*" +files = [ + {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, + {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, +] [[package]] name = "odfpy" @@ -303,6 +406,9 @@ description = "Python API and tools to manipulate OpenDocument files" category = "main" optional = false python-versions = "*" +files = [ + {file = "odfpy-1.4.1.tar.gz", hash = "sha256:db766a6e59c5103212f3cc92ec8dd50a0f3a02790233ed0b52148b70d3c438ec"}, +] [package.dependencies] defusedxml = "*" @@ -314,6 +420,10 @@ description = "A Python library to read/write Excel 2010 xlsx/xlsm files" category = "main" optional = false python-versions = ">=3.6," +files = [ + {file = "openpyxl-3.0.7-py2.py3-none-any.whl", hash = "sha256:46af4eaf201a89b610fcca177eed957635f88770a5462fb6aae4a2a52b0ff516"}, + {file = "openpyxl-3.0.7.tar.gz", hash = "sha256:6456a3b472e1ef0facb1129f3c6ef00713cebf62e736cd7a75bcc3247432f251"}, +] [package.dependencies] et-xmlfile = "*" @@ -325,6 +435,10 @@ description = "Utility library for gitignore style pattern matching of file path category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +files = [ + {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, + {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, +] [[package]] name = "platformdirs" @@ -333,6 +447,10 @@ description = "A small Python module for determining appropriate platform-specif category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"}, + {file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"}, +] [package.extras] docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] @@ -345,6 +463,10 @@ description = "Library for building powerful interactive command lines in Python category = "main" optional = false python-versions = ">=3.6.2" +files = [ + {file = "prompt_toolkit-3.0.20-py3-none-any.whl", hash = "sha256:6076e46efae19b1e0ca1ec003ed37a933dc94b4d20f486235d436e64771dcd5c"}, + {file = "prompt_toolkit-3.0.20.tar.gz", hash = "sha256:eb71d5a6b72ce6db177af4a7d4d7085b99756bf656d98ffcc4fecd36850eea6c"}, +] [package.dependencies] wcwidth = "*" @@ -356,6 +478,44 @@ description = "psycopg2 - Python-PostgreSQL Database Adapter" category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "psycopg2-binary-2.9.1.tar.gz", hash = "sha256:b0221ca5a9837e040ebf61f48899926b5783668b7807419e4adae8175a31f773"}, + {file = "psycopg2_binary-2.9.1-cp310-cp310-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:24b0b6688b9f31a911f2361fe818492650795c9e5d3a1bc647acbd7440142a4f"}, + {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:542875f62bc56e91c6eac05a0deadeae20e1730be4c6334d8f04c944fcd99759"}, + {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:661509f51531ec125e52357a489ea3806640d0ca37d9dada461ffc69ee1e7b6e"}, + {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:d92272c7c16e105788efe2cfa5d680f07e34e0c29b03c1908f8636f55d5f915a"}, + {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_24_ppc64le.whl", hash = "sha256:736b8797b58febabb85494142c627bd182b50d2a7ec65322983e71065ad3034c"}, + {file = "psycopg2_binary-2.9.1-cp310-cp310-win32.whl", hash = "sha256:ebccf1123e7ef66efc615a68295bf6fdba875a75d5bba10a05073202598085fc"}, + {file = "psycopg2_binary-2.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:1f6ca4a9068f5c5c57e744b4baa79f40e83e3746875cac3c45467b16326bab45"}, + {file = "psycopg2_binary-2.9.1-cp36-cp36m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:c250a7ec489b652c892e4f0a5d122cc14c3780f9f643e1a326754aedf82d9a76"}, + {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aef9aee84ec78af51107181d02fe8773b100b01c5dfde351184ad9223eab3698"}, + {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:123c3fb684e9abfc47218d3784c7b4c47c8587951ea4dd5bc38b6636ac57f616"}, + {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_24_aarch64.whl", hash = "sha256:995fc41ebda5a7a663a254a1dcac52638c3e847f48307b5416ee373da15075d7"}, + {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_24_ppc64le.whl", hash = "sha256:fbb42a541b1093385a2d8c7eec94d26d30437d0e77c1d25dae1dcc46741a385e"}, + {file = "psycopg2_binary-2.9.1-cp36-cp36m-win32.whl", hash = "sha256:20f1ab44d8c352074e2d7ca67dc00843067788791be373e67a0911998787ce7d"}, + {file = "psycopg2_binary-2.9.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f6fac64a38f6768e7bc7b035b9e10d8a538a9fadce06b983fb3e6fa55ac5f5ce"}, + {file = "psycopg2_binary-2.9.1-cp37-cp37m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:1e3a362790edc0a365385b1ac4cc0acc429a0c0d662d829a50b6ce743ae61b5a"}, + {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f8559617b1fcf59a9aedba2c9838b5b6aa211ffedecabca412b92a1ff75aac1a"}, + {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a36c7eb6152ba5467fb264d73844877be8b0847874d4822b7cf2d3c0cb8cdcb0"}, + {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:2f62c207d1740b0bde5c4e949f857b044818f734a3d57f1d0d0edc65050532ed"}, + {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_24_ppc64le.whl", hash = "sha256:cfc523edecddaef56f6740d7de1ce24a2fdf94fd5e704091856a201872e37f9f"}, + {file = "psycopg2_binary-2.9.1-cp37-cp37m-win32.whl", hash = "sha256:1e85b74cbbb3056e3656f1cc4781294df03383127a8114cbc6531e8b8367bf1e"}, + {file = "psycopg2_binary-2.9.1-cp37-cp37m-win_amd64.whl", hash = "sha256:1473c0215b0613dd938db54a653f68251a45a78b05f6fc21af4326f40e8360a2"}, + {file = "psycopg2_binary-2.9.1-cp38-cp38-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:35c4310f8febe41f442d3c65066ca93cccefd75013df3d8c736c5b93ec288140"}, + {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c13d72ed6af7fd2c8acbd95661cf9477f94e381fce0792c04981a8283b52917"}, + {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14db1752acdd2187d99cb2ca0a1a6dfe57fc65c3281e0f20e597aac8d2a5bd90"}, + {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:aed4a9a7e3221b3e252c39d0bf794c438dc5453bc2963e8befe9d4cd324dff72"}, + {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_24_ppc64le.whl", hash = "sha256:da113b70f6ec40e7d81b43d1b139b9db6a05727ab8be1ee559f3a69854a69d34"}, + {file = "psycopg2_binary-2.9.1-cp38-cp38-win32.whl", hash = "sha256:4235f9d5ddcab0b8dbd723dca56ea2922b485ea00e1dafacf33b0c7e840b3d32"}, + {file = "psycopg2_binary-2.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:988b47ac70d204aed01589ed342303da7c4d84b56c2f4c4b8b00deda123372bf"}, + {file = "psycopg2_binary-2.9.1-cp39-cp39-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:7360647ea04db2e7dff1648d1da825c8cf68dc5fbd80b8fb5b3ee9f068dcd21a"}, + {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca86db5b561b894f9e5f115d6a159fff2a2570a652e07889d8a383b5fae66eb4"}, + {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ced67f1e34e1a450cdb48eb53ca73b60aa0af21c46b9b35ac3e581cf9f00e31"}, + {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:0f2e04bd2a2ab54fa44ee67fe2d002bb90cee1c0f1cc0ebc3148af7b02034cbd"}, + {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_24_ppc64le.whl", hash = "sha256:3242b9619de955ab44581a03a64bdd7d5e470cc4183e8fcadd85ab9d3756ce7a"}, + {file = "psycopg2_binary-2.9.1-cp39-cp39-win32.whl", hash = "sha256:0b7dae87f0b729922e06f85f667de7bf16455d411971b2043bbd9577af9d1975"}, + {file = "psycopg2_binary-2.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:b4d7679a08fea64573c969f6994a2631908bb2c0e69a7235648642f3d2e39a68"}, +] [[package]] name = "pudb" @@ -364,6 +524,9 @@ description = "A full-screen, console-based Python debugger" category = "dev" optional = false python-versions = "*" +files = [ + {file = "pudb-2019.2.tar.gz", hash = "sha256:e8f0ea01b134d802872184b05bffc82af29a1eb2f9374a277434b932d68f58dc"}, +] [package.dependencies] pygments = ">=1.0" @@ -376,6 +539,10 @@ description = "Pygments is a syntax highlighting package written in Python." category = "dev" optional = false python-versions = ">=3.5" +files = [ + {file = "Pygments-2.10.0-py3-none-any.whl", hash = "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380"}, + {file = "Pygments-2.10.0.tar.gz", hash = "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"}, +] [[package]] name = "pytz" @@ -384,6 +551,10 @@ description = "World timezone definitions, modern and historical" category = "main" optional = false python-versions = "*" +files = [ + {file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"}, + {file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"}, +] [[package]] name = "pyyaml" @@ -392,6 +563,37 @@ description = "YAML parser and emitter for Python" category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"}, + {file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393"}, + {file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8"}, + {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"}, + {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"}, + {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"}, + {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347"}, + {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541"}, + {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"}, + {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"}, + {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"}, + {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"}, + {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa"}, + {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"}, + {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"}, + {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"}, + {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"}, + {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"}, + {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247"}, + {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc"}, + {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"}, + {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"}, + {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"}, + {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"}, + {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122"}, + {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6"}, + {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"}, + {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"}, + {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"}, +] [[package]] name = "redis" @@ -400,6 +602,10 @@ description = "Python client for Redis key-value store" category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "redis-3.5.3-py2.py3-none-any.whl", hash = "sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24"}, + {file = "redis-3.5.3.tar.gz", hash = "sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2"}, +] [package.extras] hiredis = ["hiredis (>=0.1.3)"] @@ -411,6 +617,10 @@ description = "Setuptools revision control system plugin for Git" category = "main" optional = false python-versions = "*" +files = [ + {file = "setuptools-git-1.2.tar.gz", hash = "sha256:ff64136da01aabba76ae88b050e7197918d8b2139ccbf6144e14d472b9c40445"}, + {file = "setuptools_git-1.2-py2.py3-none-any.whl", hash = "sha256:e7764dccce7d97b4b5a330d7b966aac6f9ac026385743fd6cedad553f2494cfa"}, +] [[package]] name = "six" @@ -419,6 +629,10 @@ description = "Python 2 and 3 compatibility utilities" category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] [[package]] name = "sqlparse" @@ -427,6 +641,10 @@ description = "A non-validating SQL parser." category = "main" optional = false python-versions = ">=3.5" +files = [ + {file = "sqlparse-0.4.1-py3-none-any.whl", hash = "sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0"}, + {file = "sqlparse-0.4.1.tar.gz", hash = "sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8"}, +] [[package]] name = "tablib" @@ -435,6 +653,10 @@ description = "Format agnostic tabular data library (XLS, JSON, YAML, CSV)" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "tablib-3.2.1-py3-none-any.whl", hash = "sha256:870d7e688f738531a14937a055e8bba404fbc388e77d4d500b2c904075d1019c"}, + {file = "tablib-3.2.1.tar.gz", hash = "sha256:a57f2770b8c225febec1cb1e65012a69cf30dd28be810e0ff98d024768c7d0f1"}, +] [package.dependencies] markuppy = {version = "*", optional = true, markers = "extra == \"html\""} @@ -461,6 +683,10 @@ description = "A lil' TOML parser" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] [[package]] name = "typed-ast" @@ -469,6 +695,38 @@ description = "a fork of Python 2 and 3 ast modules with type comment support" category = "dev" optional = false python-versions = "*" +files = [ + {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"}, + {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075"}, + {file = "typed_ast-1.4.3-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528"}, + {file = "typed_ast-1.4.3-cp35-cp35m-win32.whl", hash = "sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428"}, + {file = "typed_ast-1.4.3-cp35-cp35m-win_amd64.whl", hash = "sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3"}, + {file = "typed_ast-1.4.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f"}, + {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341"}, + {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace"}, + {file = "typed_ast-1.4.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f"}, + {file = "typed_ast-1.4.3-cp36-cp36m-win32.whl", hash = "sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363"}, + {file = "typed_ast-1.4.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7"}, + {file = "typed_ast-1.4.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266"}, + {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e"}, + {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04"}, + {file = "typed_ast-1.4.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899"}, + {file = "typed_ast-1.4.3-cp37-cp37m-win32.whl", hash = "sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c"}, + {file = "typed_ast-1.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805"}, + {file = "typed_ast-1.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a"}, + {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff"}, + {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41"}, + {file = "typed_ast-1.4.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39"}, + {file = "typed_ast-1.4.3-cp38-cp38-win32.whl", hash = "sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927"}, + {file = "typed_ast-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40"}, + {file = "typed_ast-1.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3"}, + {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4"}, + {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0"}, + {file = "typed_ast-1.4.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3"}, + {file = "typed_ast-1.4.3-cp39-cp39-win32.whl", hash = "sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808"}, + {file = "typed_ast-1.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c"}, + {file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"}, +] [[package]] name = "typing-extensions" @@ -477,6 +735,11 @@ description = "Backported and Experimental Type Hints for Python 3.5+" category = "main" optional = false python-versions = "*" +files = [ + {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"}, + {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"}, + {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"}, +] [[package]] name = "urwid" @@ -485,6 +748,9 @@ description = "A full-featured console (xterm et al.) user interface library" category = "dev" optional = false python-versions = "*" +files = [ + {file = "urwid-2.1.2.tar.gz", hash = "sha256:588bee9c1cb208d0906a9f73c613d2bd32c3ed3702012f51efe318a3f2127eae"}, +] [[package]] name = "vine" @@ -493,6 +759,10 @@ description = "Promises, promises, promises." category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "vine-5.0.0-py2.py3-none-any.whl", hash = "sha256:4c9dceab6f76ed92105027c49c823800dd33cacce13bdedc5b914e3514b7fb30"}, + {file = "vine-5.0.0.tar.gz", hash = "sha256:7d3b1624a953da82ef63462013bbd271d3eb75751489f9807598e8f340bd637e"}, +] [[package]] name = "wcwidth" @@ -501,6 +771,10 @@ description = "Measures the displayed width of unicode strings in a terminal" category = "main" optional = false python-versions = "*" +files = [ + {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, + {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, +] [[package]] name = "xlrd" @@ -509,6 +783,10 @@ description = "Library for developers to extract data from Microsoft Excel (tm) category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "xlrd-2.0.1-py2.py3-none-any.whl", hash = "sha256:6a33ee89877bd9abc1158129f6e94be74e2679636b8a205b43b85206c3f0bbdd"}, + {file = "xlrd-2.0.1.tar.gz", hash = "sha256:f72f148f54442c6b056bf931dbc34f986fd0c3b0b6b5a58d013c9aef274d0c88"}, +] [package.extras] build = ["twine", "wheel"] @@ -522,6 +800,10 @@ description = "Library to create spreadsheet files compatible with MS Excel 97/2 category = "main" optional = false python-versions = "*" +files = [ + {file = "xlwt-1.3.0-py2.py3-none-any.whl", hash = "sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e"}, + {file = "xlwt-1.3.0.tar.gz", hash = "sha256:c59912717a9b28f1a3c2a98fd60741014b06b043936dcecbc113eaaada156c88"}, +] [[package]] name = "zipp" @@ -530,298 +812,16 @@ description = "Backport of pathlib-compatible object wrapper for zip files" category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "zipp-3.5.0-py3-none-any.whl", hash = "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3"}, + {file = "zipp-3.5.0.tar.gz", hash = "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"}, +] [package.extras] docs = ["jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "sphinx"] testing = ["func-timeout", "jaraco.itertools", "pytest (>=4.6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy"] [metadata] -lock-version = "1.1" +lock-version = "2.0" python-versions = "^3.7" content-hash = "3803687c30191b8f372989a64507765e2f5ebe438ff55483db56e242d3a33488" - -[metadata.files] -amqp = [ - {file = "amqp-5.0.6-py3-none-any.whl", hash = "sha256:493a2ac6788ce270a2f6a765b017299f60c1998f5a8617908ee9be082f7300fb"}, - {file = "amqp-5.0.6.tar.gz", hash = "sha256:03e16e94f2b34c31f8bf1206d8ddd3ccaa4c315f7f6a1879b7b1210d229568c2"}, -] -asgiref = [ - {file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"}, - {file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"}, -] -billiard = [ - {file = "billiard-3.6.4.0-py3-none-any.whl", hash = "sha256:87103ea78fa6ab4d5c751c4909bcff74617d985de7fa8b672cf8618afd5a875b"}, - {file = "billiard-3.6.4.0.tar.gz", hash = "sha256:299de5a8da28a783d51b197d496bef4f1595dd023a93a4f59dde1886ae905547"}, -] -black = [ - {file = "black-22.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09"}, - {file = "black-22.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb"}, - {file = "black-22.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a"}, - {file = "black-22.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968"}, - {file = "black-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d"}, - {file = "black-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cc1e1de68c8e5444e8f94c3670bb48a2beef0e91dddfd4fcc29595ebd90bb9ce"}, - {file = "black-22.3.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2fc92002d44746d3e7db7cf9313cf4452f43e9ea77a2c939defce3b10b5c82"}, - {file = "black-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:a6342964b43a99dbc72f72812bf88cad8f0217ae9acb47c0d4f141a6416d2d7b"}, - {file = "black-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:328efc0cc70ccb23429d6be184a15ce613f676bdfc85e5fe8ea2a9354b4e9015"}, - {file = "black-22.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06f9d8846f2340dfac80ceb20200ea5d1b3f181dd0556b47af4e8e0b24fa0a6b"}, - {file = "black-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4efa5fad66b903b4a5f96d91461d90b9507a812b3c5de657d544215bb7877a"}, - {file = "black-22.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8477ec6bbfe0312c128e74644ac8a02ca06bcdb8982d4ee06f209be28cdf163"}, - {file = "black-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:637a4014c63fbf42a692d22b55d8ad6968a946b4a6ebc385c5505d9625b6a464"}, - {file = "black-22.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:863714200ada56cbc366dc9ae5291ceb936573155f8bf8e9de92aef51f3ad0f0"}, - {file = "black-22.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10dbe6e6d2988049b4655b2b739f98785a884d4d6b85bc35133a8fb9a2233176"}, - {file = "black-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:cee3e11161dde1b2a33a904b850b0899e0424cc331b7295f2a9698e79f9a69a0"}, - {file = "black-22.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20"}, - {file = "black-22.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a"}, - {file = "black-22.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad"}, - {file = "black-22.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21"}, - {file = "black-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265"}, - {file = "black-22.3.0-py3-none-any.whl", hash = "sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72"}, - {file = "black-22.3.0.tar.gz", hash = "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79"}, -] -cached-property = [ - {file = "cached-property-1.5.2.tar.gz", hash = "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130"}, - {file = "cached_property-1.5.2-py2.py3-none-any.whl", hash = "sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0"}, -] -celery = [ - {file = "celery-5.0.2-py3-none-any.whl", hash = "sha256:930c3acd55349d028c4e7104a7d377729cbcca19d9fce470c17172d9e7f9a8b6"}, - {file = "celery-5.0.2.tar.gz", hash = "sha256:012c814967fe89e3f5d2cf49df2dba3de5f29253a7f4f2270e8fce6b901b4ebf"}, -] -click = [ - {file = "click-8.0.1-py3-none-any.whl", hash = "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"}, - {file = "click-8.0.1.tar.gz", hash = "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a"}, -] -click-didyoumean = [ - {file = "click-didyoumean-0.0.3.tar.gz", hash = "sha256:112229485c9704ff51362fe34b2d4f0b12fc71cc20f6d2b3afabed4b8bfa6aeb"}, -] -click-repl = [ - {file = "click-repl-0.2.0.tar.gz", hash = "sha256:cd12f68d745bf6151210790540b4cb064c7b13e571bc64b6957d98d120dacfd8"}, - {file = "click_repl-0.2.0-py3-none-any.whl", hash = "sha256:94b3fbbc9406a236f176e0506524b2937e4b23b6f4c0c0b2a0a83f8a64e9194b"}, -] -colorama = [ - {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, - {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, -] -defusedxml = [ - {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, - {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, -] -diff-match-patch = [ - {file = "diff-match-patch-20200713.tar.gz", hash = "sha256:da6f5a01aa586df23dfc89f3827e1cafbb5420be9d87769eeb079ddfd9477a18"}, - {file = "diff_match_patch-20200713-py3-none-any.whl", hash = "sha256:8bf9d9c4e059d917b5c6312bac0c137971a32815ddbda9c682b949f2986b4d34"}, -] -django = [ - {file = "Django-3.2.16-py3-none-any.whl", hash = "sha256:18ba8efa36b69cfcd4b670d0fa187c6fe7506596f0ababe580e16909bcdec121"}, - {file = "Django-3.2.16.tar.gz", hash = "sha256:3adc285124244724a394fa9b9839cc8cd116faf7d159554c43ecdaa8cdf0b94d"}, -] -django-admin-smoke-tests = [ - {file = "django-admin-smoke-tests-0.3.0.tar.gz", hash = "sha256:5dc35c61610d4e762bc21a6d2ba4599d67491ff5260e576e0454c14b341a2be9"}, -] -django-author = [ - {file = "django-author-1.0.2.tar.gz", hash = "sha256:0238b6280f66a8ba6d1c730ab4acc52bc2bf37686940fd4db42e7af458c96635"}, -] -django-import-export = [ - {file = "django-import-export-2.5.0.tar.gz", hash = "sha256:c39c003bfc803fb63ba7742562f1667603a4a8d7426261845d75ce8582d40f48"}, - {file = "django_import_export-2.5.0-py3-none-any.whl", hash = "sha256:cf6f3dabdd4f32dcb26e25c7ddcba7aee3168b55d380b0da79f0349afa17c011"}, -] -et-xmlfile = [ - {file = "et_xmlfile-1.1.0-py3-none-any.whl", hash = "sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada"}, - {file = "et_xmlfile-1.1.0.tar.gz", hash = "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c"}, -] -importlib-metadata = [ - {file = "importlib_metadata-4.8.1-py3-none-any.whl", hash = "sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15"}, - {file = "importlib_metadata-4.8.1.tar.gz", hash = "sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1"}, -] -kombu = [ - {file = "kombu-5.1.0-py3-none-any.whl", hash = "sha256:e2dedd8a86c9077c350555153825a31e456a0dc20c15d5751f00137ec9c75f0a"}, - {file = "kombu-5.1.0.tar.gz", hash = "sha256:01481d99f4606f6939cdc9b637264ed353ee9e3e4f62cfb582324142c41a572d"}, -] -markuppy = [ - {file = "MarkupPy-1.14.tar.gz", hash = "sha256:1adee2c0a542af378fe84548ff6f6b0168f3cb7f426b46961038a2bcfaad0d5f"}, -] -mypy-extensions = [ - {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, - {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, -] -odfpy = [ - {file = "odfpy-1.4.1.tar.gz", hash = "sha256:db766a6e59c5103212f3cc92ec8dd50a0f3a02790233ed0b52148b70d3c438ec"}, -] -openpyxl = [ - {file = "openpyxl-3.0.7-py2.py3-none-any.whl", hash = "sha256:46af4eaf201a89b610fcca177eed957635f88770a5462fb6aae4a2a52b0ff516"}, - {file = "openpyxl-3.0.7.tar.gz", hash = "sha256:6456a3b472e1ef0facb1129f3c6ef00713cebf62e736cd7a75bcc3247432f251"}, -] -pathspec = [ - {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, - {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, -] -platformdirs = [ - {file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"}, - {file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"}, -] -prompt-toolkit = [ - {file = "prompt_toolkit-3.0.20-py3-none-any.whl", hash = "sha256:6076e46efae19b1e0ca1ec003ed37a933dc94b4d20f486235d436e64771dcd5c"}, - {file = "prompt_toolkit-3.0.20.tar.gz", hash = "sha256:eb71d5a6b72ce6db177af4a7d4d7085b99756bf656d98ffcc4fecd36850eea6c"}, -] -psycopg2-binary = [ - {file = "psycopg2-binary-2.9.1.tar.gz", hash = "sha256:b0221ca5a9837e040ebf61f48899926b5783668b7807419e4adae8175a31f773"}, - {file = "psycopg2_binary-2.9.1-cp310-cp310-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:24b0b6688b9f31a911f2361fe818492650795c9e5d3a1bc647acbd7440142a4f"}, - {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:542875f62bc56e91c6eac05a0deadeae20e1730be4c6334d8f04c944fcd99759"}, - {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:661509f51531ec125e52357a489ea3806640d0ca37d9dada461ffc69ee1e7b6e"}, - {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:d92272c7c16e105788efe2cfa5d680f07e34e0c29b03c1908f8636f55d5f915a"}, - {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_24_ppc64le.whl", hash = "sha256:736b8797b58febabb85494142c627bd182b50d2a7ec65322983e71065ad3034c"}, - {file = "psycopg2_binary-2.9.1-cp310-cp310-win32.whl", hash = "sha256:ebccf1123e7ef66efc615a68295bf6fdba875a75d5bba10a05073202598085fc"}, - {file = "psycopg2_binary-2.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:1f6ca4a9068f5c5c57e744b4baa79f40e83e3746875cac3c45467b16326bab45"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:c250a7ec489b652c892e4f0a5d122cc14c3780f9f643e1a326754aedf82d9a76"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aef9aee84ec78af51107181d02fe8773b100b01c5dfde351184ad9223eab3698"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:123c3fb684e9abfc47218d3784c7b4c47c8587951ea4dd5bc38b6636ac57f616"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_24_aarch64.whl", hash = "sha256:995fc41ebda5a7a663a254a1dcac52638c3e847f48307b5416ee373da15075d7"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_24_ppc64le.whl", hash = "sha256:fbb42a541b1093385a2d8c7eec94d26d30437d0e77c1d25dae1dcc46741a385e"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-win32.whl", hash = "sha256:20f1ab44d8c352074e2d7ca67dc00843067788791be373e67a0911998787ce7d"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f6fac64a38f6768e7bc7b035b9e10d8a538a9fadce06b983fb3e6fa55ac5f5ce"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:1e3a362790edc0a365385b1ac4cc0acc429a0c0d662d829a50b6ce743ae61b5a"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f8559617b1fcf59a9aedba2c9838b5b6aa211ffedecabca412b92a1ff75aac1a"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a36c7eb6152ba5467fb264d73844877be8b0847874d4822b7cf2d3c0cb8cdcb0"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:2f62c207d1740b0bde5c4e949f857b044818f734a3d57f1d0d0edc65050532ed"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_24_ppc64le.whl", hash = "sha256:cfc523edecddaef56f6740d7de1ce24a2fdf94fd5e704091856a201872e37f9f"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-win32.whl", hash = "sha256:1e85b74cbbb3056e3656f1cc4781294df03383127a8114cbc6531e8b8367bf1e"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-win_amd64.whl", hash = "sha256:1473c0215b0613dd938db54a653f68251a45a78b05f6fc21af4326f40e8360a2"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:35c4310f8febe41f442d3c65066ca93cccefd75013df3d8c736c5b93ec288140"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c13d72ed6af7fd2c8acbd95661cf9477f94e381fce0792c04981a8283b52917"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14db1752acdd2187d99cb2ca0a1a6dfe57fc65c3281e0f20e597aac8d2a5bd90"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:aed4a9a7e3221b3e252c39d0bf794c438dc5453bc2963e8befe9d4cd324dff72"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_24_ppc64le.whl", hash = "sha256:da113b70f6ec40e7d81b43d1b139b9db6a05727ab8be1ee559f3a69854a69d34"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-win32.whl", hash = "sha256:4235f9d5ddcab0b8dbd723dca56ea2922b485ea00e1dafacf33b0c7e840b3d32"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:988b47ac70d204aed01589ed342303da7c4d84b56c2f4c4b8b00deda123372bf"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:7360647ea04db2e7dff1648d1da825c8cf68dc5fbd80b8fb5b3ee9f068dcd21a"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca86db5b561b894f9e5f115d6a159fff2a2570a652e07889d8a383b5fae66eb4"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ced67f1e34e1a450cdb48eb53ca73b60aa0af21c46b9b35ac3e581cf9f00e31"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:0f2e04bd2a2ab54fa44ee67fe2d002bb90cee1c0f1cc0ebc3148af7b02034cbd"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_24_ppc64le.whl", hash = "sha256:3242b9619de955ab44581a03a64bdd7d5e470cc4183e8fcadd85ab9d3756ce7a"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-win32.whl", hash = "sha256:0b7dae87f0b729922e06f85f667de7bf16455d411971b2043bbd9577af9d1975"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:b4d7679a08fea64573c969f6994a2631908bb2c0e69a7235648642f3d2e39a68"}, -] -pudb = [ - {file = "pudb-2019.2.tar.gz", hash = "sha256:e8f0ea01b134d802872184b05bffc82af29a1eb2f9374a277434b932d68f58dc"}, -] -pygments = [ - {file = "Pygments-2.10.0-py3-none-any.whl", hash = "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380"}, - {file = "Pygments-2.10.0.tar.gz", hash = "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"}, -] -pytz = [ - {file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"}, - {file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"}, -] -pyyaml = [ - {file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"}, - {file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393"}, - {file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8"}, - {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"}, - {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"}, - {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"}, - {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347"}, - {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541"}, - {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"}, - {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"}, - {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"}, - {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"}, - {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa"}, - {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"}, - {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"}, - {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"}, - {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"}, - {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"}, - {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247"}, - {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc"}, - {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"}, - {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"}, - {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"}, - {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"}, - {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122"}, - {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6"}, - {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"}, - {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"}, - {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"}, -] -redis = [ - {file = "redis-3.5.3-py2.py3-none-any.whl", hash = "sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24"}, - {file = "redis-3.5.3.tar.gz", hash = "sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2"}, -] -setuptools-git = [ - {file = "setuptools-git-1.2.tar.gz", hash = "sha256:ff64136da01aabba76ae88b050e7197918d8b2139ccbf6144e14d472b9c40445"}, - {file = "setuptools_git-1.2-py2.py3-none-any.whl", hash = "sha256:e7764dccce7d97b4b5a330d7b966aac6f9ac026385743fd6cedad553f2494cfa"}, -] -six = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] -sqlparse = [ - {file = "sqlparse-0.4.1-py3-none-any.whl", hash = "sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0"}, - {file = "sqlparse-0.4.1.tar.gz", hash = "sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8"}, -] -tablib = [ - {file = "tablib-3.2.1-py3-none-any.whl", hash = "sha256:870d7e688f738531a14937a055e8bba404fbc388e77d4d500b2c904075d1019c"}, - {file = "tablib-3.2.1.tar.gz", hash = "sha256:a57f2770b8c225febec1cb1e65012a69cf30dd28be810e0ff98d024768c7d0f1"}, -] -tomli = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] -typed-ast = [ - {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"}, - {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075"}, - {file = "typed_ast-1.4.3-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528"}, - {file = "typed_ast-1.4.3-cp35-cp35m-win32.whl", hash = "sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428"}, - {file = "typed_ast-1.4.3-cp35-cp35m-win_amd64.whl", hash = "sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3"}, - {file = "typed_ast-1.4.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f"}, - {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341"}, - {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace"}, - {file = "typed_ast-1.4.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f"}, - {file = "typed_ast-1.4.3-cp36-cp36m-win32.whl", hash = "sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363"}, - {file = "typed_ast-1.4.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7"}, - {file = "typed_ast-1.4.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266"}, - {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e"}, - {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04"}, - {file = "typed_ast-1.4.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899"}, - {file = "typed_ast-1.4.3-cp37-cp37m-win32.whl", hash = "sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c"}, - {file = "typed_ast-1.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805"}, - {file = "typed_ast-1.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a"}, - {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff"}, - {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41"}, - {file = "typed_ast-1.4.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39"}, - {file = "typed_ast-1.4.3-cp38-cp38-win32.whl", hash = "sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927"}, - {file = "typed_ast-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40"}, - {file = "typed_ast-1.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3"}, - {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4"}, - {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0"}, - {file = "typed_ast-1.4.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3"}, - {file = "typed_ast-1.4.3-cp39-cp39-win32.whl", hash = "sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808"}, - {file = "typed_ast-1.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c"}, - {file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"}, -] -typing-extensions = [ - {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"}, - {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"}, - {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"}, -] -urwid = [ - {file = "urwid-2.1.2.tar.gz", hash = "sha256:588bee9c1cb208d0906a9f73c613d2bd32c3ed3702012f51efe318a3f2127eae"}, -] -vine = [ - {file = "vine-5.0.0-py2.py3-none-any.whl", hash = "sha256:4c9dceab6f76ed92105027c49c823800dd33cacce13bdedc5b914e3514b7fb30"}, - {file = "vine-5.0.0.tar.gz", hash = "sha256:7d3b1624a953da82ef63462013bbd271d3eb75751489f9807598e8f340bd637e"}, -] -wcwidth = [ - {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, - {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, -] -xlrd = [ - {file = "xlrd-2.0.1-py2.py3-none-any.whl", hash = "sha256:6a33ee89877bd9abc1158129f6e94be74e2679636b8a205b43b85206c3f0bbdd"}, - {file = "xlrd-2.0.1.tar.gz", hash = "sha256:f72f148f54442c6b056bf931dbc34f986fd0c3b0b6b5a58d013c9aef274d0c88"}, -] -xlwt = [ - {file = "xlwt-1.3.0-py2.py3-none-any.whl", hash = "sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e"}, - {file = "xlwt-1.3.0.tar.gz", hash = "sha256:c59912717a9b28f1a3c2a98fd60741014b06b043936dcecbc113eaaada156c88"}, -] -zipp = [ - {file = "zipp-3.5.0-py3-none-any.whl", hash = "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3"}, - {file = "zipp-3.5.0.tar.gz", hash = "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"}, -] From 1ecabe2e4a26001376ec2bbf3b9c31152253daaf Mon Sep 17 00:00:00 2001 From: Mahmudul Hasan Date: Thu, 2 Mar 2023 23:44:26 +0600 Subject: [PATCH 52/93] Default import mode configuration added --- README.rst | 5 +++++ import_export_celery/models/importjob.py | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 6aec0eb..d2849c1 100644 --- a/README.rst +++ b/README.rst @@ -49,6 +49,11 @@ A fully configured example project can be found in the example directory of this The available parameters are `app_label`, `model_name`, and `resource`. 'resource' should be a function which returns a django-import-export `Resource `__. 3. Done +4. Configure to turn off default dry run import. By default dry run import is `True` + + :: + + IMPORT_DRY_RUN_FIRST_TIME = False Preforming an import diff --git a/import_export_celery/models/importjob.py b/import_export_celery/models/importjob.py index 057d192..7a4f56b 100644 --- a/import_export_celery/models/importjob.py +++ b/import_export_celery/models/importjob.py @@ -1,5 +1,6 @@ # Copyright (C) 2019 o.s. Auto*Mat +from django.conf import settings from django.utils import timezone from author.decorators import with_author @@ -82,4 +83,4 @@ def importjob_post_save(sender, instance, **kwargs): if not instance.processing_initiated: instance.processing_initiated = timezone.now() instance.save() - transaction.on_commit(lambda: run_import_job.delay(instance.pk, dry_run=True)) + transaction.on_commit(lambda: run_import_job.delay(instance.pk, dry_run=getattr(settings, "IMPORT_DRY_RUN_FIRST_TIME", True))) From 1f02c4ae8f6db89188f83a7a09eae478d07e0250 Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Thu, 2 Mar 2023 20:00:06 +0100 Subject: [PATCH 53/93] Update README.rst --- README.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index d2849c1..ef4c7e6 100644 --- a/README.rst +++ b/README.rst @@ -49,7 +49,9 @@ A fully configured example project can be found in the example directory of this The available parameters are `app_label`, `model_name`, and `resource`. 'resource' should be a function which returns a django-import-export `Resource `__. 3. Done -4. Configure to turn off default dry run import. By default dry run import is `True` + + +By default a dry run of the import is initiated when the import object is created. To instead import the file immediately without a dry-run set the `IMPORT_DRY_RUN_FIRST_TIME` to `False` :: From f52326f93eaa5fd91dd40e52380ab24b5736b71f Mon Sep 17 00:00:00 2001 From: Jaspreet-singh-1032 Date: Sun, 26 Mar 2023 19:54:05 +0530 Subject: [PATCH 54/93] use template to send mail for export job completion --- docker-compose.yaml | 2 +- example/poetry.lock | 16 ++++- example/project/__init__.py | 3 + example/project/settings.py | 2 +- example/pyproject.toml | 1 + example/winners/tests/test_utils.py | 43 ++++++++++++ import_export_celery/tasks.py | 22 +----- .../email/export_job_completion.html | 14 ++++ import_export_celery/utils.py | 70 +++++++++++++++++++ 9 files changed, 149 insertions(+), 24 deletions(-) create mode 100644 example/winners/tests/test_utils.py create mode 100644 import_export_celery/templates/email/export_job_completion.html create mode 100644 import_export_celery/utils.py diff --git a/docker-compose.yaml b/docker-compose.yaml index 4b55d6e..51fe731 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -17,7 +17,7 @@ services: - ./pyenv:/home/test celery: build: . - entrypoint: poetry run celery -A project.celery worker + entrypoint: poetry run celery -A project.celery worker -l info links: - postgres - redis diff --git a/example/poetry.lock b/example/poetry.lock index 8ca7557..68bc5d2 100644 --- a/example/poetry.lock +++ b/example/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.0 and should not be changed by hand. [[package]] name = "amqp" @@ -321,6 +321,18 @@ files = [ {file = "et_xmlfile-1.1.0.tar.gz", hash = "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c"}, ] +[[package]] +name = "html2text" +version = "2020.1.16" +description = "Turn HTML into equivalent Markdown-structured text." +category = "main" +optional = false +python-versions = ">=3.5" +files = [ + {file = "html2text-2020.1.16-py3-none-any.whl", hash = "sha256:c7c629882da0cf377d66f073329ccf34a12ed2adf0169b9285ae4e63ef54c82b"}, + {file = "html2text-2020.1.16.tar.gz", hash = "sha256:e296318e16b059ddb97f7a8a1d6a5c1d7af4544049a01e261731d2d5cc277bbb"}, +] + [[package]] name = "importlib-metadata" version = "4.8.1" @@ -824,4 +836,4 @@ testing = ["func-timeout", "jaraco.itertools", "pytest (>=4.6)", "pytest-black ( [metadata] lock-version = "2.0" python-versions = "^3.7" -content-hash = "3803687c30191b8f372989a64507765e2f5ebe438ff55483db56e242d3a33488" +content-hash = "a3648819f33a1e0bf8777c6ea2b3404fd85ab3102dce0a6ccde9547efe96f9ff" diff --git a/example/project/__init__.py b/example/project/__init__.py index e69de29..53f4ccb 100644 --- a/example/project/__init__.py +++ b/example/project/__init__.py @@ -0,0 +1,3 @@ +from .celery import app as celery_app + +__all__ = ("celery_app",) diff --git a/example/project/settings.py b/example/project/settings.py index ca89a8a..58b6c6a 100644 --- a/example/project/settings.py +++ b/example/project/settings.py @@ -58,7 +58,7 @@ TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", - "DIRS": [], + "DIRS": ["templates"], "APP_DIRS": True, "OPTIONS": { "context_processors": [ diff --git a/example/pyproject.toml b/example/pyproject.toml index dfd7f27..745b5e7 100644 --- a/example/pyproject.toml +++ b/example/pyproject.toml @@ -13,6 +13,7 @@ celery = "*" django-author = "*" redis = "*" psycopg2-binary = "^2.8.4" +html2text = "^2020.1.16" [tool.poetry.dev-dependencies] django-admin-smoke-tests = "^0.3.0" diff --git a/example/winners/tests/test_utils.py b/example/winners/tests/test_utils.py new file mode 100644 index 0000000..e8565a1 --- /dev/null +++ b/example/winners/tests/test_utils.py @@ -0,0 +1,43 @@ +from django.test import TestCase, override_settings + +from django.urls import reverse +from import_export_celery.utils import ( + get_export_job_mail_subject, + get_export_job_mail_template, + get_export_job_mail_context, + DEFAULT_EXPORT_JOB_COMPLETION_MAIL_SUBJECT, + DEFAULT_EXPORT_JOB_COMPLETION_MAIL_TEMPLATE, +) +from import_export_celery.models import ExportJob + + +class UtilsTestCases(TestCase): + def test_get_export_job_mail_subject_by_default(self): + self.assertEqual( + DEFAULT_EXPORT_JOB_COMPLETION_MAIL_SUBJECT, get_export_job_mail_subject() + ) + + @override_settings(EXPORT_JOB_COMPLETION_MAIL_SUBJECT="New subject") + def test_get_export_job_mail_subject_overridden(self): + self.assertEqual("New subject", get_export_job_mail_subject()) + + def test_get_export_job_mail_template_default(self): + self.assertEqual( + DEFAULT_EXPORT_JOB_COMPLETION_MAIL_TEMPLATE, get_export_job_mail_template() + ) + + @override_settings(EXPORT_JOB_COMPLETION_MAIL_TEMPLATE="mytemplate.html") + def test_get_export_job_mail_template_overridden(self): + self.assertEqual("mytemplate.html", get_export_job_mail_template()) + + def test_get_export_job_mail_context(self): + export_job = ExportJob.objects.create( + app_label="winners", model="Winner", site_of_origin="http://127.0.0.1:8000" + ) + context = get_export_job_mail_context(export_job) + expected_context = { + "app_label": "winners", + "model": "Winner", + "link": f"http://127.0.0.1:8000/adminimport_export_celery/exportjob/{export_job.id}/change/", + } + self.assertEqual(context, expected_context) diff --git a/import_export_celery/tasks.py b/import_export_celery/tasks.py index c7e9b93..73c99eb 100644 --- a/import_export_celery/tasks.py +++ b/import_export_celery/tasks.py @@ -17,6 +17,7 @@ from . import models from .model_config import ModelConfig +from .utils import send_export_job_completion_mail from celery.utils.log import get_task_logger import logging @@ -234,24 +235,5 @@ def export_resource(self, *args, **kwargs): serialized = serialized.encode("utf8") export_job.file.save(filename, ContentFile(serialized)) if export_job.email_on_completion: - send_mail( - _("Django: Export job completed"), - _( - "Your export job on model {app_label}.{model} has completed. You can download the file at the following link:\n\n{link}" - ).format( - app_label=export_job.app_label, - model=export_job.model, - link=export_job.site_of_origin - + reverse( - "admin:%s_%s_change" - % ( - export_job._meta.app_label, - export_job._meta.model_name, - ), - args=[export_job.pk], - ), - ), - settings.SERVER_EMAIL, - [export_job.updated_by.email], - ) + send_export_job_completion_mail(export_job) return diff --git a/import_export_celery/templates/email/export_job_completion.html b/import_export_celery/templates/email/export_job_completion.html new file mode 100644 index 0000000..845c8c5 --- /dev/null +++ b/import_export_celery/templates/email/export_job_completion.html @@ -0,0 +1,14 @@ + + + + + + + Document + + + +

Your export job on model {{app_label}}.{{model}} has completed. You can download the file at the following link:

+ {{link}} + + diff --git a/import_export_celery/utils.py b/import_export_celery/utils.py new file mode 100644 index 0000000..f1d4f1d --- /dev/null +++ b/import_export_celery/utils.py @@ -0,0 +1,70 @@ +import html2text +from django.core.mail import send_mail +from django.template.loader import get_template +from django.conf import settings +from django.urls import reverse + +DEFAULT_EXPORT_JOB_COMPLETION_MAIL_SUBJECT = "Django: Export job completed" +DEFAULT_EXPORT_JOB_COMPLETION_MAIL_TEMPLATE = "email/export_job_completion.html" + + +def build_html_and_text_message(template_name, context={}): + """ + Render the given template with the context and returns + the data in html and plain text format. + """ + template = get_template(template_name) + html_message = template.render(context) + text_message = html2text.html2text(html_message) + return html_message, text_message + + +def get_export_job_mail_context(export_job): + context = { + "app_label": export_job.app_label, + "model": export_job.model, + "link": export_job.site_of_origin + + reverse( + "admin:%s_%s_change" + % ( + export_job._meta.app_label, + export_job._meta.model_name, + ), + args=[export_job.pk], + ), + } + return context + + +def get_export_job_mail_subject(): + return getattr( + settings, + "EXPORT_JOB_COMPLETION_MAIL_SUBJECT", + DEFAULT_EXPORT_JOB_COMPLETION_MAIL_SUBJECT, + ) + + +def get_export_job_mail_template(): + return getattr( + settings, + "EXPORT_JOB_COMPLETION_MAIL_TEMPLATE", + DEFAULT_EXPORT_JOB_COMPLETION_MAIL_TEMPLATE, + ) + + +def send_export_job_completion_mail(export_job): + """ + Send export job completion mail + """ + subject = get_export_job_mail_subject() + template_name = get_export_job_mail_template() + context = get_export_job_mail_context(export_job) + context.update({"export_job": export_job}) + html_message, text_message = build_html_and_text_message(template_name, context) + send_mail( + subject=subject, + message=text_message, + html_message=html_message, + from_email=settings.SERVER_EMAIL, + recipient_list=[export_job.updated_by.email], + ) From e347b0f2b9266de0259d9be85294c6ff5a99e158 Mon Sep 17 00:00:00 2001 From: Jaspreet-singh-1032 Date: Sun, 26 Mar 2023 21:59:33 +0530 Subject: [PATCH 55/93] fixed flake8 issues and added html2text to setup.py dependencies --- example/winners/tests/test_utils.py | 1 - import_export_celery/tasks.py | 2 -- setup.cfg | 1 + setup.py | 2 +- 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/example/winners/tests/test_utils.py b/example/winners/tests/test_utils.py index e8565a1..1017f7e 100644 --- a/example/winners/tests/test_utils.py +++ b/example/winners/tests/test_utils.py @@ -1,6 +1,5 @@ from django.test import TestCase, override_settings -from django.urls import reverse from import_export_celery.utils import ( get_export_job_mail_subject, get_export_job_mail_template, diff --git a/import_export_celery/tasks.py b/import_export_celery/tasks.py index 73c99eb..6321fe4 100644 --- a/import_export_celery/tasks.py +++ b/import_export_celery/tasks.py @@ -7,9 +7,7 @@ from django.conf import settings from django.core.files.base import ContentFile from django.core.cache import cache -from django.core.mail import send_mail -from django.urls import reverse from django.utils.encoding import force_str from django.utils.translation import gettext_lazy as _ diff --git a/setup.cfg b/setup.cfg index 406b63e..8d4f8ec 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,7 @@ [flake8] max-line-length = 150 exclude = + pyenv/*, env/*, env-dj19/*, *migrations/*, diff --git a/setup.py b/setup.py index df41556..142d237 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ here = os.path.abspath(os.path.dirname(__file__)) -requires = ["Django", "django-import-export", "django-author"] +requires = ["Django", "django-import-export", "django-author", "html2text"] try: version = subprocess.check_output( From d6243e7df6d95394c4bffd39940cda0759521e64 Mon Sep 17 00:00:00 2001 From: Jaspreet singh <69707565+Jaspreet-singh-1032@users.noreply.github.com> Date: Mon, 27 Mar 2023 22:20:16 +0530 Subject: [PATCH 56/93] added documentation --- README.rst | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/README.rst b/README.rst index ef4c7e6..5388fb2 100644 --- a/README.rst +++ b/README.rst @@ -141,6 +141,7 @@ As with imports, a fully configured example project can be found in the `example user=OuterRef("pk")).values("type")[:1]) 4. Done! + Performing exports with celery ------------------------------ @@ -156,6 +157,44 @@ Performing exports with celery 6. Click on the link near the bottom of the page titled `Exported file`. + + +Customizing email template for export job completion email +--------------------------------------------------------- + +By default this is the subject and template used to send the email + + + :: + + Subject: 'Django: Export job completed' + Email template: 'email/export_job_completion.html' + + +The default email template can be found `here `__ + +The default email subject and template can be customized by overriding these values from django settings:- + + + :: + + EXPORT_JOB_COMPLETION_MAIL_SUBJECT="Your custom subject" + EXPORT_JOB_COMPLETION_MAIL_TEMPLATE="path_to_folder/your_custom_template.html" + + +The email template will get some context variables that you can use to customize your template. + + + :: + + { + export_job: The current instance of ExportJob model + app_label: export_job.app_label + model: export_job.model + link: A link to go to the export_job instance on django admin + } + + For developers of this library ------------------------------ From 256acd8ff1ebf913fd6e524f45ea7b6946610528 Mon Sep 17 00:00:00 2001 From: Jaspreet singh <69707565+Jaspreet-singh-1032@users.noreply.github.com> Date: Tue, 28 Mar 2023 18:28:44 +0530 Subject: [PATCH 57/93] error fix in readme --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 5388fb2..e14a932 100644 --- a/README.rst +++ b/README.rst @@ -160,7 +160,7 @@ Performing exports with celery Customizing email template for export job completion email ---------------------------------------------------------- +---------------------------------------------------------- By default this is the subject and template used to send the email From 87bb13f248e6f9dc190b7ce24a77111ce5dd6284 Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sat, 8 Apr 2023 09:14:30 +0200 Subject: [PATCH 58/93] Weird typo in code of conduct :O --- CODE_OF_CONDUCT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index bb32606..55f0d7a 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1 +1 @@ -Please follow the spirit of [The PSF code of conduct](https://www.python.org/psf/conduct/) and try not to be nice. +Please follow the spirit of [The PSF code of conduct](https://www.python.org/psf/conduct/) and try to be nice. From 65ed15a0612560ab9ec990039c051b1e9b1dcbc5 Mon Sep 17 00:00:00 2001 From: MPinto Date: Wed, 17 May 2023 22:44:08 +0100 Subject: [PATCH 59/93] added translation in portuguese --- import_export_celery/admin.py | 2 +- .../locale/pt/LC_MESSAGES/django.mo | Bin 0 -> 2679 bytes .../locale/pt/LC_MESSAGES/django.po | 150 ++++++++++++++++++ ...8_alter_exportjob_id_alter_importjob_id.py | 23 +++ import_export_celery/models/exportjob.py | 5 + import_export_celery/models/importjob.py | 12 +- 6 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 import_export_celery/locale/pt/LC_MESSAGES/django.mo create mode 100644 import_export_celery/locale/pt/LC_MESSAGES/django.po create mode 100644 import_export_celery/migrations/0008_alter_exportjob_id_alter_importjob_id.py diff --git a/import_export_celery/admin.py b/import_export_celery/admin.py index 52807c7..3e1ea08 100644 --- a/import_export_celery/admin.py +++ b/import_export_celery/admin.py @@ -9,6 +9,7 @@ class JobWithStatusMixin: + @admin.display(description=_("Job status info")) def job_status_info(self, obj): job_status = cache.get(self.direction + "_job_status_%s" % obj.pk) if job_status: @@ -18,7 +19,6 @@ def job_status_info(self, obj): class ImportJobForm(forms.ModelForm): - model = forms.ChoiceField(label=_("Name of model to import to")) class Meta: diff --git a/import_export_celery/locale/pt/LC_MESSAGES/django.mo b/import_export_celery/locale/pt/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..52405db1d731a7c13b37bd28e2dc1783df46713e GIT binary patch literal 2679 zcmaKtyKfvt9LEP@NOHtHf_WtYe!L=Ms1t z^P6B5{0bZbe*~Wae*szEA0W&72RsQL7!cwZcpBt$b0FWl4zj%)e*bfj^?waM4c-G^ z10VSLL$HSV-+un~6GA+P`54H0=D>RXW($* z_c4&qp9eWFA9=PxzV|7}IsF!#0e=EHE`ta%$LR#fdPe*_1mU(gf`PU^#J87{D6el-Keb;Mu zc}u%CHB_YRwwT9FmR(n*V-~MMF>h=v9jj)!ez#D*-){Hr6`7K2m%<=cCDbr+CsL3+ zMGH+z4Q;hmG9|9aO+{OZQYTq0b*yQqG-ZES0_*O-u#g)_-nrSr0l%p7cpw6P&aU@f z%VlWEU24NhNn6%Hmr5FjgP6zf>e{tsigcQL-?<52%CL*8rp~6iEG3;Zjabx49&-v1 z_{w2C(7r5VwQtV$Z0f=xXT*xKO+=kSyY2JPT`CTVRh62|Hu7|2DFTNW`ig+@Vl^vg z#ICQYBqW$3u^LMq6~|p$r)3r46k%58MyzRp`!XWjzE&Pv#gUm&|<}!4b^bLLKxgoHq|B>r^>40LJOACmJWlNtd$1q2Fokg zf>pJt`A~3KIs|vLIyx3q&jz*gG+G-!d+xnzty--t%G3qxRwijAow4I|Stc4^$V!x< zu0QB7!b>f7dl>Fr#D%1l$(9P%m5iaNoR3q-eKNCJSz1_{>zP*@u2yDE;#2}H+Z~wU z)NMD?iKI>@*mavKH+g-1KDf|3$JR8J4d%MVbfK>n4LFG}=mAgx5ERR3LJ78MPrpmG^R)-Hmk5PVvP-Ji-Z~zI9C7TbbT8 z(3L`0k$xE(-#&61OZEOtQ5*k%rYC2*lv%jkG`g%-IYn#e8#+Eiw=$W8W=hN=NIQ2; z22H+?z}%kydoL{H-yR>zd`EfIKW?!c3U5(i1;V&HfV=m)8+icxcCL~1!Sc(nu4awYq5MOOf+#paNw2_*mKkZ@x4GEjw+EBO&6|BW)o7+`8 zm)qa3^4jVaQ-38Dg|}oA#oD_E}z4jm)C$OUj&%^c`H2Mc%lqeNmJW ztVJ=ER`0FEWK-jM7W=m5#q|7q^addmdJ`gjqccULLt44fDg2S{4Ha5#79)E6ClNV( bl(6j{+Fes=hcz@WmMZ%SLv%~MSLFWz6)g9t literal 0 HcmV?d00001 diff --git a/import_export_celery/locale/pt/LC_MESSAGES/django.po b/import_export_celery/locale/pt/LC_MESSAGES/django.po new file mode 100644 index 0000000..268d022 --- /dev/null +++ b/import_export_celery/locale/pt/LC_MESSAGES/django.po @@ -0,0 +1,150 @@ +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Dan , 2020. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-05-17 20:55+0000\n" +"PO-Revision-Date: 2023-05-17 21:56+0100\n" +"Last-Translator: Daniel Pluth \n" +"Language-Team: \n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 3.3.1\n" + +#: import_export_celery/admin.py:12 +msgid "Job status info" +msgstr "Informação do estado do trabalho" + +#: import_export_celery/admin.py:22 import_export_celery/models/importjob.py:62 +msgid "Name of model to import to" +msgstr "Nome do modelo a importar" + +#: import_export_celery/admin_actions.py:20 +msgid "Perform import" +msgstr "Confirmar importação" + +#: import_export_celery/admin_actions.py:29 +msgid "Perform dry import" +msgstr "Confirmar importação" + +#: import_export_celery/admin_actions.py:39 +msgid "Run export job" +msgstr "Correr trabalho de exportação" + +#: import_export_celery/admin_actions.py:67 +msgid "Export with celery" +msgstr "Exportar com o celery" + +#: import_export_celery/apps.py:7 +msgid "Import Export Celery" +msgstr "Importar ou Exportar com o celery" + +#: import_export_celery/models/exportjob.py:27 +msgid "exported file" +msgstr "ficheiro exportado" + +#: import_export_celery/models/exportjob.py:35 +#: import_export_celery/models/importjob.py:30 +msgid "Have we started processing the file? If so when?" +msgstr "Começou a processar o ficheiro? Se sim, quando?" + +#: import_export_celery/models/exportjob.py:42 +#: import_export_celery/models/importjob.py:67 +msgid "Status of the job" +msgstr "Estado do trabalho" + +#: import_export_celery/models/exportjob.py:48 +msgid "Format of file to be exported" +msgstr "Formato do ficheiro a ser exportado" + +#: import_export_celery/models/exportjob.py:55 +msgid "App label of model to export from" +msgstr "Nome da aplicação do modelo para exportar de" + +#: import_export_celery/models/exportjob.py:60 +msgid "Name of model to export from" +msgstr "Nome do modelo a exportar de" + +#: import_export_celery/models/exportjob.py:65 +msgid "Resource to use when exporting" +msgstr "Recurso a utilizar aquando da exportação" + +#: import_export_celery/models/exportjob.py:71 +msgid "JSON list of pks to export" +msgstr "Lista de ids em formato json para exportar" + +#: import_export_celery/models/exportjob.py:76 +msgid "Send me an email when this export job is complete" +msgstr "Enviar um email quando o trabalho de exportação estiver completo" + +#: import_export_celery/models/exportjob.py:81 +msgid "Site of origin" +msgstr "Site de origem" + +#: import_export_celery/models/exportjob.py:87 +msgid "Export job" +msgstr "Trabalho de exportação" + +#: import_export_celery/models/exportjob.py:88 +msgid "Export jobs" +msgstr "Trabalhos de exportação" + +#: import_export_celery/models/importjob.py:22 +msgid "File to be imported" +msgstr "Arquivo a ser importado" + +#: import_export_celery/models/importjob.py:37 +msgid "Has the import been completed? If so when?" +msgstr "A importação foi completa? Se sim, quando?" + +#: import_export_celery/models/importjob.py:44 +msgid "Format of file to be imported" +msgstr "Formato do ficheiro a ser importado" + +#: import_export_celery/models/importjob.py:49 +msgid "Summary of changes made by this import" +msgstr "Resumo das alterações feitas por esta importação" + +#: import_export_celery/models/importjob.py:56 +msgid "Errors" +msgstr "Erros" + +#: import_export_celery/models/importjob.py:73 +msgid "Import job" +msgstr "Trabalho de importação" + +#: import_export_celery/models/importjob.py:74 +msgid "Import jobs" +msgstr "Trabalhos de importação" + +#: import_export_celery/tasks.py:61 +#, python-format +msgid "Imported file has a wrong encoding: %s" +msgstr "O arquivo importado tem uma codificação errada: %s" + +#: import_export_celery/tasks.py:68 +#, python-format +msgid "Error reading file: %s" +msgstr "Erro a ler o ficheiro: %s" + +#: import_export_celery/tasks.py:101 +#, python-format +msgid "" +"Line: %s - %s\n" +"\t%s\n" +"%s" +msgstr "" +"Linha: %s - %s\n" +"\t%s\n" +"%s" + +#: import_export_celery/tasks.py:190 +#, python-format +msgid "Import error %s" +msgstr "Erro de importação %s" diff --git a/import_export_celery/migrations/0008_alter_exportjob_id_alter_importjob_id.py b/import_export_celery/migrations/0008_alter_exportjob_id_alter_importjob_id.py new file mode 100644 index 0000000..d8eab09 --- /dev/null +++ b/import_export_celery/migrations/0008_alter_exportjob_id_alter_importjob_id.py @@ -0,0 +1,23 @@ +# Generated by Django 4.0.6 on 2023-05-15 16:34 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('import_export_celery', '0007_auto_20210210_1831'), + ] + + operations = [ + migrations.AlterField( + model_name='exportjob', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='importjob', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + ] diff --git a/import_export_celery/models/exportjob.py b/import_export_celery/models/exportjob.py index c7324c0..0ec9c03 100644 --- a/import_export_celery/models/exportjob.py +++ b/import_export_celery/models/exportjob.py @@ -78,10 +78,15 @@ def __init__(self, *args, **kwargs): ) site_of_origin = models.TextField( + verbose_name=_("Site of origin"), max_length=255, default="", ) + class Meta: + verbose_name = _("Export job") + verbose_name_plural = _("Export jobs") + def get_resource_class(self): if self.resource: return ( diff --git a/import_export_celery/models/importjob.py b/import_export_celery/models/importjob.py index 7a4f56b..a9bef5b 100644 --- a/import_export_celery/models/importjob.py +++ b/import_export_celery/models/importjob.py @@ -53,6 +53,7 @@ class ImportJob(models.Model): ) errors = models.TextField( + verbose_name=_("Errors"), default="", blank=True, ) @@ -68,6 +69,10 @@ class ImportJob(models.Model): blank=True, ) + class Meta: + verbose_name = _("Import job") + verbose_name_plural = _("Import jobs") + @staticmethod def get_format_choices(): """returns choices of available import formats""" @@ -83,4 +88,9 @@ def importjob_post_save(sender, instance, **kwargs): if not instance.processing_initiated: instance.processing_initiated = timezone.now() instance.save() - transaction.on_commit(lambda: run_import_job.delay(instance.pk, dry_run=getattr(settings, "IMPORT_DRY_RUN_FIRST_TIME", True))) + transaction.on_commit( + lambda: run_import_job.delay( + instance.pk, + dry_run=getattr(settings, "IMPORT_DRY_RUN_FIRST_TIME", True), + ) + ) From 4e49658f8443e5b2fcae064e9c2c69ef6e7a43c7 Mon Sep 17 00:00:00 2001 From: Jack Linke Date: Sat, 27 May 2023 18:52:27 -0400 Subject: [PATCH 60/93] Add missing migration - Migration for changes in models was not present in most recent commit (dde72db) --- ...ptions_alter_importjob_options_and_more.py | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 import_export_celery/migrations/0009_alter_exportjob_options_alter_importjob_options_and_more.py diff --git a/import_export_celery/migrations/0009_alter_exportjob_options_alter_importjob_options_and_more.py b/import_export_celery/migrations/0009_alter_exportjob_options_alter_importjob_options_and_more.py new file mode 100644 index 0000000..317cb44 --- /dev/null +++ b/import_export_celery/migrations/0009_alter_exportjob_options_alter_importjob_options_and_more.py @@ -0,0 +1,41 @@ +# Generated by Django 4.1.9 on 2023-05-27 22:35 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('import_export_celery', '0008_alter_exportjob_id_alter_importjob_id'), + ] + + operations = [ + migrations.AlterModelOptions( + name='exportjob', + options={'verbose_name': 'Export job', 'verbose_name_plural': 'Export jobs'}, + ), + migrations.AlterModelOptions( + name='importjob', + options={'verbose_name': 'Import job', 'verbose_name_plural': 'Import jobs'}, + ), + migrations.AlterField( + model_name='exportjob', + name='id', + field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='exportjob', + name='site_of_origin', + field=models.TextField(default='', max_length=255, verbose_name='Site of origin'), + ), + migrations.AlterField( + model_name='importjob', + name='errors', + field=models.TextField(blank=True, default='', verbose_name='Errors'), + ), + migrations.AlterField( + model_name='importjob', + name='id', + field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + ] From 1cb285730594b5d820e831c03587d4503f0b9ce4 Mon Sep 17 00:00:00 2001 From: Urtzi Odriozola Date: Wed, 7 Jun 2023 16:36:34 +0200 Subject: [PATCH 61/93] Add Basque localization --- .../locale/eu/LC_MESSAGES/django.po | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 import_export_celery/locale/eu/LC_MESSAGES/django.po diff --git a/import_export_celery/locale/eu/LC_MESSAGES/django.po b/import_export_celery/locale/eu/LC_MESSAGES/django.po new file mode 100644 index 0000000..1d2097c --- /dev/null +++ b/import_export_celery/locale/eu/LC_MESSAGES/django.po @@ -0,0 +1,149 @@ +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Urtzi Odriozola , 2023. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-05-17 20:55+0000\n" +"PO-Revision-Date: 2023-06-07 21:56+0100\n" +"Last-Translator: Urtzi Odriozola \n" +"Language-Team: \n" +"Language: eu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: import_export_celery/admin.py:12 +msgid "Job status info" +msgstr "Lanaren egoera" + +#: import_export_celery/admin.py:22 import_export_celery/models/importjob.py:62 +msgid "Name of model to import to" +msgstr "Inportatu beharreko modeloaren izena" + +#: import_export_celery/admin_actions.py:20 +msgid "Perform import" +msgstr "Hasi inportazioa" + +#: import_export_celery/admin_actions.py:29 +msgid "Perform dry import" +msgstr "Hasi probako inportazioa" + +#: import_export_celery/admin_actions.py:39 +msgid "Run export job" +msgstr "Hasi esportazio lana" + +#: import_export_celery/admin_actions.py:67 +msgid "Export with celery" +msgstr "Exportatu celery bidez" + +#: import_export_celery/apps.py:7 +msgid "Import Export Celery" +msgstr "Inportatu - Esportatu Celery bidez" + +#: import_export_celery/models/exportjob.py:27 +msgid "exported file" +msgstr "esportatutako fitxategia" + +#: import_export_celery/models/exportjob.py:35 +#: import_export_celery/models/importjob.py:30 +msgid "Have we started processing the file? If so when?" +msgstr "Fitxategia prozesatzen hasi gara? Hala bada, noiz?" + +#: import_export_celery/models/exportjob.py:42 +#: import_export_celery/models/importjob.py:67 +msgid "Status of the job" +msgstr "Lanaren egoera" + +#: import_export_celery/models/exportjob.py:48 +msgid "Format of file to be exported" +msgstr "Esportatu beharreko fitxategiaren formatua" + +#: import_export_celery/models/exportjob.py:55 +msgid "App label of model to export from" +msgstr "Esportatu beharreko modeloaren aplikazio izena" + +#: import_export_celery/models/exportjob.py:60 +msgid "Name of model to export from" +msgstr "Esportatu beharreko modeloaren izena" + +#: import_export_celery/models/exportjob.py:65 +msgid "Resource to use when exporting" +msgstr "Esportatzeko erabili beharreko baliabidea" + +#: import_export_celery/models/exportjob.py:71 +msgid "JSON list of pks to export" +msgstr "Esportatzeko ID-en JSON zerrenda" + +#: import_export_celery/models/exportjob.py:76 +msgid "Send me an email when this export job is complete" +msgstr "Bidali eposta bat esportazio lan hau amaitzen denean" + +#: import_export_celery/models/exportjob.py:81 +msgid "Site of origin" +msgstr "Jatorrizko gunea" + +#: import_export_celery/models/exportjob.py:87 +msgid "Export job" +msgstr "Esportazio lana" + +#: import_export_celery/models/exportjob.py:88 +msgid "Export jobs" +msgstr "Esportazio lanak" + +#: import_export_celery/models/importjob.py:22 +msgid "File to be imported" +msgstr "Inportatu beharreko fitxategia" + +#: import_export_celery/models/importjob.py:37 +msgid "Has the import been completed? If so when?" +msgstr "Inportazioa amaitu da? Hala bada, noiz?" + +#: import_export_celery/models/importjob.py:44 +msgid "Format of file to be imported" +msgstr "Inportatu beharreko fitxategiaren formatua" + +#: import_export_celery/models/importjob.py:49 +msgid "Summary of changes made by this import" +msgstr "Inportazio honek eginiko aldaketen laburpena" + +#: import_export_celery/models/importjob.py:56 +msgid "Errors" +msgstr "Erroreak" + +#: import_export_celery/models/importjob.py:73 +msgid "Import job" +msgstr "Inportazio lana" + +#: import_export_celery/models/importjob.py:74 +msgid "Import jobs" +msgstr "Inportazio lanak" + +#: import_export_celery/tasks.py:61 +#, python-format +msgid "Imported file has a wrong encoding: %s" +msgstr "Inportatutako fitxategiak kodetze okerra du: %s" + +#: import_export_celery/tasks.py:68 +#, python-format +msgid "Error reading file: %s" +msgstr "Errorea fitxategia irakurtzean: %s" + +#: import_export_celery/tasks.py:101 +#, python-format +msgid "" +"Line: %s - %s\n" +"\t%s\n" +"%s" +msgstr "" +"Lerroa: %s - %s\n" +"\t%s\n" +"%s" + +#: import_export_celery/tasks.py:190 +#, python-format +msgid "Import error %s" +msgstr "Inportazio errorea %s" From 59288842505cae110b396c56afd2669f0541e601 Mon Sep 17 00:00:00 2001 From: Urtzi Odriozola Date: Wed, 7 Jun 2023 17:14:10 +0200 Subject: [PATCH 62/93] translatable email template --- .../templates/email/export_job_completion.html | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/import_export_celery/templates/email/export_job_completion.html b/import_export_celery/templates/email/export_job_completion.html index 845c8c5..ae90585 100644 --- a/import_export_celery/templates/email/export_job_completion.html +++ b/import_export_celery/templates/email/export_job_completion.html @@ -1,14 +1,15 @@ +{% load i18n %} - + - Document + {% translate "Document" %} -

Your export job on model {{app_label}}.{{model}} has completed. You can download the file at the following link:

+

{% blocktranslate %}Your export job on model {{app_label}}.{{model}} has completed. You can download the file at the following link:{% endblocktranslate %}

{{link}} From 918410c4097663c650112e0fec9e63a34961ed90 Mon Sep 17 00:00:00 2001 From: Urtzi Odriozola Date: Wed, 7 Jun 2023 17:15:16 +0200 Subject: [PATCH 63/93] Optional function to exclude some DEFAULT_FORMATS --- import_export_celery/models/exportjob.py | 5 ++--- import_export_celery/tasks.py | 26 ++++++++++++++++-------- import_export_celery/utils.py | 22 ++++++++++++++++++-- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/import_export_celery/models/exportjob.py b/import_export_celery/models/exportjob.py index 0ec9c03..3eb01b3 100644 --- a/import_export_celery/models/exportjob.py +++ b/import_export_celery/models/exportjob.py @@ -12,9 +12,8 @@ from django.db.models.signals import post_save from django.utils.translation import gettext_lazy as _ -from import_export.formats.base_formats import DEFAULT_FORMATS - from ..tasks import run_export_job +from ..utils import get_formats @with_author @@ -127,7 +126,7 @@ def get_format_choices(): """returns choices of available export formats""" return [ (f.CONTENT_TYPE, f().get_title()) - for f in DEFAULT_FORMATS + for f in get_formats() if f().can_export() ] diff --git a/import_export_celery/tasks.py b/import_export_celery/tasks.py index 6321fe4..8869a4c 100644 --- a/import_export_celery/tasks.py +++ b/import_export_celery/tasks.py @@ -11,11 +11,9 @@ from django.utils.encoding import force_str from django.utils.translation import gettext_lazy as _ -from import_export.formats.base_formats import DEFAULT_FORMATS - from . import models from .model_config import ModelConfig -from .utils import send_export_job_completion_mail +from .utils import send_export_job_completion_mail, get_formats from celery.utils.log import get_task_logger import logging @@ -39,7 +37,7 @@ def change_job_status(job, direction, job_status, dry_run=False): def get_format(job): - for format in DEFAULT_FORMATS: + for format in get_formats(): if job.format == format.CONTENT_TYPE: return format() break @@ -58,7 +56,9 @@ def _run_import_job(import_job, dry_run=True): data = force_str(data, "utf8") dataset = import_format.create_dataset(data) except UnicodeDecodeError as e: - import_job.errors += _("Imported file has a wrong encoding: %s" % e) + "\n" + import_job.errors += ( + _("Imported file has a wrong encoding: %s" % e) + "\n" + ) change_job_status( import_job, "import", "Imported file has a wrong encoding", dry_run ) @@ -69,7 +69,9 @@ def _run_import_job(import_job, dry_run=True): change_job_status(import_job, "import", "Error reading file", dry_run) import_job.save() return - change_job_status(import_job, "import", "2/5 Processing import data", dry_run) + change_job_status( + import_job, "import", "2/5 Processing import data", dry_run + ) class Resource(model_config.resource): def __init__(self, import_job, *args, **kwargs): @@ -93,7 +95,9 @@ def before_import_row(self, row, **kwargs): skip_diff = resource._meta.skip_diff or resource._meta.skip_html_diff result = resource.import_data(dataset, dry_run=dry_run) - change_job_status(import_job, "import", "4/5 Generating import summary", dry_run) + change_job_status( + import_job, "import", "4/5 Generating import summary", dry_run + ) for error in result.base_errors: import_job.errors += f"\n{error.error}\n{error.traceback}\n" for line, errors in result.row_errors(): @@ -111,7 +115,9 @@ def before_import_row(self, row, **kwargs): summary += '' summary += "" summary += "" - summary += '' # TODO refactor the existing template so we can use it for this + summary += ( # TODO refactor the existing template so we can use it for this + '
' + ) # https://github.com/django-import-export/django-import-export/blob/6575c3e1d89725701e918696fbc531aeb192a6f7/import_export/templates/admin/import_export/import.html if not result.invalid_rows and not skip_diff: cols = lambda row: "" ) else: - cols = lambda row: "" + "
".join([field for field in row.diff]) @@ -133,7 +139,9 @@ def before_import_row(self, row, **kwargs): + "
".join([str(field) for field in row.values]) + cols = lambda row: "".join( + [str(field) for field in row.values] + ) cols_error = lambda row: "".join( [ "" diff --git a/import_export_celery/utils.py b/import_export_celery/utils.py index f1d4f1d..c350080 100644 --- a/import_export_celery/utils.py +++ b/import_export_celery/utils.py @@ -3,9 +3,25 @@ from django.template.loader import get_template from django.conf import settings from django.urls import reverse +from import_export.formats.base_formats import DEFAULT_FORMATS DEFAULT_EXPORT_JOB_COMPLETION_MAIL_SUBJECT = "Django: Export job completed" -DEFAULT_EXPORT_JOB_COMPLETION_MAIL_TEMPLATE = "email/export_job_completion.html" +DEFAULT_EXPORT_JOB_COMPLETION_MAIL_TEMPLATE = ( + "email/export_job_completion.html" +) +EXCLUDED_EXPORT_FORMATS = getattr( + settings, + "EXCLUDED_EXPORT_FORMATS", + [], +) + + +def get_formats(): + formats = [] + for format in DEFAULT_FORMATS: + if format.CONTENT_TYPE not in EXCLUDED_EXPORT_FORMATS: + formats.append(format) + return formats def build_html_and_text_message(template_name, context={}): @@ -60,7 +76,9 @@ def send_export_job_completion_mail(export_job): template_name = get_export_job_mail_template() context = get_export_job_mail_context(export_job) context.update({"export_job": export_job}) - html_message, text_message = build_html_and_text_message(template_name, context) + html_message, text_message = build_html_and_text_message( + template_name, context + ) send_mail( subject=subject, message=text_message, From f7a01be4066bc5c2e3eb0c52b15853d8a538ad60 Mon Sep 17 00:00:00 2001 From: Urtzi Odriozola Date: Wed, 7 Jun 2023 17:17:53 +0200 Subject: [PATCH 64/93] function rewrited in more pythonic way --- import_export_celery/utils.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/import_export_celery/utils.py b/import_export_celery/utils.py index c350080..c307449 100644 --- a/import_export_celery/utils.py +++ b/import_export_celery/utils.py @@ -17,11 +17,11 @@ def get_formats(): - formats = [] - for format in DEFAULT_FORMATS: - if format.CONTENT_TYPE not in EXCLUDED_EXPORT_FORMATS: - formats.append(format) - return formats + return [ + format + for format in DEFAULT_FORMATS + if format.CONTENT_TYPE not in EXCLUDED_EXPORT_FORMATS + ] def build_html_and_text_message(template_name, context={}): From 03dc4637af54ccdb963aefdcb1d6c14ab15c3ab2 Mon Sep 17 00:00:00 2001 From: Urtzi Odriozola Date: Wed, 7 Jun 2023 17:55:03 +0200 Subject: [PATCH 65/93] get_formats conditional fixed --- import_export_celery/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/import_export_celery/utils.py b/import_export_celery/utils.py index c307449..3db3d99 100644 --- a/import_export_celery/utils.py +++ b/import_export_celery/utils.py @@ -20,7 +20,8 @@ def get_formats(): return [ format for format in DEFAULT_FORMATS - if format.CONTENT_TYPE not in EXCLUDED_EXPORT_FORMATS + if format.TABLIB_MODULE.split(".")[-1].strip("_") + not in EXCLUDED_EXPORT_FORMATS ] From 4ab9cd093adcc2707b12fd99eb77af1b5d31a6fd Mon Sep 17 00:00:00 2001 From: Urtzi Odriozola Date: Thu, 8 Jun 2023 08:32:19 +0200 Subject: [PATCH 66/93] removed translatable template + black --- .../templates/email/export_job_completion.html | 7 +++---- setup.py | 17 ++++++++++++----- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/import_export_celery/templates/email/export_job_completion.html b/import_export_celery/templates/email/export_job_completion.html index ae90585..845c8c5 100644 --- a/import_export_celery/templates/email/export_job_completion.html +++ b/import_export_celery/templates/email/export_job_completion.html @@ -1,15 +1,14 @@ -{% load i18n %} - + - {% translate "Document" %} + Document -

{% blocktranslate %}Your export job on model {{app_label}}.{{model}} has completed. You can download the file at the following link:{% endblocktranslate %}

+

Your export job on model {{app_label}}.{{model}} has completed. You can download the file at the following link:

{{link}} diff --git a/setup.py b/setup.py index 142d237..415e322 100644 --- a/setup.py +++ b/setup.py @@ -9,9 +9,11 @@ requires = ["Django", "django-import-export", "django-author", "html2text"] try: - version = subprocess.check_output( - ["git", "describe", "--abbrev=0", "--tags"] - ).decode("utf-8").strip() + version = ( + subprocess.check_output(["git", "describe", "--abbrev=0", "--tags"]) + .decode("utf-8") + .strip() + ) except subprocess.CalledProcessError: version = "0.dev" + datetime.datetime.now().strftime("%Y%m%d%H%M%S") @@ -23,9 +25,14 @@ url="https://github.com/auto-mat/django-import-export-celery", download_url="http://pypi.python.org/pypi/django-import-export-celery/", description="Process long running django imports and exports in celery", - long_description=codecs.open(os.path.join(here, "README.rst"), "r", "utf-8").read(), + long_description=codecs.open( + os.path.join(here, "README.rst"), "r", "utf-8" + ).read(), long_description_content_type="text/x-rst", - license="License :: OSI Approved :: GNU Lesser General Public License v3.0 or later (LGPLv3.0+)", + license=( + "License :: OSI Approved :: GNU Lesser General Public License v3.0 or" + " later (LGPLv3.0+)" + ), install_requires=requires, packages=find_packages(), include_package_data=True, From 393752818c1df501b45b8c1c2060045d983cf7b6 Mon Sep 17 00:00:00 2001 From: Jaspreet-singh-1032 Date: Fri, 7 Jul 2023 21:03:52 +0530 Subject: [PATCH 67/93] treat templates and locale directories as sub-module --- import_export_celery/locale/pt/LC_MESSAGES/__init__.py | 0 import_export_celery/templates/email/__init__.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 import_export_celery/locale/pt/LC_MESSAGES/__init__.py create mode 100644 import_export_celery/templates/email/__init__.py diff --git a/import_export_celery/locale/pt/LC_MESSAGES/__init__.py b/import_export_celery/locale/pt/LC_MESSAGES/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/import_export_celery/templates/email/__init__.py b/import_export_celery/templates/email/__init__.py new file mode 100644 index 0000000..e69de29 From 0df1fdf334f244ccfb95813914523a07aa4005d3 Mon Sep 17 00:00:00 2001 From: Jaspreet-singh-1032 Date: Sun, 9 Jul 2023 19:44:21 +0530 Subject: [PATCH 68/93] added MANIFEST.in to include data files --- MANIFEST.in | 3 +++ import_export_celery/locale/pt/LC_MESSAGES/__init__.py | 0 import_export_celery/templates/email/__init__.py | 0 3 files changed, 3 insertions(+) create mode 100644 MANIFEST.in delete mode 100644 import_export_celery/locale/pt/LC_MESSAGES/__init__.py delete mode 100644 import_export_celery/templates/email/__init__.py diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..da3ca87 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,3 @@ +recursive-include import_export_celery/static *.js *.css *.map *.png *.ico *.eot *.svg *.ttf *.woff *.woff2 +recursive-include import_export_celery/templates *.html +recursive-include import_export_celery/locale *.mo diff --git a/import_export_celery/locale/pt/LC_MESSAGES/__init__.py b/import_export_celery/locale/pt/LC_MESSAGES/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/import_export_celery/templates/email/__init__.py b/import_export_celery/templates/email/__init__.py deleted file mode 100644 index e69de29..0000000 From b4232e01e4e35c43c3e5f96fbb7ca0986a0d28b4 Mon Sep 17 00:00:00 2001 From: Urtzi Odriozola Date: Mon, 17 Jul 2023 09:22:50 +0200 Subject: [PATCH 69/93] Necesary changes for the PR acceptance --- README.rst | 13 ++++++++++++- import_export_celery/utils.py | 6 +++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index e14a932..1526216 100644 --- a/README.rst +++ b/README.rst @@ -158,6 +158,17 @@ Performing exports with celery 6. Click on the link near the bottom of the page titled `Exported file`. +Excluding export file formats in the admin site +----------------------------------------------- + +All available file formats to export are taken from the `Tablib project `. + +To exclude or disable file formats from the admin site, configure `IMPORT_EXPORT_CELERY_EXCLUDED_FORMATS` django settings variable. This variable is a list of format strings written in lower case. + + :: + + IMPORT_EXPORT_CELERY_EXCLUDED_FORMATS = ["csv", "xls"] + Customizing email template for export job completion email ---------------------------------------------------------- @@ -186,7 +197,7 @@ The email template will get some context variables that you can use to customize :: - + { export_job: The current instance of ExportJob model app_label: export_job.app_label diff --git a/import_export_celery/utils.py b/import_export_celery/utils.py index 3db3d99..2cd4659 100644 --- a/import_export_celery/utils.py +++ b/import_export_celery/utils.py @@ -9,9 +9,9 @@ DEFAULT_EXPORT_JOB_COMPLETION_MAIL_TEMPLATE = ( "email/export_job_completion.html" ) -EXCLUDED_EXPORT_FORMATS = getattr( +IMPORT_EXPORT_CELERY_EXCLUDED_FORMATS = getattr( settings, - "EXCLUDED_EXPORT_FORMATS", + "IMPORT_EXPORT_CELERY_EXCLUDED_FORMATS", [], ) @@ -21,7 +21,7 @@ def get_formats(): format for format in DEFAULT_FORMATS if format.TABLIB_MODULE.split(".")[-1].strip("_") - not in EXCLUDED_EXPORT_FORMATS + not in IMPORT_EXPORT_CELERY_EXCLUDED_FORMATS ] From aa8fb58e0164d3110409389d9804289c9aaa66ce Mon Sep 17 00:00:00 2001 From: Urtzi Odriozola Date: Mon, 17 Jul 2023 09:27:10 +0200 Subject: [PATCH 70/93] fix README tablib URL --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 1526216..b5be367 100644 --- a/README.rst +++ b/README.rst @@ -161,7 +161,7 @@ Performing exports with celery Excluding export file formats in the admin site ----------------------------------------------- -All available file formats to export are taken from the `Tablib project `. +All available file formats to export are taken from the `Tablib project `__. To exclude or disable file formats from the admin site, configure `IMPORT_EXPORT_CELERY_EXCLUDED_FORMATS` django settings variable. This variable is a list of format strings written in lower case. From b3273d37b158ec481e076ab60207c3c66f683b01 Mon Sep 17 00:00:00 2001 From: Zach Bellay Date: Fri, 28 Jul 2023 18:37:54 -0700 Subject: [PATCH 71/93] add customizable storage backend configurable via IMPORT_EXPORT_CELERYY_STORAGE --- README.rst | 12 ++++++++++-- example/project/settings.py | 1 + import_export_celery/fields.py | 13 +++++++++++++ import_export_celery/models/exportjob.py | 3 ++- import_export_celery/models/importjob.py | 5 +++-- 5 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 import_export_celery/fields.py diff --git a/README.rst b/README.rst index b5be367..5929040 100644 --- a/README.rst +++ b/README.rst @@ -169,6 +169,14 @@ To exclude or disable file formats from the admin site, configure `IMPORT_EXPORT IMPORT_EXPORT_CELERY_EXCLUDED_FORMATS = ["csv", "xls"] +Customizing File Storage Backend +-------------------------------- + +Define a custom storage backend by adding the `IMPORT_EXPORT_CELERY_STORAGE` to your Django settings. For instance: + + :: + + IMPORT_EXPORT_CELERY_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" Customizing email template for export job completion email ---------------------------------------------------------- @@ -215,10 +223,10 @@ Before submitting a PR please run `flake8` and (in the examples directory) `pyth Please note, that you need to restart celery for changes to propogate to the workers. Do this with `docker-compose down celery`, `docker-compose up celery`. -Comercial support +Commercial support ----------------- -Comercial support is provided by `gradesta s.r.o `_. +Commercial support is provided by `gradesta s.r.o `_. Credits ------- diff --git a/example/project/settings.py b/example/project/settings.py index 58b6c6a..f5fce3f 100644 --- a/example/project/settings.py +++ b/example/project/settings.py @@ -135,3 +135,4 @@ } EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" +IMPORT_EXPORT_CELERY_STORAGE = "django.core.files.storage.FileSystemStorage" diff --git a/import_export_celery/fields.py b/import_export_celery/fields.py new file mode 100644 index 0000000..53ad05e --- /dev/null +++ b/import_export_celery/fields.py @@ -0,0 +1,13 @@ +from django.conf import settings +from django.core.files.storage import get_storage_class +from django.db import models + + +class ImportExportFileField(models.FileField): + def __init__(self, *args, **kwargs): + # If the user has specified a custom storage backend, use it. + if settings.IMPORT_EXPORT_CELERY_STORAGE: + storage_class = get_storage_class(settings.IMPORT_EXPORT_CELERY_STORAGE) + kwargs["storage"] = storage_class() + + super().__init__(*args, **kwargs) diff --git a/import_export_celery/models/exportjob.py b/import_export_celery/models/exportjob.py index 3eb01b3..66f5691 100644 --- a/import_export_celery/models/exportjob.py +++ b/import_export_celery/models/exportjob.py @@ -12,6 +12,7 @@ from django.db.models.signals import post_save from django.utils.translation import gettext_lazy as _ +from ..fields import ImportExportFileField from ..tasks import run_export_job from ..utils import get_formats @@ -22,7 +23,7 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._content_type = None - file = models.FileField( + file = ImportExportFileField( verbose_name=_("exported file"), upload_to="django-import-export-celery-export-jobs", blank=False, diff --git a/import_export_celery/models/importjob.py b/import_export_celery/models/importjob.py index a9bef5b..c6d3a6d 100644 --- a/import_export_celery/models/importjob.py +++ b/import_export_celery/models/importjob.py @@ -13,12 +13,13 @@ from import_export.formats.base_formats import DEFAULT_FORMATS +from ..fields import ImportExportFileField from ..tasks import run_import_job @with_author class ImportJob(models.Model): - file = models.FileField( + file = ImportExportFileField( verbose_name=_("File to be imported"), upload_to="django-import-export-celery-import-jobs", blank=False, @@ -45,7 +46,7 @@ class ImportJob(models.Model): max_length=255, ) - change_summary = models.FileField( + change_summary = ImportExportFileField( verbose_name=_("Summary of changes made by this import"), upload_to="django-import-export-celery-import-change-summaries", blank=True, From a08f82d47023254958ee0c13672507c3ab259330 Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sat, 29 Jul 2023 12:14:03 +0200 Subject: [PATCH 72/93] Underline two short errors are sadistic bs. --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 5929040..c33afd8 100644 --- a/README.rst +++ b/README.rst @@ -224,7 +224,7 @@ Before submitting a PR please run `flake8` and (in the examples directory) `pyth Please note, that you need to restart celery for changes to propogate to the workers. Do this with `docker-compose down celery`, `docker-compose up celery`. Commercial support ------------------ +------------------ Commercial support is provided by `gradesta s.r.o `_. From e7bc39c03f524b12f965163f87eb9226b3c1939e Mon Sep 17 00:00:00 2001 From: Zach Bellay Date: Mon, 31 Jul 2023 11:21:22 -0700 Subject: [PATCH 73/93] Fix AttributeError if IMPORT_EXPORT_CELERY_STORAGE is not defined in django settings --- import_export_celery/fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/import_export_celery/fields.py b/import_export_celery/fields.py index 53ad05e..371b2a9 100644 --- a/import_export_celery/fields.py +++ b/import_export_celery/fields.py @@ -6,7 +6,7 @@ class ImportExportFileField(models.FileField): def __init__(self, *args, **kwargs): # If the user has specified a custom storage backend, use it. - if settings.IMPORT_EXPORT_CELERY_STORAGE: + if getattr(settings, "IMPORT_EXPORT_CELERY_STORAGE", None): storage_class = get_storage_class(settings.IMPORT_EXPORT_CELERY_STORAGE) kwargs["storage"] = storage_class() From 066bf85eeb4344689e4d6a622e7ee3a4bea8ad92 Mon Sep 17 00:00:00 2001 From: Zach Bellay Date: Mon, 31 Jul 2023 11:35:41 -0700 Subject: [PATCH 74/93] add configurable soft and hard time limits for import and export tasks --- README.rst | 17 ++++++++++++++++- example/project/settings.py | 8 ++++++++ import_export_celery/tasks.py | 12 ++++++++++-- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index c33afd8..cc34c71 100644 --- a/README.rst +++ b/README.rst @@ -58,7 +58,7 @@ By default a dry run of the import is initiated when the import object is create IMPORT_DRY_RUN_FIRST_TIME = False -Preforming an import +Performing an import -------------------- You will find an example django application that uses django-import-export-celery for importing data. There are instructions for running the example application in the example directory's README file. Once you have it running, you can perform an import with the following steps. @@ -178,6 +178,21 @@ Define a custom storage backend by adding the `IMPORT_EXPORT_CELERY_STORAGE` to IMPORT_EXPORT_CELERY_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" +Customizing Task Time Limits +---------------------------- + +By default, there is no time limit on celery import/export tasks. This can be customized by setting the following variables in your Django settings file. + + :: + + # set import time limits (in seconds) + IMPORT_EXPORT_CELERY_IMPORT_SOFT_TIME_LIMIT = 300 # 5 minutes + IMPORT_EXPORT_CELERY_IMPORT_HARD_TIME_LIMIT = 360 # 6 minutes + + # set export time limits (in seconds) + IMPORT_EXPORT_CELERY_EXPORT_SOFT_TIME_LIMIT = 300 # 5 minutes + IMPORT_EXPORT_CELERY_EXPORT_HARD_TIME_LIMIT = 360 # 6 minutes + Customizing email template for export job completion email ---------------------------------------------------------- diff --git a/example/project/settings.py b/example/project/settings.py index f5fce3f..10dc7ee 100644 --- a/example/project/settings.py +++ b/example/project/settings.py @@ -136,3 +136,11 @@ EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" IMPORT_EXPORT_CELERY_STORAGE = "django.core.files.storage.FileSystemStorage" + +# Default import time limits (in seconds) +IMPORT_EXPORT_CELERY_IMPORT_SOFT_TIME_LIMIT = 300 # 5 minutes +IMPORT_EXPORT_CELERY_IMPORT_HARD_TIME_LIMIT = 360 # 6 minutes + +# Default export time limits (in seconds) +IMPORT_EXPORT_CELERY_EXPORT_SOFT_TIME_LIMIT = 300 # 5 minutes +IMPORT_EXPORT_CELERY_EXPORT_HARD_TIME_LIMIT = 360 # 6 minutes diff --git a/import_export_celery/tasks.py b/import_export_celery/tasks.py index 8869a4c..ef3083b 100644 --- a/import_export_celery/tasks.py +++ b/import_export_celery/tasks.py @@ -188,7 +188,11 @@ def before_import_row(self, row, **kwargs): import_job.save() -@shared_task(bind=False) +@shared_task( + bind=False, + soft_time_limit=getattr(settings, "IMPORT_EXPORT_CELERY_IMPORT_SOFT_TIME_LIMIT", 0), + time_limit=getattr(settings, "IMPORT_EXPORT_CELERY_IMPORT_HARD_TIME_LIMIT", 0), +) def run_import_job(pk, dry_run=True): log.info(f"Importing {pk} dry-run {dry_run}") import_job = models.ImportJob.objects.get(pk=pk) @@ -201,7 +205,11 @@ def run_import_job(pk, dry_run=True): return -@shared_task(bind=False) +@shared_task( + bind=False, + soft_time_limit=getattr(settings, "IMPORT_EXPORT_CELERY_EXPORT_SOFT_TIME_LIMIT", 0), + time_limit=getattr(settings, "IMPORT_EXPORT_CELERY_EXPORT_HARD_TIME_LIMIT", 0), +) def run_export_job(pk): log.info("Exporting %s" % pk) export_job = models.ExportJob.objects.get(pk=pk) From a8738b1dcf2d3c8b0ef00c39dca74f5c31b0c054 Mon Sep 17 00:00:00 2001 From: Jaspreet-singh-1032 Date: Sat, 5 Aug 2023 20:51:56 +0530 Subject: [PATCH 75/93] delete uploaded file on import job delete --- example/winners/tests/test_models.py | 18 ++++++++++++++++++ import_export_celery/models/importjob.py | 12 +++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 example/winners/tests/test_models.py diff --git a/example/winners/tests/test_models.py b/example/winners/tests/test_models.py new file mode 100644 index 0000000..0ebc943 --- /dev/null +++ b/example/winners/tests/test_models.py @@ -0,0 +1,18 @@ +import os +from django.test import TestCase +from django.core.files.base import ContentFile + +from import_export_celery.models.importjob import ImportJob + + +class ImportJobTestCases(TestCase): + + def test_delete_file_on_job_delete(self): + job = ImportJob.objects.create( + file=ContentFile(b"", "file.csv"), + ) + file_path = job.file.path + assert os.path.exists(file_path) + job.delete() + assert not os.path.exists(file_path) + assert not ImportJob.objects.filter(id=job.id).exists() diff --git a/import_export_celery/models/importjob.py b/import_export_celery/models/importjob.py index c6d3a6d..1ba0f56 100644 --- a/import_export_celery/models/importjob.py +++ b/import_export_celery/models/importjob.py @@ -8,7 +8,7 @@ from django.db import models, transaction from django.dispatch import receiver -from django.db.models.signals import post_save +from django.db.models.signals import post_save, post_delete from django.utils.translation import gettext_lazy as _ from import_export.formats.base_formats import DEFAULT_FORMATS @@ -95,3 +95,13 @@ def importjob_post_save(sender, instance, **kwargs): dry_run=getattr(settings, "IMPORT_DRY_RUN_FIRST_TIME", True), ) ) + + +@receiver(post_delete, sender=ImportJob) +def auto_delete_file_on_delete(sender, instance, **kwargs): + """ + Deletes file related to the import job + """ + if instance.file: + instance.file.delete() + instance.delete() From f6744d97a82ebde915c2980a53571b91b39a416d Mon Sep 17 00:00:00 2001 From: Jaspreet-singh-1032 Date: Sat, 5 Aug 2023 21:34:38 +0530 Subject: [PATCH 76/93] added try except for import file delete --- import_export_celery/models/importjob.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/import_export_celery/models/importjob.py b/import_export_celery/models/importjob.py index 1ba0f56..74e545e 100644 --- a/import_export_celery/models/importjob.py +++ b/import_export_celery/models/importjob.py @@ -16,6 +16,10 @@ from ..fields import ImportExportFileField from ..tasks import run_import_job +import logging + +logger = logging.getLogger(__name__) + @with_author class ImportJob(models.Model): @@ -103,5 +107,10 @@ def auto_delete_file_on_delete(sender, instance, **kwargs): Deletes file related to the import job """ if instance.file: - instance.file.delete() - instance.delete() + try: + instance.file.delete() + except Exception as e: + logger.error( + "Some error occurred while deleting ImportJob file: {0}".format(e) + ) + ImportJob.objects.filter(id=instance.id).delete() From d8357e76f750b1c34cd73943e1a976b01dc87df6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Szafra=C5=84ski?= Date: Fri, 13 Oct 2023 11:05:07 +0200 Subject: [PATCH 77/93] Fix: Lazy-initialize storage class to prevent unwanted migration generation --- import_export_celery/fields.py | 14 +++++---- .../migrations/0010_auto_20231013_0904.py | 29 +++++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 import_export_celery/migrations/0010_auto_20231013_0904.py diff --git a/import_export_celery/fields.py b/import_export_celery/fields.py index 371b2a9..7badc92 100644 --- a/import_export_celery/fields.py +++ b/import_export_celery/fields.py @@ -3,11 +3,15 @@ from django.db import models +def lazy_initialize_storage_class(): + # If the user has specified a custom storage backend, use it. + if getattr(settings, "IMPORT_EXPORT_CELERY_STORAGE", None): + storage_class = get_storage_class(settings.IMPORT_EXPORT_CELERY_STORAGE) + return storage_class() + return None + + class ImportExportFileField(models.FileField): def __init__(self, *args, **kwargs): - # If the user has specified a custom storage backend, use it. - if getattr(settings, "IMPORT_EXPORT_CELERY_STORAGE", None): - storage_class = get_storage_class(settings.IMPORT_EXPORT_CELERY_STORAGE) - kwargs["storage"] = storage_class() - + kwargs["storage"] = lazy_initialize_storage_class super().__init__(*args, **kwargs) diff --git a/import_export_celery/migrations/0010_auto_20231013_0904.py b/import_export_celery/migrations/0010_auto_20231013_0904.py new file mode 100644 index 0000000..c4ea04d --- /dev/null +++ b/import_export_celery/migrations/0010_auto_20231013_0904.py @@ -0,0 +1,29 @@ +# Generated by Django 3.2.18 on 2023-10-13 09:04 + +from django.db import migrations +import import_export_celery.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('import_export_celery', '0009_alter_exportjob_options_alter_importjob_options_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='exportjob', + name='file', + field=import_export_celery.fields.ImportExportFileField(max_length=255, storage=import_export_celery.fields.lazy_initialize_storage_class, upload_to='django-import-export-celery-export-jobs', verbose_name='exported file'), + ), + migrations.AlterField( + model_name='importjob', + name='change_summary', + field=import_export_celery.fields.ImportExportFileField(blank=True, null=True, storage=import_export_celery.fields.lazy_initialize_storage_class, upload_to='django-import-export-celery-import-change-summaries', verbose_name='Summary of changes made by this import'), + ), + migrations.AlterField( + model_name='importjob', + name='file', + field=import_export_celery.fields.ImportExportFileField(max_length=255, storage=import_export_celery.fields.lazy_initialize_storage_class, upload_to='django-import-export-celery-import-jobs', verbose_name='File to be imported'), + ), + ] From 90a34d50b73373c36468c4905517e06718296dd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Dlouh=C3=BD?= Date: Tue, 14 Nov 2023 12:29:09 +0100 Subject: [PATCH 78/93] add support for Django 4.2 storages --- import_export_celery/fields.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/import_export_celery/fields.py b/import_export_celery/fields.py index 7badc92..35dc3de 100644 --- a/import_export_celery/fields.py +++ b/import_export_celery/fields.py @@ -1,13 +1,17 @@ from django.conf import settings -from django.core.files.storage import get_storage_class +from django.core.files.storage import get_storage_class, storages from django.db import models def lazy_initialize_storage_class(): # If the user has specified a custom storage backend, use it. if getattr(settings, "IMPORT_EXPORT_CELERY_STORAGE", None): - storage_class = get_storage_class(settings.IMPORT_EXPORT_CELERY_STORAGE) - return storage_class() + try: + storage_class = get_storage_class(settings.IMPORT_EXPORT_CELERY_STORAGE) + return storage_class() + except (ImportError, TypeError): + return storages[settings.IMPORT_EXPORT_CELERY_STORAGE] + return None From f86afdb92770c2c95461fdeb50d3aeaad345da86 Mon Sep 17 00:00:00 2001 From: Joan Marc Soler Date: Mon, 19 Feb 2024 13:22:11 +0100 Subject: [PATCH 79/93] Manage custom storage class using django.core.files.storage.storages modules instead of deprecated method In Django documentation we can see that get_storage_class is deprecated in Django 5.1 and later. https://docs.djangoproject.com/en/5.0/ref/files/storage/#django.core.files.storage.get_storage_class Recommendation of Django is to use storages instead of get_storage_class. This leads to specify this file storage backend in STORAGES config settings instead of a new config variable. This commit allows also to keep using custom storage classe from older verions (4.2 and earlier) and prevents to crash when invalid storage class is provided, using the default one. Solves https://github.com/auto-mat/django-import-export-celery/issues/115 --- README.rst | 8 ++++++-- example/project/settings.py | 6 +++++- import_export_celery/fields.py | 25 +++++++++++++++++-------- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/README.rst b/README.rst index cc34c71..1bde213 100644 --- a/README.rst +++ b/README.rst @@ -172,11 +172,15 @@ To exclude or disable file formats from the admin site, configure `IMPORT_EXPORT Customizing File Storage Backend -------------------------------- -Define a custom storage backend by adding the `IMPORT_EXPORT_CELERY_STORAGE` to your Django settings. For instance: +Define a custom storage backend by adding the `IMPORT_EXPORT_CELERY_STORAGE` to your Django settings STORAGES definition. For instance: :: - IMPORT_EXPORT_CELERY_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" + STORAGES = { + "IMPORT_EXPORT_CELERY_STORAGE": { + "BACKEND": "storages.backends.s3boto3.S3Boto3Storage", + }, + } Customizing Task Time Limits ---------------------------- diff --git a/example/project/settings.py b/example/project/settings.py index 10dc7ee..3e7c5f6 100644 --- a/example/project/settings.py +++ b/example/project/settings.py @@ -89,6 +89,11 @@ }, } +STORAGES = { + "IMPORT_EXPORT_CELERY_STORAGE": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + }, +} # Password validation # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators @@ -135,7 +140,6 @@ } EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" -IMPORT_EXPORT_CELERY_STORAGE = "django.core.files.storage.FileSystemStorage" # Default import time limits (in seconds) IMPORT_EXPORT_CELERY_IMPORT_SOFT_TIME_LIMIT = 300 # 5 minutes diff --git a/import_export_celery/fields.py b/import_export_celery/fields.py index 35dc3de..bb7d725 100644 --- a/import_export_celery/fields.py +++ b/import_export_celery/fields.py @@ -1,18 +1,27 @@ from django.conf import settings -from django.core.files.storage import get_storage_class, storages from django.db import models def lazy_initialize_storage_class(): # If the user has specified a custom storage backend, use it. - if getattr(settings, "IMPORT_EXPORT_CELERY_STORAGE", None): + if settings.STORAGES.get("IMPORT_EXPORT_CELERY_STORAGE"): try: - storage_class = get_storage_class(settings.IMPORT_EXPORT_CELERY_STORAGE) - return storage_class() - except (ImportError, TypeError): - return storages[settings.IMPORT_EXPORT_CELERY_STORAGE] - - return None + # From Django 4.2 and later + from django.core.files.storage import storages + from django.core.files.storage.handler import InvalidStorageError + try: + storage_class = storages['IMPORT_EXPORT_CELERY_STORAGE'] + except InvalidStorageError: + from django.utils.module_loading import import_string + storage_class = settings.DEFAULT_FILE_STORAGE + storage_class = import_string(storage_class)() + except ImportError: + # Deprecated since Django 4.2, Removed in Django 5.1 + from django.core.files.storage import get_storage_class + storage_class = get_storage_class( + settings.STORAGES.get("IMPORT_EXPORT_CELERY_STORAGE")["BACKEND"] + )() + return storage_class class ImportExportFileField(models.FileField): From c4340d0a5621592df4fee314cdac59d3ec85f14b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 07:14:28 +0200 Subject: [PATCH 80/93] Bump django from 3.2.18 to 3.2.19 in /example (#98) Bumps [django](https://github.com/django/django) from 3.2.18 to 3.2.19. - [Commits](https://github.com/django/django/compare/3.2.18...3.2.19) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- example/poetry.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/example/poetry.lock b/example/poetry.lock index 68bc5d2..839c700 100644 --- a/example/poetry.lock +++ b/example/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.4.0 and should not be changed by hand. +# This file is automatically @generated by Poetry and should not be changed by hand. [[package]] name = "amqp" @@ -244,14 +244,14 @@ files = [ [[package]] name = "django" -version = "3.2.18" +version = "3.2.19" description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design." category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "Django-3.2.18-py3-none-any.whl", hash = "sha256:4d492d9024c7b3dfababf49f94511ab6a58e2c9c3c7207786f1ba4eb77750706"}, - {file = "Django-3.2.18.tar.gz", hash = "sha256:08208dfe892eb64fff073ca743b3b952311104f939e7f6dae954fe72dcc533ba"}, + {file = "Django-3.2.19-py3-none-any.whl", hash = "sha256:21cc991466245d659ab79cb01204f9515690f8dae00e5eabde307f14d24d4d7d"}, + {file = "Django-3.2.19.tar.gz", hash = "sha256:031365bae96814da19c10706218c44dff3b654cc4de20a98bd2d29b9bde469f0"}, ] [package.dependencies] From 825484d46e0e21f0bd6a518ab03443754b7b30cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 05:15:37 +0000 Subject: [PATCH 81/93] Bump pygments from 2.10.0 to 2.15.0 in /example Bumps [pygments](https://github.com/pygments/pygments) from 2.10.0 to 2.15.0. - [Release notes](https://github.com/pygments/pygments/releases) - [Changelog](https://github.com/pygments/pygments/blob/master/CHANGES) - [Commits](https://github.com/pygments/pygments/compare/2.10.0...2.15.0) --- updated-dependencies: - dependency-name: pygments dependency-type: indirect ... Signed-off-by: dependabot[bot] --- example/poetry.lock | 59 ++++++--------------------------------------- 1 file changed, 8 insertions(+), 51 deletions(-) diff --git a/example/poetry.lock b/example/poetry.lock index 839c700..6edd93a 100644 --- a/example/poetry.lock +++ b/example/poetry.lock @@ -1,10 +1,9 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "amqp" version = "5.0.6" description = "Low-level AMQP client for Python (fork of amqplib)." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -19,7 +18,6 @@ vine = "5.0.0" name = "asgiref" version = "3.4.1" description = "ASGI specs, helper code, and adapters" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -37,7 +35,6 @@ tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] name = "billiard" version = "3.6.4.0" description = "Python multiprocessing fork with improvements and bugfixes" -category = "main" optional = false python-versions = "*" files = [ @@ -49,7 +46,6 @@ files = [ name = "black" version = "22.3.0" description = "The uncompromising code formatter." -category = "dev" optional = false python-versions = ">=3.6.2" files = [ @@ -97,7 +93,6 @@ uvloop = ["uvloop (>=0.15.2)"] name = "cached-property" version = "1.5.2" description = "A decorator for caching properties in classes." -category = "main" optional = false python-versions = "*" files = [ @@ -109,7 +104,6 @@ files = [ name = "celery" version = "5.0.2" description = "Distributed Task Queue." -category = "main" optional = false python-versions = ">=3.6," files = [ @@ -163,7 +157,6 @@ zstd = ["zstandard"] name = "click" version = "8.0.1" description = "Composable command line interface toolkit" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -179,7 +172,6 @@ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} name = "click-didyoumean" version = "0.0.3" description = "Enable git-like did-you-mean feature in click." -category = "main" optional = false python-versions = "*" files = [ @@ -193,7 +185,6 @@ click = "*" name = "click-repl" version = "0.2.0" description = "REPL plugin for Click" -category = "main" optional = false python-versions = "*" files = [ @@ -210,7 +201,6 @@ six = "*" name = "colorama" version = "0.4.4" description = "Cross-platform colored terminal text." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -222,7 +212,6 @@ files = [ name = "defusedxml" version = "0.7.1" description = "XML bomb protection for Python stdlib modules" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -234,7 +223,6 @@ files = [ name = "diff-match-patch" version = "20200713" description = "Repackaging of Google's Diff Match and Patch libraries. Offers robust algorithms to perform the operations required for synchronizing plain text." -category = "main" optional = false python-versions = ">=2.7" files = [ @@ -246,7 +234,6 @@ files = [ name = "django" version = "3.2.19" description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -267,7 +254,6 @@ bcrypt = ["bcrypt"] name = "django-admin-smoke-tests" version = "0.3.0" description = "Runs some quick tests on your admin site objects to make sure there aren't non-existant fields listed, etc." -category = "dev" optional = false python-versions = "*" files = [ @@ -282,7 +268,6 @@ six = "*" name = "django-author" version = "1.0.2" description = "Add special User ForeignKey fields which update automatically" -category = "main" optional = false python-versions = "*" files = [ @@ -296,7 +281,6 @@ setuptools-git = "*" name = "django-import-export" version = "2.5.0" description = "Django application and library for importing and exporting data with included admin integration." -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -313,7 +297,6 @@ tablib = {version = ">=0.14.0", extras = ["html", "ods", "xls", "xlsx", "yaml"]} name = "et-xmlfile" version = "1.1.0" description = "An implementation of lxml.xmlfile for the standard library" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -325,7 +308,6 @@ files = [ name = "html2text" version = "2020.1.16" description = "Turn HTML into equivalent Markdown-structured text." -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -337,7 +319,6 @@ files = [ name = "importlib-metadata" version = "4.8.1" description = "Read metadata from Python packages" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -358,7 +339,6 @@ testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pep517", name = "kombu" version = "5.1.0" description = "Messaging library for Python." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -392,7 +372,6 @@ zookeeper = ["kazoo (>=1.3.1)"] name = "markuppy" version = "1.14" description = "An HTML/XML generator" -category = "main" optional = false python-versions = "*" files = [ @@ -403,7 +382,6 @@ files = [ name = "mypy-extensions" version = "0.4.3" description = "Experimental type system extensions for programs checked with the mypy typechecker." -category = "dev" optional = false python-versions = "*" files = [ @@ -415,7 +393,6 @@ files = [ name = "odfpy" version = "1.4.1" description = "Python API and tools to manipulate OpenDocument files" -category = "main" optional = false python-versions = "*" files = [ @@ -429,7 +406,6 @@ defusedxml = "*" name = "openpyxl" version = "3.0.7" description = "A Python library to read/write Excel 2010 xlsx/xlsm files" -category = "main" optional = false python-versions = ">=3.6," files = [ @@ -444,7 +420,6 @@ et-xmlfile = "*" name = "pathspec" version = "0.9.0" description = "Utility library for gitignore style pattern matching of file paths." -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" files = [ @@ -456,7 +431,6 @@ files = [ name = "platformdirs" version = "2.5.1" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -472,7 +446,6 @@ test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock name = "prompt-toolkit" version = "3.0.20" description = "Library for building powerful interactive command lines in Python" -category = "main" optional = false python-versions = ">=3.6.2" files = [ @@ -487,7 +460,6 @@ wcwidth = "*" name = "psycopg2-binary" version = "2.9.1" description = "psycopg2 - Python-PostgreSQL Database Adapter" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -533,7 +505,6 @@ files = [ name = "pudb" version = "2019.2" description = "A full-screen, console-based Python debugger" -category = "dev" optional = false python-versions = "*" files = [ @@ -546,21 +517,22 @@ urwid = ">=1.1.1" [[package]] name = "pygments" -version = "2.10.0" +version = "2.15.0" description = "Pygments is a syntax highlighting package written in Python." -category = "dev" optional = false -python-versions = ">=3.5" +python-versions = ">=3.7" files = [ - {file = "Pygments-2.10.0-py3-none-any.whl", hash = "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380"}, - {file = "Pygments-2.10.0.tar.gz", hash = "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"}, + {file = "Pygments-2.15.0-py3-none-any.whl", hash = "sha256:77a3299119af881904cd5ecd1ac6a66214b6e9bed1f2db16993b54adede64094"}, + {file = "Pygments-2.15.0.tar.gz", hash = "sha256:f7e36cffc4c517fbc252861b9a6e4644ca0e5abadf9a113c72d1358ad09b9500"}, ] +[package.extras] +plugins = ["importlib-metadata"] + [[package]] name = "pytz" version = "2021.1" description = "World timezone definitions, modern and historical" -category = "main" optional = false python-versions = "*" files = [ @@ -572,7 +544,6 @@ files = [ name = "pyyaml" version = "5.4.1" description = "YAML parser and emitter for Python" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ @@ -611,7 +582,6 @@ files = [ name = "redis" version = "3.5.3" description = "Python client for Redis key-value store" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -626,7 +596,6 @@ hiredis = ["hiredis (>=0.1.3)"] name = "setuptools-git" version = "1.2" description = "Setuptools revision control system plugin for Git" -category = "main" optional = false python-versions = "*" files = [ @@ -638,7 +607,6 @@ files = [ name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -650,7 +618,6 @@ files = [ name = "sqlparse" version = "0.4.1" description = "A non-validating SQL parser." -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -662,7 +629,6 @@ files = [ name = "tablib" version = "3.2.1" description = "Format agnostic tabular data library (XLS, JSON, YAML, CSV)" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -692,7 +658,6 @@ yaml = ["pyyaml"] name = "tomli" version = "2.0.1" description = "A lil' TOML parser" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -704,7 +669,6 @@ files = [ name = "typed-ast" version = "1.4.3" description = "a fork of Python 2 and 3 ast modules with type comment support" -category = "dev" optional = false python-versions = "*" files = [ @@ -744,7 +708,6 @@ files = [ name = "typing-extensions" version = "3.10.0.2" description = "Backported and Experimental Type Hints for Python 3.5+" -category = "main" optional = false python-versions = "*" files = [ @@ -757,7 +720,6 @@ files = [ name = "urwid" version = "2.1.2" description = "A full-featured console (xterm et al.) user interface library" -category = "dev" optional = false python-versions = "*" files = [ @@ -768,7 +730,6 @@ files = [ name = "vine" version = "5.0.0" description = "Promises, promises, promises." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -780,7 +741,6 @@ files = [ name = "wcwidth" version = "0.2.5" description = "Measures the displayed width of unicode strings in a terminal" -category = "main" optional = false python-versions = "*" files = [ @@ -792,7 +752,6 @@ files = [ name = "xlrd" version = "2.0.1" description = "Library for developers to extract data from Microsoft Excel (tm) .xls spreadsheet files" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ @@ -809,7 +768,6 @@ test = ["pytest", "pytest-cov"] name = "xlwt" version = "1.3.0" description = "Library to create spreadsheet files compatible with MS Excel 97/2000/XP/2003 XLS files, on any platform, with Python 2.6, 2.7, 3.3+" -category = "main" optional = false python-versions = "*" files = [ @@ -821,7 +779,6 @@ files = [ name = "zipp" version = "3.5.0" description = "Backport of pathlib-compatible object wrapper for zip files" -category = "main" optional = false python-versions = ">=3.6" files = [ From 2017a7690b39b298a246d4076d24f1aa8adf0105 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 05:15:39 +0000 Subject: [PATCH 82/93] Bump django from 3.2.19 to 3.2.25 in /example Bumps [django](https://github.com/django/django) from 3.2.19 to 3.2.25. - [Commits](https://github.com/django/django/compare/3.2.19...3.2.25) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- example/poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/example/poetry.lock b/example/poetry.lock index 6edd93a..fa14308 100644 --- a/example/poetry.lock +++ b/example/poetry.lock @@ -232,13 +232,13 @@ files = [ [[package]] name = "django" -version = "3.2.19" +version = "3.2.25" description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design." optional = false python-versions = ">=3.6" files = [ - {file = "Django-3.2.19-py3-none-any.whl", hash = "sha256:21cc991466245d659ab79cb01204f9515690f8dae00e5eabde307f14d24d4d7d"}, - {file = "Django-3.2.19.tar.gz", hash = "sha256:031365bae96814da19c10706218c44dff3b654cc4de20a98bd2d29b9bde469f0"}, + {file = "Django-3.2.25-py3-none-any.whl", hash = "sha256:a52ea7fcf280b16f7b739cec38fa6d3f8953a5456986944c3ca97e79882b4e38"}, + {file = "Django-3.2.25.tar.gz", hash = "sha256:7ca38a78654aee72378594d63e51636c04b8e28574f5505dff630895b5472777"}, ] [package.dependencies] From 1ea5a0617484a1853f31796ef21d4b2879c7a9d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Dlouh=C3=BD?= Date: Mon, 20 May 2024 16:45:21 +0200 Subject: [PATCH 83/93] update publish-to-pypi actions --- .github/workflows/publish-to-live-pypi.yml | 2 +- .github/workflows/publish-to-test-pypi.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish-to-live-pypi.yml b/.github/workflows/publish-to-live-pypi.yml index 95ff909..4a1ec95 100644 --- a/.github/workflows/publish-to-live-pypi.yml +++ b/.github/workflows/publish-to-live-pypi.yml @@ -36,7 +36,7 @@ jobs: - name: Publish distribution 📦 to PyPI if: startsWith(github.ref, 'refs/tags') - uses: pypa/gh-action-pypi-publish@master + uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.github/workflows/publish-to-test-pypi.yml b/.github/workflows/publish-to-test-pypi.yml index f11b035..2c76669 100644 --- a/.github/workflows/publish-to-test-pypi.yml +++ b/.github/workflows/publish-to-test-pypi.yml @@ -35,7 +35,7 @@ jobs: . - name: Publish distribution 📦 to Test PyPI - uses: pypa/gh-action-pypi-publish@master + uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ password: ${{ secrets.TEST_PYPI_API_TOKEN }} From 7678b58bed15ca79651c9dad532db13d3e1f7758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Dlouh=C3=BD?= Date: Mon, 20 May 2024 16:58:56 +0200 Subject: [PATCH 84/93] Bumped version for normal release. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 415e322..9ec5322 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ .strip() ) except subprocess.CalledProcessError: - version = "0.dev" + datetime.datetime.now().strftime("%Y%m%d%H%M%S") + version="1.7", setup( name="django-import-export-celery", From 80a1ebbb8c2afa7b24d3cd1a3271933bce7c926d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Dlouh=C3=BD?= Date: Mon, 20 May 2024 17:07:34 +0200 Subject: [PATCH 85/93] fix flake8 errors --- setup.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 9ec5322..628e232 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,6 @@ import os from setuptools import setup, find_packages import subprocess -import datetime here = os.path.abspath(os.path.dirname(__file__)) @@ -15,7 +14,7 @@ .strip() ) except subprocess.CalledProcessError: - version="1.7", + version = "1.7", setup( name="django-import-export-celery", From eb8fa0cbf930947f7832ac71b9af228b88dfb07e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Dlouh=C3=BD?= Date: Mon, 20 May 2024 17:13:44 +0200 Subject: [PATCH 86/93] Revert "fix flake8 errors" This reverts commit 80a1ebbb8c2afa7b24d3cd1a3271933bce7c926d. --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 628e232..9ec5322 100644 --- a/setup.py +++ b/setup.py @@ -2,6 +2,7 @@ import os from setuptools import setup, find_packages import subprocess +import datetime here = os.path.abspath(os.path.dirname(__file__)) @@ -14,7 +15,7 @@ .strip() ) except subprocess.CalledProcessError: - version = "1.7", + version="1.7", setup( name="django-import-export-celery", From 5a9bab61b315afef8817e462d2299c5c158a4532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Dlouh=C3=BD?= Date: Mon, 20 May 2024 17:13:46 +0200 Subject: [PATCH 87/93] Revert "Bumped version for normal release." This reverts commit 7678b58bed15ca79651c9dad532db13d3e1f7758. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9ec5322..415e322 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ .strip() ) except subprocess.CalledProcessError: - version="1.7", + version = "0.dev" + datetime.datetime.now().strftime("%Y%m%d%H%M%S") setup( name="django-import-export-celery", From c2302df530cc80fc52038a0e5f2715b88dbb96ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Dlouh=C3=BD?= Date: Wed, 22 May 2024 10:09:57 +0200 Subject: [PATCH 88/93] fix tests --- example/project/settings.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/example/project/settings.py b/example/project/settings.py index 3e7c5f6..249a8cf 100644 --- a/example/project/settings.py +++ b/example/project/settings.py @@ -93,6 +93,12 @@ "IMPORT_EXPORT_CELERY_STORAGE": { "BACKEND": "django.core.files.storage.FileSystemStorage", }, + "staticfiles": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + }, + "default": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + } } # Password validation From 244b008676e3e94e94f4ffe2ee2569c8b1c54b74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Dlouh=C3=BD?= Date: Wed, 22 May 2024 09:59:33 +0200 Subject: [PATCH 89/93] establish GitHub actions testing with TOX --- .coveragerc | 9 ++++ .github/workflows/linters.yml | 83 ++++++++++++++++++++++++++++++++++- example/project/settings.py | 29 +++++++----- requirements_test.txt | 7 +++ tox.ini | 38 ++++++++++++++++ 5 files changed, 155 insertions(+), 11 deletions(-) create mode 100644 .coveragerc create mode 100644 requirements_test.txt create mode 100644 tox.ini diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..835e4c8 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,9 @@ +[run] +omit = + */virtualenvs/*, + */migrations/*, + */site-packages/* +include = import_export_celery/* +plugins = + django_coverage_plugin +branch = True diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 43caacd..79f2b11 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -1,4 +1,4 @@ -name: Flake8 +name: CI on: [push, pull_request] @@ -7,6 +7,87 @@ concurrency: cancel-in-progress: true jobs: + test: + runs-on: ubuntu-latest + + services: + postgres: + image: postgres:13 + ports: + - 5432:5432 + env: + POSTGRES_DB: pguser + POSTGRES_USER: pguser + POSTGRES_PASSWORD: foobar + options: >- + --health-cmd "pg_isready -U pguser" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + redis: + image: redis:latest + ports: + - 6379:6379 + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + strategy: + fail-fast: false + matrix: + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + django-version: ["3.2", "4.0", "4.1", "4.2", "5.0", "5.1"] + exclude: + - python-version: "3.8" + django-version: "5.0" + - python-version: "3.8" + django-version: "5.1" + + - python-version: "3.9" + django-version: "5.0" + - python-version: "3.9" + django-version: "5.1" + + - python-version: "3.11" + django-version: "3.2" + + - python-version: "3.12" + django-version: "3.2" + - python-version: "3.12" + django-version: "4.0" + + steps: + - uses: actions/checkout@v2 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install tox tox-gh-actions + + - name: Run Tox + env: + DJANGO_VERSION: ${{ matrix.django-version }} + run: | + PYTHON_VERSION=`echo ${{ matrix.python-version }} | sed 's/\.//'` + DJANGO_VERSION=`echo $DJANGO_VERSION | sed 's/\.//'` + tox -e py${PYTHON_VERSION}-django${DJANGO_VERSION} + + # TODO: activate when organization token will be available + # - name: Upload coverage to Codecov + # uses: codecov/codecov-action@v4 + # with: + # token: ${{ secrets.CODECOV_TOKEN }} + # files: coverage.xml + # fail_ci_if_error: true + flake8: name: flake8 runs-on: ubuntu-latest diff --git a/example/project/settings.py b/example/project/settings.py index 249a8cf..355d63e 100644 --- a/example/project/settings.py +++ b/example/project/settings.py @@ -67,6 +67,7 @@ "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", ], + "debug": DEBUG, }, }, ] @@ -78,16 +79,24 @@ # Database # https://docs.djangoproject.com/en/1.10/ref/settings/#databases -DATABASES = { - "default": { - "ENGINE": "django.db.backends.postgresql_psycopg2", - "NAME": os.environ.get("DATABASE_NAME", "pguser"), - "USER": os.environ.get("DATABASE_USER", "pguser"), - "PASSWORD": os.environ.get("DATABASE_PASSWORD", "foobar"), - "HOST": os.environ.get("DATABASE_HOST", "postgres"), - "PORT": os.environ.get("DATABASE_PORT", ""), - }, -} +if os.environ.get("DATABASE_TYPE") == "sqlite": + DATABASES = { + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": os.environ.get("DATABASE_NAME", os.path.join(BASE_DIR, "db.sqlite3")), + } + } +else: + DATABASES = { + "default": { + "ENGINE": "django.db.backends.postgresql_psycopg2", + "NAME": os.environ.get("DATABASE_NAME", "pguser"), + "USER": os.environ.get("DATABASE_USER", "pguser"), + "PASSWORD": os.environ.get("DATABASE_PASSWORD", "foobar"), + "HOST": os.environ.get("DATABASE_HOST", "postgres"), + "PORT": os.environ.get("DATABASE_PORT", ""), + }, + } STORAGES = { "IMPORT_EXPORT_CELERY_STORAGE": { diff --git a/requirements_test.txt b/requirements_test.txt new file mode 100644 index 0000000..9a18bf2 --- /dev/null +++ b/requirements_test.txt @@ -0,0 +1,7 @@ +Django +django-import-export +django-author +html2text +celery +psycopg2-binary +django-admin-smoke-tests diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..53ee723 --- /dev/null +++ b/tox.ini @@ -0,0 +1,38 @@ +[tox] +envlist = + py{36,37,38,39,310}-django32 + py{38,39,310}-django40 + py{38,39,310,311}-django41 + py{38,39,310,311,312}-django42 + py{310,311,312}-django50 + py{310,311,312}-django51 + +[testenv] +deps = + -rrequirements_test.txt + coverage + django-coverage-plugin + django32: django>=3.2,<3.3 + django40: django>=4.0,<4.1 + django41: django>=4.1,<4.2 + django42: django>=4.2,<4.3 + django50: django>=5.0,<5.1 + django51: django>=5.1a1,<5.2 + +setenv = + DATABASE_TYPE=sqlite + REDIS_URL=redis://127.0.0.1:6379/0 + +allowlist_externals = coverage + +test-executable = + python --version + python -c "import django; print(django.get_version())" + pip install -r requirements_test.txt + {envbindir}/python -Wall {envbindir}/coverage run --append + +commands = + python example/manage.py migrate + {[testenv]test-executable} example/manage.py test winners + coverage report + coverage xml -o coverage.xml From c5542630df0774ab3e5e46063e361fda54e090d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Dlouh=C3=BD?= Date: Fri, 24 May 2024 14:37:48 +0200 Subject: [PATCH 90/93] re-enable Codecov --- .github/workflows/linters.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 79f2b11..d40199a 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -80,13 +80,12 @@ jobs: DJANGO_VERSION=`echo $DJANGO_VERSION | sed 's/\.//'` tox -e py${PYTHON_VERSION}-django${DJANGO_VERSION} - # TODO: activate when organization token will be available - # - name: Upload coverage to Codecov - # uses: codecov/codecov-action@v4 - # with: - # token: ${{ secrets.CODECOV_TOKEN }} - # files: coverage.xml - # fail_ci_if_error: true + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: coverage.xml + fail_ci_if_error: true flake8: name: flake8 From 7a9ec547d586049344fd118c4404c413c753f283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Dlouh=C3=BD?= Date: Wed, 22 May 2024 09:46:12 +0200 Subject: [PATCH 91/93] fix #115 correctly --- README.rst | 19 ++++++++- example/project/settings.py | 12 ------ example/winners/tests/test_fields.py | 60 ++++++++++++++++++++++++++++ import_export_celery/fields.py | 38 +++++++++--------- 4 files changed, 95 insertions(+), 34 deletions(-) create mode 100644 example/winners/tests/test_fields.py diff --git a/README.rst b/README.rst index 1bde213..f5394d3 100644 --- a/README.rst +++ b/README.rst @@ -169,18 +169,33 @@ To exclude or disable file formats from the admin site, configure `IMPORT_EXPORT IMPORT_EXPORT_CELERY_EXCLUDED_FORMATS = ["csv", "xls"] + Customizing File Storage Backend -------------------------------- -Define a custom storage backend by adding the `IMPORT_EXPORT_CELERY_STORAGE` to your Django settings STORAGES definition. For instance: +**If you are using the new Django 4.2 STORAGES**: + +By default, `import_export_celery` uses Django `default` storage. +To use your own storage, use the the `IMPORT_EXPORT_CELERY_STORAGE_ALIAS` variable in your Django settings and adding the STORAGES definition. +For instance: :: STORAGES = { - "IMPORT_EXPORT_CELERY_STORAGE": { + "import_export_celery": { "BACKEND": "storages.backends.s3boto3.S3Boto3Storage", }, } + IMPORT_EXPORT_CELERY_STORAGE_ALIAS = 'import_export_celery' + +**DEPRECATED: If you are using old style storages**: + +Define a custom storage backend by adding the `IMPORT_EXPORT_CELERY_STORAGE` to your Django settings. For instance: + + :: + + IMPORT_EXPORT_CELERY_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" + Customizing Task Time Limits ---------------------------- diff --git a/example/project/settings.py b/example/project/settings.py index 355d63e..c4ea7fe 100644 --- a/example/project/settings.py +++ b/example/project/settings.py @@ -98,18 +98,6 @@ }, } -STORAGES = { - "IMPORT_EXPORT_CELERY_STORAGE": { - "BACKEND": "django.core.files.storage.FileSystemStorage", - }, - "staticfiles": { - "BACKEND": "django.core.files.storage.FileSystemStorage", - }, - "default": { - "BACKEND": "django.core.files.storage.FileSystemStorage", - } -} - # Password validation # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators diff --git a/example/winners/tests/test_fields.py b/example/winners/tests/test_fields.py new file mode 100644 index 0000000..80ff76a --- /dev/null +++ b/example/winners/tests/test_fields.py @@ -0,0 +1,60 @@ +import django +from django.test import TestCase, override_settings +from django.conf import settings +from django.core.files.storage import FileSystemStorage +import unittest + +from import_export_celery.fields import lazy_initialize_storage_class + + +class FooTestingStorage(FileSystemStorage): + pass + + +class InitializeStorageClassTests(TestCase): + + def test_default(self): + self.assertIsInstance(lazy_initialize_storage_class(), FileSystemStorage) + + @unittest.skipUnless(django.VERSION < (5, 1), "Test only applicable for Django versions < 5.1") + @override_settings( + IMPORT_EXPORT_CELERY_STORAGE="winners.tests.test_fields.FooTestingStorage" + ) + def test_old_style(self): + del settings.IMPORT_EXPORT_CELERY_STORAGE_ALIAS + del settings.STORAGES + self.assertIsInstance(lazy_initialize_storage_class(), FooTestingStorage) + + @unittest.skipUnless((4, 2) <= django.VERSION, "Test only applicable for Django 4.2 and later") + @override_settings( + IMPORT_EXPORT_CELERY_STORAGE_ALIAS="test_import_export_celery", + STORAGES={ + "test_import_export_celery": { + "BACKEND": "winners.tests.test_fields.FooTestingStorage", + }, + "staticfiles": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + }, + "default": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + } + } + + ) + def test_new_style(self): + self.assertIsInstance(lazy_initialize_storage_class(), FooTestingStorage) + + @unittest.skipUnless((4, 2) <= django.VERSION, "Test only applicable for Django 4.2 and later") + @override_settings( + STORAGES={ + "staticfiles": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + }, + "default": { + "BACKEND": "winners.tests.test_fields.FooTestingStorage", + } + } + ) + def test_default_storage(self): + """ Test that "default" storage is used when no alias is provided """ + self.assertIsInstance(lazy_initialize_storage_class(), FooTestingStorage) diff --git a/import_export_celery/fields.py b/import_export_celery/fields.py index bb7d725..74f8097 100644 --- a/import_export_celery/fields.py +++ b/import_export_celery/fields.py @@ -1,27 +1,25 @@ -from django.conf import settings from django.db import models def lazy_initialize_storage_class(): - # If the user has specified a custom storage backend, use it. - if settings.STORAGES.get("IMPORT_EXPORT_CELERY_STORAGE"): - try: - # From Django 4.2 and later - from django.core.files.storage import storages - from django.core.files.storage.handler import InvalidStorageError - try: - storage_class = storages['IMPORT_EXPORT_CELERY_STORAGE'] - except InvalidStorageError: - from django.utils.module_loading import import_string - storage_class = settings.DEFAULT_FILE_STORAGE - storage_class = import_string(storage_class)() - except ImportError: - # Deprecated since Django 4.2, Removed in Django 5.1 - from django.core.files.storage import get_storage_class - storage_class = get_storage_class( - settings.STORAGES.get("IMPORT_EXPORT_CELERY_STORAGE")["BACKEND"] - )() - return storage_class + from django.conf import settings + try: + from django.core.files.storage import storages + storages_defined = True + except ImportError: + storages_defined = False + + if not hasattr(settings, 'IMPORT_EXPORT_CELERY_STORAGE') and storages_defined: + # Use new style storages if defined + storage_alias = getattr(settings, "IMPORT_EXPORT_CELERY_STORAGE_ALIAS", "default") + storage_class = storages[storage_alias] + else: + # Use old style storages if defined + from django.core.files.storage import get_storage_class + storage_class = get_storage_class(getattr(settings, "IMPORT_EXPORT_CELERY_STORAGE", "django.core.files.storage.FileSystemStorage")) + return storage_class() + + return storage_class class ImportExportFileField(models.FileField): From 37d2c9671e0376067c6276bee5bf10b6eba33870 Mon Sep 17 00:00:00 2001 From: Igor Kozyrenko Date: Fri, 27 Sep 2024 12:44:20 -0700 Subject: [PATCH 92/93] Handle ValidationErrors having just plain messages list --- import_export_celery/tasks.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/import_export_celery/tasks.py b/import_export_celery/tasks.py index ef3083b..2b87759 100644 --- a/import_export_celery/tasks.py +++ b/import_export_celery/tasks.py @@ -142,17 +142,23 @@ def before_import_row(self, row, **kwargs): cols = lambda row: "
".join( [str(field) for field in row.values] ) - cols_error = lambda row: "".join( - [ - "" - + key - + "" - + "
" - + row.error.message_dict[key][0] - + "
" - for key in row.error.message_dict.keys() - ] - ) + + def cols_error(row): + if hasattr(row.error, "message_dict"): + return "".join( + [ + "" + + key + + "" + + "
" + + row.error.message_dict[key][0] + + "
" + for key in row.error.message_dict.keys() + ] + ) + else: + return "".join(message + "
" for message in row.error.messages) + summary += ( "
rowerrors" From f58ed82f34770d2338f5a58ca0c2b06572938503 Mon Sep 17 00:00:00 2001 From: Karim Tayie Date: Fri, 22 Nov 2024 17:18:08 +0200 Subject: [PATCH 93/93] add configurable email on completion for export job --- README.rst | 8 +++++--- example/winners/tests/test_models.py | 20 ++++++++++++++++++- example/winners/tests/test_utils.py | 11 ++++++++++ ...011_alter_exportjob_email_on_completion.py | 19 ++++++++++++++++++ import_export_celery/models/exportjob.py | 4 ++-- import_export_celery/utils.py | 9 +++++++++ 6 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 import_export_celery/migrations/0011_alter_exportjob_email_on_completion.py diff --git a/README.rst b/README.rst index f5394d3..24a6a8b 100644 --- a/README.rst +++ b/README.rst @@ -212,27 +212,29 @@ By default, there is no time limit on celery import/export tasks. This can be cu IMPORT_EXPORT_CELERY_EXPORT_SOFT_TIME_LIMIT = 300 # 5 minutes IMPORT_EXPORT_CELERY_EXPORT_HARD_TIME_LIMIT = 360 # 6 minutes -Customizing email template for export job completion email +Customizing email settings for export job completion ---------------------------------------------------------- -By default this is the subject and template used to send the email +By default the export job completion email uses the following settings :: Subject: 'Django: Export job completed' Email template: 'email/export_job_completion.html' + Email on completion: True The default email template can be found `here `__ -The default email subject and template can be customized by overriding these values from django settings:- +The default email subject, template and sending behavior can be customized by overriding these values from django settings:- :: EXPORT_JOB_COMPLETION_MAIL_SUBJECT="Your custom subject" EXPORT_JOB_COMPLETION_MAIL_TEMPLATE="path_to_folder/your_custom_template.html" + EXPORT_JOB_EMAIL_ON_COMPLETION = True # Set to False to disable email The email template will get some context variables that you can use to customize your template. diff --git a/example/winners/tests/test_models.py b/example/winners/tests/test_models.py index 0ebc943..cfc2916 100644 --- a/example/winners/tests/test_models.py +++ b/example/winners/tests/test_models.py @@ -1,7 +1,8 @@ import os -from django.test import TestCase +from django.test import TestCase, override_settings from django.core.files.base import ContentFile +from import_export_celery.models.exportjob import ExportJob from import_export_celery.models.importjob import ImportJob @@ -16,3 +17,20 @@ def test_delete_file_on_job_delete(self): job.delete() assert not os.path.exists(file_path) assert not ImportJob.objects.filter(id=job.id).exists() + + +class ExportJobTestCases(TestCase): + def test_create_export_job_default_email_on_completion(self): + job = ExportJob.objects.create( + app_label="winners", model="Winner" + ) + job.refresh_from_db() + self.assertTrue(job.email_on_completion) + + @override_settings(EXPORT_JOB_EMAIL_ON_COMPLETION=False) + def test_create_export_job_false_email_on_completion(self): + job = ExportJob.objects.create( + app_label="winners", model="Winner" + ) + job.refresh_from_db() + self.assertFalse(job.email_on_completion) diff --git a/example/winners/tests/test_utils.py b/example/winners/tests/test_utils.py index 1017f7e..cefc09f 100644 --- a/example/winners/tests/test_utils.py +++ b/example/winners/tests/test_utils.py @@ -4,8 +4,10 @@ get_export_job_mail_subject, get_export_job_mail_template, get_export_job_mail_context, + get_export_job_email_on_completion, DEFAULT_EXPORT_JOB_COMPLETION_MAIL_SUBJECT, DEFAULT_EXPORT_JOB_COMPLETION_MAIL_TEMPLATE, + DEFAULT_EXPORT_JOB_EMAIL_ON_COMPLETION, ) from import_export_celery.models import ExportJob @@ -29,6 +31,15 @@ def test_get_export_job_mail_template_default(self): def test_get_export_job_mail_template_overridden(self): self.assertEqual("mytemplate.html", get_export_job_mail_template()) + def test_get_export_job_email_on_completion_default(self): + self.assertEqual( + DEFAULT_EXPORT_JOB_EMAIL_ON_COMPLETION, get_export_job_email_on_completion() + ) + + @override_settings(EXPORT_JOB_EMAIL_ON_COMPLETION=False) + def test_get_export_job_email_on_completion_overridden(self): + self.assertEqual(False, get_export_job_email_on_completion()) + def test_get_export_job_mail_context(self): export_job = ExportJob.objects.create( app_label="winners", model="Winner", site_of_origin="http://127.0.0.1:8000" diff --git a/import_export_celery/migrations/0011_alter_exportjob_email_on_completion.py b/import_export_celery/migrations/0011_alter_exportjob_email_on_completion.py new file mode 100644 index 0000000..809e71d --- /dev/null +++ b/import_export_celery/migrations/0011_alter_exportjob_email_on_completion.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.25 on 2024-11-22 12:19 + +from django.db import migrations, models +import import_export_celery.utils + + +class Migration(migrations.Migration): + + dependencies = [ + ('import_export_celery', '0010_auto_20231013_0904'), + ] + + operations = [ + migrations.AlterField( + model_name='exportjob', + name='email_on_completion', + field=models.BooleanField(default=import_export_celery.utils.get_export_job_email_on_completion, verbose_name='Send me an email when this export job is complete'), + ), + ] diff --git a/import_export_celery/models/exportjob.py b/import_export_celery/models/exportjob.py index 66f5691..9876d19 100644 --- a/import_export_celery/models/exportjob.py +++ b/import_export_celery/models/exportjob.py @@ -14,7 +14,7 @@ from ..fields import ImportExportFileField from ..tasks import run_export_job -from ..utils import get_formats +from ..utils import get_formats, get_export_job_email_on_completion @with_author @@ -74,7 +74,7 @@ def __init__(self, *args, **kwargs): email_on_completion = models.BooleanField( verbose_name=_("Send me an email when this export job is complete"), - default=True, + default=get_export_job_email_on_completion, ) site_of_origin = models.TextField( diff --git a/import_export_celery/utils.py b/import_export_celery/utils.py index 2cd4659..cbe05a7 100644 --- a/import_export_celery/utils.py +++ b/import_export_celery/utils.py @@ -5,6 +5,7 @@ from django.urls import reverse from import_export.formats.base_formats import DEFAULT_FORMATS +DEFAULT_EXPORT_JOB_EMAIL_ON_COMPLETION = True DEFAULT_EXPORT_JOB_COMPLETION_MAIL_SUBJECT = "Django: Export job completed" DEFAULT_EXPORT_JOB_COMPLETION_MAIL_TEMPLATE = ( "email/export_job_completion.html" @@ -53,6 +54,14 @@ def get_export_job_mail_context(export_job): return context +def get_export_job_email_on_completion(): + return getattr( + settings, + "EXPORT_JOB_EMAIL_ON_COMPLETION", + DEFAULT_EXPORT_JOB_EMAIL_ON_COMPLETION, + ) + + def get_export_job_mail_subject(): return getattr( settings,