diff --git a/.gitignore b/.gitignore index 052ef78..c83a018 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# PDM local config +.pdm-python + # Django project # Use .gitkeep pattern to for empty directories that Wagtail expects to exist. /media/* diff --git a/ov_collections/__init__.py b/ov_collections/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ov_collections/admin.py b/ov_collections/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/ov_collections/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/ov_collections/apps.py b/ov_collections/apps.py new file mode 100644 index 0000000..736d46e --- /dev/null +++ b/ov_collections/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class CollectionsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'ov_collections' diff --git a/ov_collections/blocks.py b/ov_collections/blocks.py new file mode 100644 index 0000000..c5c8f17 --- /dev/null +++ b/ov_collections/blocks.py @@ -0,0 +1,29 @@ +from wagtail.core.blocks import StructBlock, CharBlock, URLBlock +from wagtail.images.blocks import ImageChooserBlock + + +class ContentBlock(StructBlock): + """Generic content block + - title + - link + + All fields are required + """ + + title = CharBlock( + required=True, max_length=1024, help_text='The title of this content' + ) + link = URLBlock(required=True) + + +class ContentImageBlock(ContentBlock): + """Generic content block with image + - image: required + """ + + image = ImageChooserBlock(required=True) + + def get_api_representation(self, value, context=None): + results = super().get_api_representation(value, context) + results['image'] = value.get('image').get_rendition('width-400').attrs_dict + return results diff --git a/ov_collections/migrations/0001_initial.py b/ov_collections/migrations/0001_initial.py new file mode 100644 index 0000000..f3f937e --- /dev/null +++ b/ov_collections/migrations/0001_initial.py @@ -0,0 +1,33 @@ +# Generated by Django 4.1.2 on 2022-10-06 20:24 + +from django.db import migrations, models +import django.db.models.deletion +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('wagtailimages', '0024_index_image_file_hash'), + ('wagtailcore', '0077_alter_revision_user'), + ] + + operations = [ + migrations.CreateModel( + name='Collection', + fields=[ + ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')), + ('about', wagtail.fields.RichTextField(blank=True)), + ('content', wagtail.fields.StreamField([('heading', wagtail.blocks.CharBlock(form_classname='title')), ('text', wagtail.blocks.TextBlock()), ('image', wagtail.images.blocks.ImageChooserBlock())], use_json_field=True)), + ('cover_image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.image')), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + ] diff --git a/ov_collections/migrations/0002_alter_collection_content.py b/ov_collections/migrations/0002_alter_collection_content.py new file mode 100644 index 0000000..c967e05 --- /dev/null +++ b/ov_collections/migrations/0002_alter_collection_content.py @@ -0,0 +1,21 @@ +# Generated by Django 4.1.2 on 2022-10-13 18:14 + +from django.db import migrations +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks + + +class Migration(migrations.Migration): + + dependencies = [ + ('ov_collections', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='collection', + name='content', + field=wagtail.fields.StreamField([('heading', wagtail.blocks.CharBlock(form_classname='title')), ('text', wagtail.blocks.TextBlock()), ('image', wagtail.images.blocks.ImageChooserBlock()), ('Interviews', wagtail.blocks.StructBlock([('interviews', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('interview', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('link', wagtail.blocks.URLBlock(required=True))]))])))]))], use_json_field=True), + ), + ] diff --git a/ov_collections/migrations/0003_alter_collection_content.py b/ov_collections/migrations/0003_alter_collection_content.py new file mode 100644 index 0000000..5a60812 --- /dev/null +++ b/ov_collections/migrations/0003_alter_collection_content.py @@ -0,0 +1,21 @@ +# Generated by Django 4.1.2 on 2022-10-14 16:05 + +from django.db import migrations +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks + + +class Migration(migrations.Migration): + + dependencies = [ + ('ov_collections', '0002_alter_collection_content'), + ] + + operations = [ + migrations.AlterField( + model_name='collection', + name='content', + field=wagtail.fields.StreamField([('heading', wagtail.blocks.CharBlock(form_classname='title')), ('text', wagtail.blocks.TextBlock()), ('image', wagtail.images.blocks.ImageChooserBlock()), ('interviews', wagtail.blocks.StructBlock([('interviews', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('interview', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('link', wagtail.blocks.URLBlock(required=True))]))])))])), ('archival_footage', wagtail.blocks.StructBlock([('footage', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('footage', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('link', wagtail.blocks.URLBlock(required=True))]))])))]))], use_json_field=True), + ), + ] diff --git a/ov_collections/migrations/0004_alter_collection_content.py b/ov_collections/migrations/0004_alter_collection_content.py new file mode 100644 index 0000000..11182f7 --- /dev/null +++ b/ov_collections/migrations/0004_alter_collection_content.py @@ -0,0 +1,21 @@ +# Generated by Django 4.1.2 on 2022-10-14 21:56 + +from django.db import migrations +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks + + +class Migration(migrations.Migration): + + dependencies = [ + ('ov_collections', '0003_alter_collection_content'), + ] + + operations = [ + migrations.AlterField( + model_name='collection', + name='content', + field=wagtail.fields.StreamField([('heading', wagtail.blocks.CharBlock(form_classname='title')), ('text', wagtail.blocks.TextBlock()), ('image', wagtail.images.blocks.ImageChooserBlock()), ('interviews', wagtail.blocks.StructBlock([('interviews', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('interview', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('link', wagtail.blocks.URLBlock(required=True))]))])))])), ('archival_footage', wagtail.blocks.StructBlock([('footage', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('footage', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('link', wagtail.blocks.URLBlock(required=True))]))])))])), ('photographs', wagtail.blocks.StructBlock([('photos', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('photos', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('link', wagtail.blocks.URLBlock(required=True))]))])))])), ('original_footage', wagtail.blocks.StructBlock([('footage', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('footage', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('link', wagtail.blocks.URLBlock(required=True))]))])))])), ('programs', wagtail.blocks.StructBlock([('programs', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('programs', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('link', wagtail.blocks.URLBlock(required=True))]))])))])), ('related_content', wagtail.blocks.StructBlock([('content', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('related_content', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('link', wagtail.blocks.URLBlock(required=True))]))])))])), ('credits', wagtail.blocks.StructBlock([('credits', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('credits', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('link', wagtail.blocks.URLBlock(required=True))]))])))]))], use_json_field=True), + ), + ] diff --git a/ov_collections/migrations/0005_alter_collection_content.py b/ov_collections/migrations/0005_alter_collection_content.py new file mode 100644 index 0000000..afc0f7e --- /dev/null +++ b/ov_collections/migrations/0005_alter_collection_content.py @@ -0,0 +1,21 @@ +# Generated by Django 4.1.2 on 2022-10-17 18:54 + +from django.db import migrations +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks + + +class Migration(migrations.Migration): + + dependencies = [ + ('ov_collections', '0004_alter_collection_content'), + ] + + operations = [ + migrations.AlterField( + model_name='collection', + name='content', + field=wagtail.fields.StreamField([('interviews', wagtail.blocks.StructBlock([('interviews', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('interview', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('link', wagtail.blocks.URLBlock(required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True))]))])))])), ('archival_footage', wagtail.blocks.StructBlock([('footage', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('footage', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('link', wagtail.blocks.URLBlock(required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True))]))])))])), ('photographs', wagtail.blocks.StructBlock([('photos', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('photos', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('link', wagtail.blocks.URLBlock(required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True))]))])))])), ('original_footage', wagtail.blocks.StructBlock([('footage', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('footage', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('link', wagtail.blocks.URLBlock(required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True))]))])))])), ('programs', wagtail.blocks.StructBlock([('programs', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('programs', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('link', wagtail.blocks.URLBlock(required=True))]))])))])), ('related_content', wagtail.blocks.StructBlock([('content', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('related_content', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('link', wagtail.blocks.URLBlock(required=True))]))])))])), ('credits', wagtail.blocks.RichTextBlock()), ('heading', wagtail.blocks.CharBlock(form_classname='title')), ('text', wagtail.blocks.TextBlock()), ('image', wagtail.images.blocks.ImageChooserBlock())], use_json_field=True), + ), + ] diff --git a/ov_collections/migrations/0006_alter_collection_content.py b/ov_collections/migrations/0006_alter_collection_content.py new file mode 100644 index 0000000..fa2af38 --- /dev/null +++ b/ov_collections/migrations/0006_alter_collection_content.py @@ -0,0 +1,21 @@ +# Generated by Django 4.1.2 on 2022-10-19 19:10 + +from django.db import migrations +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks + + +class Migration(migrations.Migration): + + dependencies = [ + ('ov_collections', '0005_alter_collection_content'), + ] + + operations = [ + migrations.AlterField( + model_name='collection', + name='content', + field=wagtail.fields.StreamField([('interviews', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('link', wagtail.blocks.URLBlock(required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True))]), icon='openquote')), ('archival_footage', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('link', wagtail.blocks.URLBlock(required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True))]), icon='form')), ('photographs', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('link', wagtail.blocks.URLBlock(required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True))]), icon='image')), ('original_footage', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('link', wagtail.blocks.URLBlock(required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True))]), icon='doc-full-inverse')), ('programs', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('link', wagtail.blocks.URLBlock(required=True))]), icon='clipboard-list')), ('related_content', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('link', wagtail.blocks.URLBlock(required=True))]), icon='list-ul')), ('credits', wagtail.blocks.RichTextBlock()), ('heading', wagtail.blocks.CharBlock(form_classname='title')), ('text', wagtail.blocks.TextBlock()), ('image', wagtail.images.blocks.ImageChooserBlock())], use_json_field=True), + ), + ] diff --git a/ov_collections/migrations/0007_rename_about_collection_introduction.py b/ov_collections/migrations/0007_rename_about_collection_introduction.py new file mode 100644 index 0000000..310a5bd --- /dev/null +++ b/ov_collections/migrations/0007_rename_about_collection_introduction.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.2 on 2022-10-19 21:01 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('ov_collections', '0006_alter_collection_content'), + ] + + operations = [ + migrations.RenameField( + model_name='collection', + old_name='about', + new_name='introduction', + ), + ] diff --git a/ov_collections/migrations/0008_alter_collection_content.py b/ov_collections/migrations/0008_alter_collection_content.py new file mode 100644 index 0000000..62b7bea --- /dev/null +++ b/ov_collections/migrations/0008_alter_collection_content.py @@ -0,0 +1,21 @@ +# Generated by Django 4.1.12 on 2023-10-30 19:42 + +from django.db import migrations +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks + + +class Migration(migrations.Migration): + + dependencies = [ + ('ov_collections', '0007_rename_about_collection_introduction'), + ] + + operations = [ + migrations.AlterField( + model_name='collection', + name='content', + field=wagtail.fields.StreamField([('interviews', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('link', wagtail.blocks.URLBlock(required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True))], icon='openquote', label='Interview'), icon='openquote')), ('archival_footage', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('link', wagtail.blocks.URLBlock(required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True))], icon='form', label='Footage'), icon='form')), ('photographs', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('link', wagtail.blocks.URLBlock(required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True))], icon='image', label='Photograph'), icon='image')), ('original_footage', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('link', wagtail.blocks.URLBlock(required=True)), ('image', wagtail.images.blocks.ImageChooserBlock(required=True))], icon='doc-full-inverse', label='Footage'), icon='doc-full-inverse')), ('programs', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('link', wagtail.blocks.URLBlock(required=True))], icon='clipboard-list', label='Program'), icon='clipboard-list')), ('related_content', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(help_text='The title of this content', max_length=1024, required=True)), ('link', wagtail.blocks.URLBlock(required=True))], icon='list-ul', label='Content'), icon='list-ul')), ('credits', wagtail.blocks.RichTextBlock()), ('heading', wagtail.blocks.CharBlock(form_classname='title')), ('text', wagtail.blocks.TextBlock()), ('image', wagtail.images.blocks.ImageChooserBlock())], use_json_field=True), + ), + ] diff --git a/ov_collections/migrations/__init__.py b/ov_collections/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ov_collections/models.py b/ov_collections/models.py new file mode 100644 index 0000000..a39d4ac --- /dev/null +++ b/ov_collections/models.py @@ -0,0 +1,89 @@ +from django.db import models +from wagtail.blocks import ListBlock, RichTextBlock, TextBlock, CharBlock +from wagtail.core.models import Page +from wagtail.core.fields import RichTextField, StreamField +from wagtail.search import index +from wagtail.admin.edit_handlers import FieldPanel +from wagtail.images.api.fields import ImageRenditionField +from wagtail.images.blocks import ImageChooserBlock +from wagtail.api import APIField +from .blocks import ContentImageBlock, ContentBlock + + +class Collection(Page): + introduction = RichTextField(blank=True) + + content = StreamField( + [ + ( + 'interviews', + ListBlock( + ContentImageBlock(label='Interview', icon='openquote'), + icon='openquote', + ), + ), + ( + 'archival_footage', + ListBlock(ContentImageBlock(label='Footage', icon='form'), icon='form'), + ), + ( + 'photographs', + ListBlock( + ContentImageBlock(label='Photograph', icon='image'), icon='image' + ), + ), + ( + 'original_footage', + ListBlock( + ContentImageBlock(label='Footage', icon='doc-full-inverse'), + icon='doc-full-inverse', + ), + ), + ( + 'programs', + ListBlock( + ContentBlock(label='Program', icon='clipboard-list'), + icon='clipboard-list', + ), + ), + ( + 'related_content', + ListBlock( + ContentBlock(label='Content', icon='list-ul'), icon='list-ul' + ), + ), + ('credits', RichTextBlock()), + ('heading', CharBlock(form_classname='title')), + ('text', TextBlock()), + ('image', ImageChooserBlock()), + ], + use_json_field=True, + ) + + cover_image = models.ForeignKey( + 'wagtailimages.Image', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+', + ) + + search_fields = Page.search_fields + [ + index.SearchField('introduction'), + ] + + content_panels = Page.content_panels + [ + FieldPanel('introduction'), + FieldPanel('cover_image'), + FieldPanel('content'), + ] + + api_fields = [ + APIField('title'), + APIField('introduction'), + APIField( + 'cover_image', + serializer=ImageRenditionField('fill-1600x500'), + ), + APIField('content'), + ] diff --git a/ov_collections/tests.py b/ov_collections/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/ov_collections/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/ov_collections/views.py b/ov_collections/views.py new file mode 100644 index 0000000..4af84f0 --- /dev/null +++ b/ov_collections/views.py @@ -0,0 +1,12 @@ +from wagtail.api.v2.views import BaseAPIViewSet +from .models import Collection + + +class CollectionAPIViewSet(BaseAPIViewSet): + model = Collection + + listing_default_fields = BaseAPIViewSet.listing_default_fields + [ + 'title', + 'introduction', + 'cover_image', + ] diff --git a/ov_wag/api.py b/ov_wag/api.py index 124d91b..ca72a92 100644 --- a/ov_wag/api.py +++ b/ov_wag/api.py @@ -4,6 +4,7 @@ from wagtail.documents.api.v2.views import DocumentsAPIViewSet from authors.views import AuthorsAPIViewSet from exhibits.views import ExhibitsAPIViewSet +from ov_collections.views import CollectionAPIViewSet # Create the router. "wagtailapi" is the URL namespace api_router = WagtailAPIRouter('wagtailapi') @@ -17,3 +18,4 @@ api_router.register_endpoint('documents', DocumentsAPIViewSet) api_router.register_endpoint('authors', AuthorsAPIViewSet) api_router.register_endpoint('exhibits', ExhibitsAPIViewSet) +api_router.register_endpoint('collections', CollectionAPIViewSet) diff --git a/ov_wag/settings/base.py b/ov_wag/settings/base.py index a38e664..9df4b2f 100644 --- a/ov_wag/settings/base.py +++ b/ov_wag/settings/base.py @@ -27,6 +27,7 @@ 'home', 'search', 'exhibits', + 'ov_collections', 'authors', 'wagtail.contrib.forms', 'wagtail.contrib.modeladmin', diff --git a/pdm.lock b/pdm.lock new file mode 100644 index 0000000..1effd9b --- /dev/null +++ b/pdm.lock @@ -0,0 +1,572 @@ +# This file is @generated by PDM. +# It is not intended for manual editing. + +[metadata] +groups = ["default"] +strategy = ["cross_platform"] +lock_version = "4.4" +content_hash = "sha256:ef9f7b76ccd3aa29e374113c094524d6e203f8c9fef0d8bdd434f17a82edc1fa" + +[[package]] +name = "anyascii" +version = "0.3.2" +requires_python = ">=3.3" +summary = "Unicode to ASCII transliteration" +files = [ + {file = "anyascii-0.3.2-py3-none-any.whl", hash = "sha256:3b3beef6fc43d9036d3b0529050b0c48bfad8bc960e9e562d7223cfb94fe45d4"}, + {file = "anyascii-0.3.2.tar.gz", hash = "sha256:9d5d32ef844fe225b8bc7cba7f950534fae4da27a9bf3a6bea2cb0ea46ce4730"}, +] + +[[package]] +name = "asgiref" +version = "3.7.2" +requires_python = ">=3.7" +summary = "ASGI specs, helper code, and adapters" +files = [ + {file = "asgiref-3.7.2-py3-none-any.whl", hash = "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e"}, + {file = "asgiref-3.7.2.tar.gz", hash = "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed"}, +] + +[[package]] +name = "beautifulsoup4" +version = "4.11.2" +requires_python = ">=3.6.0" +summary = "Screen-scraping library" +dependencies = [ + "soupsieve>1.2", +] +files = [ + {file = "beautifulsoup4-4.11.2-py3-none-any.whl", hash = "sha256:0e79446b10b3ecb499c1556f7e228a53e64a2bfcebd455f370d8927cb5b59e39"}, + {file = "beautifulsoup4-4.11.2.tar.gz", hash = "sha256:bc4bdda6717de5a2987436fb8d72f45dc90dd856bdfd512a1314ce90349a0106"}, +] + +[[package]] +name = "certifi" +version = "2023.7.22" +requires_python = ">=3.6" +summary = "Python package for providing Mozilla's CA Bundle." +files = [ + {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, + {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.3.1" +requires_python = ">=3.7.0" +summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +files = [ + {file = "charset-normalizer-3.3.1.tar.gz", hash = "sha256:d9137a876020661972ca6eec0766d81aef8a5627df628b664b234b73396e727e"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae4070f741f8d809075ef697877fd350ecf0b7c5837ed68738607ee0a2c572cf"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58e875eb7016fd014c0eea46c6fa92b87b62c0cb31b9feae25cbbe62c919f54d"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dbd95e300367aa0827496fe75a1766d198d34385a58f97683fe6e07f89ca3e3c"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de0b4caa1c8a21394e8ce971997614a17648f94e1cd0640fbd6b4d14cab13a72"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:985c7965f62f6f32bf432e2681173db41336a9c2611693247069288bcb0c7f8b"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a15c1fe6d26e83fd2e5972425a772cca158eae58b05d4a25a4e474c221053e2d"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae55d592b02c4349525b6ed8f74c692509e5adffa842e582c0f861751701a673"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be4d9c2770044a59715eb57c1144dedea7c5d5ae80c68fb9959515037cde2008"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:851cf693fb3aaef71031237cd68699dded198657ec1e76a76eb8be58c03a5d1f"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:31bbaba7218904d2eabecf4feec0d07469284e952a27400f23b6628439439fa7"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:871d045d6ccc181fd863a3cd66ee8e395523ebfbc57f85f91f035f50cee8e3d4"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:501adc5eb6cd5f40a6f77fbd90e5ab915c8fd6e8c614af2db5561e16c600d6f3"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f5fb672c396d826ca16a022ac04c9dce74e00a1c344f6ad1a0fdc1ba1f332213"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-win32.whl", hash = "sha256:bb06098d019766ca16fc915ecaa455c1f1cd594204e7f840cd6258237b5079a8"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:8af5a8917b8af42295e86b64903156b4f110a30dca5f3b5aedea123fbd638bff"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7ae8e5142dcc7a49168f4055255dbcced01dc1714a90a21f87448dc8d90617d1"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5b70bab78accbc672f50e878a5b73ca692f45f5b5e25c8066d748c09405e6a55"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ceca5876032362ae73b83347be8b5dbd2d1faf3358deb38c9c88776779b2e2f"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34d95638ff3613849f473afc33f65c401a89f3b9528d0d213c7037c398a51296"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9edbe6a5bf8b56a4a84533ba2b2f489d0046e755c29616ef8830f9e7d9cf5728"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6a02a3c7950cafaadcd46a226ad9e12fc9744652cc69f9e5534f98b47f3bbcf"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10b8dd31e10f32410751b3430996f9807fc4d1587ca69772e2aa940a82ab571a"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edc0202099ea1d82844316604e17d2b175044f9bcb6b398aab781eba957224bd"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b891a2f68e09c5ef989007fac11476ed33c5c9994449a4e2c3386529d703dc8b"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:71ef3b9be10070360f289aea4838c784f8b851be3ba58cf796262b57775c2f14"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:55602981b2dbf8184c098bc10287e8c245e351cd4fdcad050bd7199d5a8bf514"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:46fb9970aa5eeca547d7aa0de5d4b124a288b42eaefac677bde805013c95725c"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:520b7a142d2524f999447b3a0cf95115df81c4f33003c51a6ab637cbda9d0bf4"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-win32.whl", hash = "sha256:8ec8ef42c6cd5856a7613dcd1eaf21e5573b2185263d87d27c8edcae33b62a61"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:baec8148d6b8bd5cee1ae138ba658c71f5b03e0d69d5907703e3e1df96db5e41"}, + {file = "charset_normalizer-3.3.1-py3-none-any.whl", hash = "sha256:800561453acdecedaac137bf09cd719c7a440b6800ec182f077bb8e7025fb708"}, +] + +[[package]] +name = "django" +version = "4.1.12" +requires_python = ">=3.8" +summary = "A high-level Python web framework that encourages rapid development and clean, pragmatic design." +dependencies = [ + "asgiref<4,>=3.5.2", + "sqlparse>=0.2.2", + "tzdata; sys_platform == \"win32\"", +] +files = [ + {file = "Django-4.1.12-py3-none-any.whl", hash = "sha256:e92ce8f240a856615e96d8b955707f824c29ea0f51dff4f76777caa5e113ec72"}, + {file = "Django-4.1.12.tar.gz", hash = "sha256:d02483ad49872238fa59875c1269293fe4f17ecee13c121893607cc0b284696b"}, +] + +[[package]] +name = "django-filter" +version = "22.1" +requires_python = ">=3.7" +summary = "Django-filter is a reusable Django application for allowing users to filter querysets dynamically." +dependencies = [ + "Django>=3.2", +] +files = [ + {file = "django-filter-22.1.tar.gz", hash = "sha256:ed473b76e84f7e83b2511bb2050c3efb36d135207d0128dfe3ae4b36e3594ba5"}, + {file = "django_filter-22.1-py3-none-any.whl", hash = "sha256:ed429e34760127e3520a67f415bec4c905d4649fbe45d0d6da37e6ff5e0287eb"}, +] + +[[package]] +name = "django-modelcluster" +version = "6.1" +requires_python = ">=3.8" +summary = "Django extension to allow working with 'clusters' of models as a single unit, independently of the database" +dependencies = [ + "django>=3.2", + "pytz>=2022.4", +] +files = [ + {file = "django-modelcluster-6.1.tar.gz", hash = "sha256:3b1791638046c73ae7415327cf54bfa0adad9d89d342a5b86d0ec29a2504e067"}, + {file = "django_modelcluster-6.1-py2.py3-none-any.whl", hash = "sha256:8ce72635db4b90b34993afda5021ed8676ef94f1d4c607466d0f8d3f676c5b64"}, +] + +[[package]] +name = "django-permissionedforms" +version = "0.1" +requires_python = ">=3.7" +summary = "Django extension for creating forms that vary according to user permissions" +dependencies = [ + "Django", +] +files = [ + {file = "django-permissionedforms-0.1.tar.gz", hash = "sha256:4340bb20c4477fffb13b4cc5cccf9f1b1010b64f79956c291c72d2ad2ed243f8"}, + {file = "django_permissionedforms-0.1-py2.py3-none-any.whl", hash = "sha256:d341a961a27cc77fde8cc42141c6ab55cc1f0cb886963cc2d6967b9674fa47d6"}, +] + +[[package]] +name = "django-taggit" +version = "3.1.0" +requires_python = ">=3.6" +summary = "django-taggit is a reusable Django application for simple tagging." +dependencies = [ + "Django>=3.2", +] +files = [ + {file = "django-taggit-3.1.0.tar.gz", hash = "sha256:c8f2e4eae387939089b3d75d1d8649e008880970c068ce9d0e82f87fd5e29508"}, + {file = "django_taggit-3.1.0-py3-none-any.whl", hash = "sha256:543218ac346fbe02a65733e0341c91b57a3e0f7a41568966b26f1cea9edc4805"}, +] + +[[package]] +name = "django-treebeard" +version = "4.7" +requires_python = ">=3.8" +summary = "Efficient tree implementations for Django" +dependencies = [ + "Django>=3.2", +] +files = [ + {file = "django-treebeard-4.7.tar.gz", hash = "sha256:c751a3f924158c288fea89afc25a7151979faf01bf11fdc7be3b858099dfa56d"}, + {file = "django_treebeard-4.7-py3-none-any.whl", hash = "sha256:787117995ff985d98e6c2b241ef6b9d37fe8ff7051cd7535c283616a0b5b2645"}, +] + +[[package]] +name = "djangorestframework" +version = "3.14.0" +requires_python = ">=3.6" +summary = "Web APIs for Django, made easy." +dependencies = [ + "django>=3.0", + "pytz", +] +files = [ + {file = "djangorestframework-3.14.0-py3-none-any.whl", hash = "sha256:eb63f58c9f218e1a7d064d17a70751f528ed4e1d35547fdade9aaf4cd103fd08"}, + {file = "djangorestframework-3.14.0.tar.gz", hash = "sha256:579a333e6256b09489cbe0a067e66abe55c6595d8926be6b99423786334350c8"}, +] + +[[package]] +name = "draftjs-exporter" +version = "2.1.7" +summary = "Library to convert rich text from Draft.js raw ContentState to HTML" +files = [ + {file = "draftjs_exporter-2.1.7-py3-none-any.whl", hash = "sha256:d415a9964690a2cddb66a31ef32dd46c277e9b80434b94e39e3043188ed83e33"}, + {file = "draftjs_exporter-2.1.7.tar.gz", hash = "sha256:5839cbc29d7bce2fb99837a404ca40c3a07313f2a20e2700de7ad6aa9a9a18fb"}, +] + +[[package]] +name = "et-xmlfile" +version = "1.1.0" +requires_python = ">=3.6" +summary = "An implementation of lxml.xmlfile for the standard library" +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 = "factory-boy" +version = "3.3.0" +requires_python = ">=3.7" +summary = "A versatile test fixtures replacement based on thoughtbot's factory_bot for Ruby." +dependencies = [ + "Faker>=0.7.0", +] +files = [ + {file = "factory_boy-3.3.0-py2.py3-none-any.whl", hash = "sha256:a2cdbdb63228177aa4f1c52f4b6d83fab2b8623bf602c7dedd7eb83c0f69c04c"}, + {file = "factory_boy-3.3.0.tar.gz", hash = "sha256:bc76d97d1a65bbd9842a6d722882098eb549ec8ee1081f9fb2e8ff29f0c300f1"}, +] + +[[package]] +name = "faker" +version = "19.12.0" +requires_python = ">=3.8" +summary = "Faker is a Python package that generates fake data for you." +dependencies = [ + "python-dateutil>=2.4", +] +files = [ + {file = "Faker-19.12.0-py3-none-any.whl", hash = "sha256:5990380a8ee81cf189d6b85d5fdc1fb43772cb136aca0385a08ff24ef01b9fdf"}, + {file = "Faker-19.12.0.tar.gz", hash = "sha256:91438f6b1713274ec3f24970ba303617be86ce5caf6f6a0776f1d04777b6ff5f"}, +] + +[[package]] +name = "html5lib" +version = "1.1" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +summary = "HTML parser based on the WHATWG HTML specification" +dependencies = [ + "six>=1.9", + "webencodings", +] +files = [ + {file = "html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d"}, + {file = "html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f"}, +] + +[[package]] +name = "idna" +version = "3.4" +requires_python = ">=3.5" +summary = "Internationalized Domain Names in Applications (IDNA)" +files = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] + +[[package]] +name = "l18n" +version = "2021.3" +summary = "Internationalization for pytz timezones and territories" +dependencies = [ + "pytz>=2020.1", + "six", +] +files = [ + {file = "l18n-2021.3-py3-none-any.whl", hash = "sha256:78495d1df95b6f7dcc694d1ba8994df709c463a1cbac1bf016e1b9a5ce7280b9"}, + {file = "l18n-2021.3.tar.gz", hash = "sha256:1956e890d673d17135cc20913253c154f6bc1c00266c22b7d503cc1a5a42d848"}, +] + +[[package]] +name = "openpyxl" +version = "3.1.2" +requires_python = ">=3.6" +summary = "A Python library to read/write Excel 2010 xlsx/xlsm files" +dependencies = [ + "et-xmlfile", +] +files = [ + {file = "openpyxl-3.1.2-py2.py3-none-any.whl", hash = "sha256:f91456ead12ab3c6c2e9491cf33ba6d08357d802192379bb482f1033ade496f5"}, + {file = "openpyxl-3.1.2.tar.gz", hash = "sha256:a6f5977418eff3b2d5500d54d9db50c8277a368436f4e4f8ddb1be3422870184"}, +] + +[[package]] +name = "pillow" +version = "9.5.0" +requires_python = ">=3.7" +summary = "Python Imaging Library (Fork)" +files = [ + {file = "Pillow-9.5.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:7ec6f6ce99dab90b52da21cf0dc519e21095e332ff3b399a357c187b1a5eee32"}, + {file = "Pillow-9.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:560737e70cb9c6255d6dcba3de6578a9e2ec4b573659943a5e7e4af13f298f5c"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96e88745a55b88a7c64fa49bceff363a1a27d9a64e04019c2281049444a571e3"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d9c206c29b46cfd343ea7cdfe1232443072bbb270d6a46f59c259460db76779a"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cfcc2c53c06f2ccb8976fb5c71d448bdd0a07d26d8e07e321c103416444c7ad1"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:a0f9bb6c80e6efcde93ffc51256d5cfb2155ff8f78292f074f60f9e70b942d99"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8d935f924bbab8f0a9a28404422da8af4904e36d5c33fc6f677e4c4485515625"}, + {file = "Pillow-9.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fed1e1cf6a42577953abbe8e6cf2fe2f566daebde7c34724ec8803c4c0cda579"}, + {file = "Pillow-9.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c1170d6b195555644f0616fd6ed929dfcf6333b8675fcca044ae5ab110ded296"}, + {file = "Pillow-9.5.0-cp311-cp311-win32.whl", hash = "sha256:54f7102ad31a3de5666827526e248c3530b3a33539dbda27c6843d19d72644ec"}, + {file = "Pillow-9.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:cfa4561277f677ecf651e2b22dc43e8f5368b74a25a8f7d1d4a3a243e573f2d4"}, + {file = "Pillow-9.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:965e4a05ef364e7b973dd17fc765f42233415974d773e82144c9bbaaaea5d089"}, + {file = "Pillow-9.5.0-cp312-cp312-win32.whl", hash = "sha256:22baf0c3cf0c7f26e82d6e1adf118027afb325e703922c8dfc1d5d0156bb2eeb"}, + {file = "Pillow-9.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:432b975c009cf649420615388561c0ce7cc31ce9b2e374db659ee4f7d57a1f8b"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:833b86a98e0ede388fa29363159c9b1a294b0905b5128baf01db683672f230f5"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aaf305d6d40bd9632198c766fb64f0c1a83ca5b667f16c1e79e1661ab5060140"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0852ddb76d85f127c135b6dd1f0bb88dbb9ee990d2cd9aa9e28526c93e794fba"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:91ec6fe47b5eb5a9968c79ad9ed78c342b1f97a091677ba0e012701add857829"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cb841572862f629b99725ebaec3287fc6d275be9b14443ea746c1dd325053cbd"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c380b27d041209b849ed246b111b7c166ba36d7933ec6e41175fd15ab9eb1572"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c9af5a3b406a50e313467e3565fc99929717f780164fe6fbb7704edba0cebbe"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5671583eab84af046a397d6d0ba25343c00cd50bce03787948e0fff01d4fd9b1"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:84a6f19ce086c1bf894644b43cd129702f781ba5751ca8572f08aa40ef0ab7b7"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1e7723bd90ef94eda669a3c2c19d549874dd5badaeefabefd26053304abe5799"}, + {file = "Pillow-9.5.0.tar.gz", hash = "sha256:bf548479d336726d7a0eceb6e767e179fbde37833ae42794602631a070d630f1"}, +] + +[[package]] +name = "psycopg2" +version = "2.9.9" +requires_python = ">=3.7" +summary = "psycopg2 - Python-PostgreSQL Database Adapter" +files = [ + {file = "psycopg2-2.9.9-cp311-cp311-win32.whl", hash = "sha256:ade01303ccf7ae12c356a5e10911c9e1c51136003a9a1d92f7aa9d010fb98372"}, + {file = "psycopg2-2.9.9-cp311-cp311-win_amd64.whl", hash = "sha256:121081ea2e76729acfb0673ff33755e8703d45e926e416cb59bae3a86c6a4981"}, + {file = "psycopg2-2.9.9-cp312-cp312-win32.whl", hash = "sha256:d735786acc7dd25815e89cc4ad529a43af779db2e25aa7c626de864127e5a024"}, + {file = "psycopg2-2.9.9-cp312-cp312-win_amd64.whl", hash = "sha256:a7653d00b732afb6fc597e29c50ad28087dcb4fbfb28e86092277a559ae4e693"}, + {file = "psycopg2-2.9.9.tar.gz", hash = "sha256:d1454bde93fb1e224166811694d600e746430c006fbb031ea06ecc2ea41bf156"}, +] + +[[package]] +name = "pydantic" +version = "1.10.13" +requires_python = ">=3.7" +summary = "Data validation and settings management using python type hints" +dependencies = [ + "typing-extensions>=4.2.0", +] +files = [ + {file = "pydantic-1.10.13-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c553f6a156deb868ba38a23cf0df886c63492e9257f60a79c0fd8e7173537653"}, + {file = "pydantic-1.10.13-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5e08865bc6464df8c7d61439ef4439829e3ab62ab1669cddea8dd00cd74b9ffe"}, + {file = "pydantic-1.10.13-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e31647d85a2013d926ce60b84f9dd5300d44535a9941fe825dc349ae1f760df9"}, + {file = "pydantic-1.10.13-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:210ce042e8f6f7c01168b2d84d4c9eb2b009fe7bf572c2266e235edf14bacd80"}, + {file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8ae5dd6b721459bfa30805f4c25880e0dd78fc5b5879f9f7a692196ddcb5a580"}, + {file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f8e81fc5fb17dae698f52bdd1c4f18b6ca674d7068242b2aff075f588301bbb0"}, + {file = "pydantic-1.10.13-cp311-cp311-win_amd64.whl", hash = "sha256:61d9dce220447fb74f45e73d7ff3b530e25db30192ad8d425166d43c5deb6df0"}, + {file = "pydantic-1.10.13-py3-none-any.whl", hash = "sha256:b87326822e71bd5f313e7d3bfdc77ac3247035ac10b0c0618bd99dcf95b1e687"}, + {file = "pydantic-1.10.13.tar.gz", hash = "sha256:32c8b48dcd3b2ac4e78b0ba4af3a2c2eb6048cb75202f0ea7b34feb740efc340"}, +] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +summary = "Extensions to the standard Python datetime module" +dependencies = [ + "six>=1.5", +] +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] + +[[package]] +name = "pytz" +version = "2023.3.post1" +summary = "World timezone definitions, modern and historical" +files = [ + {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, + {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, +] + +[[package]] +name = "requests" +version = "2.31.0" +requires_python = ">=3.7" +summary = "Python HTTP for Humans." +dependencies = [ + "certifi>=2017.4.17", + "charset-normalizer<4,>=2", + "idna<4,>=2.5", + "urllib3<3,>=1.21.1", +] +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[[package]] +name = "six" +version = "1.16.0" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +summary = "Python 2 and 3 compatibility utilities" +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 = "soupsieve" +version = "2.5" +requires_python = ">=3.8" +summary = "A modern CSS selector implementation for Beautiful Soup." +files = [ + {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"}, + {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, +] + +[[package]] +name = "sqlparse" +version = "0.4.4" +requires_python = ">=3.5" +summary = "A non-validating SQL parser." +files = [ + {file = "sqlparse-0.4.4-py3-none-any.whl", hash = "sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3"}, + {file = "sqlparse-0.4.4.tar.gz", hash = "sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c"}, +] + +[[package]] +name = "tablib" +version = "3.5.0" +requires_python = ">=3.8" +summary = "Format agnostic tabular data library (XLS, JSON, YAML, CSV, etc.)" +files = [ + {file = "tablib-3.5.0-py3-none-any.whl", hash = "sha256:9821caa9eca6062ff7299fa645e737aecff982e6b2b42046928a6413c8dabfd9"}, + {file = "tablib-3.5.0.tar.gz", hash = "sha256:f6661dfc45e1d4f51fa8a6239f9c8349380859a5bfaa73280645f046d6c96e33"}, +] + +[[package]] +name = "tablib" +version = "3.5.0" +extras = ["xls", "xlsx"] +requires_python = ">=3.8" +summary = "Format agnostic tabular data library (XLS, JSON, YAML, CSV, etc.)" +dependencies = [ + "openpyxl>=2.6.0", + "tablib==3.5.0", + "xlrd", + "xlwt", +] +files = [ + {file = "tablib-3.5.0-py3-none-any.whl", hash = "sha256:9821caa9eca6062ff7299fa645e737aecff982e6b2b42046928a6413c8dabfd9"}, + {file = "tablib-3.5.0.tar.gz", hash = "sha256:f6661dfc45e1d4f51fa8a6239f9c8349380859a5bfaa73280645f046d6c96e33"}, +] + +[[package]] +name = "telepath" +version = "0.3.1" +requires_python = ">=3.8" +summary = "A library for exchanging data between Python and JavaScript" +files = [ + {file = "telepath-0.3.1.tar.gz", hash = "sha256:925c0609e0a8a6488ec4a55b19d485882cf72223b2b19fe2359a50fddd813c9c"}, +] + +[[package]] +name = "typing-extensions" +version = "4.8.0" +requires_python = ">=3.8" +summary = "Backported and Experimental Type Hints for Python 3.8+" +files = [ + {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, + {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, +] + +[[package]] +name = "tzdata" +version = "2023.3" +requires_python = ">=2" +summary = "Provider of IANA time zone data" +files = [ + {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"}, + {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"}, +] + +[[package]] +name = "urllib3" +version = "2.0.7" +requires_python = ">=3.7" +summary = "HTTP library with thread-safe connection pooling, file post, and more." +files = [ + {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"}, + {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"}, +] + +[[package]] +name = "wagtail" +version = "4.0.4" +requires_python = ">=3.7" +summary = "A Django content management system." +dependencies = [ + "Django<4.2,>=3.2", + "Pillow<10.0.0,>=4.0.0", + "Willow<1.5,>=1.4", + "anyascii>=0.1.5", + "beautifulsoup4<4.12,>=4.8", + "django-filter<23,>=2.2", + "django-modelcluster<7.0,>=6.0", + "django-permissionedforms<1.0,>=0.1", + "django-taggit<4.0,>=2.0", + "django-treebeard<5.0,>=4.5.1", + "djangorestframework<4.0,>=3.11.1", + "draftjs-exporter<3.0,>=2.1.5", + "html5lib<2,>=0.999", + "l18n>=2018.5", + "requests<3.0,>=2.11.1", + "tablib[xls,xlsx]>=0.14.0", + "telepath<1,>=0.1.1", + "xlsxwriter<4.0,>=1.2.8", +] +files = [ + {file = "wagtail-4.0.4-py3-none-any.whl", hash = "sha256:43b35e8e29bcc83a3ddf60f08e8c22fea1e819f338bcba73a4b290771233809a"}, + {file = "wagtail-4.0.4.tar.gz", hash = "sha256:8799c7550cc033c8e85aeeaf6f91b5343d7dee72fecd5d4093499af9d3aeaa1d"}, +] + +[[package]] +name = "wagtail-factories" +version = "3.1.0" +summary = "Factory boy classes for wagtail" +dependencies = [ + "factory-boy>=3.2", + "wagtail>=2.15", +] +files = [ + {file = "wagtail_factories-3.1.0-py2.py3-none-any.whl", hash = "sha256:26b42998420005ab556f714e72e4a53427aac59ae595c66d1379a2c141f92be5"}, + {file = "wagtail_factories-3.1.0.tar.gz", hash = "sha256:ea366dc1d399e9c24218366fc80a104f51c3f18469ed19c576e15023a226c942"}, +] + +[[package]] +name = "webencodings" +version = "0.5.1" +summary = "Character encoding aliases for legacy web content" +files = [ + {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, + {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, +] + +[[package]] +name = "willow" +version = "1.4.1" +requires_python = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" +summary = "A Python image library that sits on top of Pillow, Wand and OpenCV" +files = [ + {file = "Willow-1.4.1-py2.py3-none-any.whl", hash = "sha256:fc4042696d090e75aef922fa1ed26d483c764f005b36cf523cf7c34e69d5dd7a"}, + {file = "Willow-1.4.1.tar.gz", hash = "sha256:0df8ff528531e00b48d40bf72ed81beac1dc82f2d42e5bbed4aff0218bef8c0d"}, +] + +[[package]] +name = "xlrd" +version = "2.0.1" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +summary = "Library for developers to extract data from Microsoft Excel (tm) .xls spreadsheet files" +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]] +name = "xlsxwriter" +version = "3.1.9" +requires_python = ">=3.6" +summary = "A Python module for creating Excel XLSX files." +files = [ + {file = "XlsxWriter-3.1.9-py3-none-any.whl", hash = "sha256:b61c1a0c786f82644936c0936ec96ee96cd3afb9440094232f7faef9b38689f0"}, + {file = "XlsxWriter-3.1.9.tar.gz", hash = "sha256:de810bf328c6a4550f4ffd6b0b34972aeb7ffcf40f3d285a0413734f9b63a929"}, +] + +[[package]] +name = "xlwt" +version = "1.3.0" +summary = "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+" +files = [ + {file = "xlwt-1.3.0-py2.py3-none-any.whl", hash = "sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e"}, + {file = "xlwt-1.3.0.tar.gz", hash = "sha256:c59912717a9b28f1a3c2a98fd60741014b06b043936dcecbc113eaaada156c88"}, +] diff --git a/pdm.toml b/pdm.toml new file mode 100644 index 0000000..07d8848 --- /dev/null +++ b/pdm.toml @@ -0,0 +1,5 @@ +[venv] +with_pip = true + +[strategy] +update = 'eager' diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..cf9a154 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,10 @@ + +[project] +# PEP 621 project metadata +# See https://www.python.org/dev/peps/pep-0621/ +dependencies = ["Django<4.2,>=4.1.1", "wagtail<4.1,>=4.0.4", "wagtail-factories<3.2,>=3.1.0", "pydantic<2.0,>=1.10.2", "psycopg2<2.10,>=2.9.3"] +requires-python = ">=3.11" + +[build-system] +requires = ["pdm-backend"] +build-backend = "pdm.backend"