diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6ee3394cb0ed106a8deaadc79e9d723c4401f485..1b40df197dd94deb70e14407da9b5c0a6f7175ac 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -28,6 +28,8 @@ test: - adduser --disabled-password --gecos "Test User" testuser - chown -R testuser . script: + - sudo apt update + - sudo apt install python3-ldap libldap2-dev libssl-dev libsasl2-dev python3.7-dev -y - sudo -u testuser env TEST_SELENIUM_HUB=http://selenium:4444/wd/hub TEST_SELENIUM_BROWSERS=firefox diff --git a/.gitmodules b/.gitmodules index 33ef9e8df0ca7f341b1da2ea53faf28ddab5ba1e..0b1ff289423a93278ac8d274890a2b5ae0788e1a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,3 @@ -[submodule "apps/official/AlekSIS-App-Alsijil"] - path = apps/official/AlekSIS-App-Alsijil - url = https://edugit.org/AlekSIS/Official/AlekSIS-App-Alsijil - ignore = untracked [submodule "apps/official/AlekSIS-App-Chronos"] path = apps/official/AlekSIS-App-Chronos url = https://edugit.org/AlekSIS/Official/AlekSIS-App-Chronos diff --git a/Dockerfile b/Dockerfile index 660874f026ffaba394d52493c8c85b38cd3923e5..0c4f3b52ededb87de3ea36f7814d155aaa20026d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.8-buster +FROM python:3.8-buster AS core # Configure Python to be nice inside Docker and pip to stfu ENV PYTHONUNBUFFERED 1 @@ -36,7 +36,36 @@ RUN set -e; \ eatmydata poetry install; \ eatmydata pip install gunicorn django-compressor +# Declare a persistent volume for all data +VOLUME /var/lib/aleksis + +# Define entrypoint and gunicorn running on port 8000 +EXPOSE 8000 +COPY docker/entrypoint.sh /usr/local/bin/ +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] + +# Install core extras +FROM core AS core-extras +ARG EXTRA_LDAP=1 +ARG EXTRA_CELERY=1 +WORKDIR /usr/src/app + +# LDAP +RUN if [ $EXTRA_LDAP = 1 ] ; then \ + eatmydata apt-get install -y --no-install-recommends \ + libldap2-dev \ + libsasl2-dev \ + ldap-utils; \ + eatmydata poetry install -E ldap; \ + fi; + +# Celery +RUN if [ $EXTRA_CELERY = 1 ] ; then \ + eatmydata poetry install -E celery; \ + fi; + # Install official apps +FROM core-extras AS apps COPY apps ./apps/ RUN set -e; \ for d in apps/official/*; do \ @@ -47,11 +76,13 @@ RUN set -e; \ done # Build messages and assets +FROM apps as assets RUN eatmydata python manage.py compilemessages && \ eatmydata python manage.py yarn install && \ eatmydata python manage.py collectstatic --no-input --clear # Clean up build dependencies +FROM assets AS clean RUN set -e; \ eatmydata apt-get remove --purge -y \ build-essential \ @@ -64,11 +95,3 @@ RUN set -e; \ eatmydata pip uninstall -y poetry; \ rm -f /var/lib/apt/lists/*_*; \ rm -rf /root/.cache - -# Declare a persistent volume for all data -VOLUME /var/lib/aleksis - -# Define entrypoint and gunicorn running on port 8000 -EXPOSE 8000 -COPY docker/entrypoint.sh /usr/local/bin/ -ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] diff --git a/aleksis/core/forms.py b/aleksis/core/forms.py index aa9d9f8fc52d535e14a74cec20ab64d9bc9698e4..fd331592f24d3527c3edfb2726cce25ec83095fe 100644 --- a/aleksis/core/forms.py +++ b/aleksis/core/forms.py @@ -6,7 +6,7 @@ from django.contrib.auth import get_user_model from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ValidationError from django.utils import timezone -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django_select2.forms import ModelSelect2MultipleWidget, Select2Widget from material import Layout, Fieldset, Row @@ -55,7 +55,25 @@ PersonsAccountsFormSet = forms.modelformset_factory( ) -class EditPersonForm(forms.ModelForm): +class EditPersonForm(ExtensibleForm): + layout = Layout( + Fieldset( + _("Base data"), + "short_name", + Row("user", "primary_group"), + "is_active", + Row("first_name", "additional_name", "last_name"), + ), + Fieldset(_("Address"), Row("street", "housenumber"), Row("postal_code", "place")), + Fieldset(_("Contact data"), "email", Row("phone_number", "mobile_number")), + Fieldset( + _("Advanced personal data"), + Row("sex", "date_of_birth"), + Row("photo", "photo_cropping"), + "guardians", + ), + ) + class Meta: model = Person fields = [ @@ -76,6 +94,8 @@ class EditPersonForm(forms.ModelForm): "sex", "photo", "photo_cropping", + "guardians", + "primary_group", ] widgets = {"user": Select2Widget} @@ -105,10 +125,15 @@ class EditPersonForm(forms.ModelForm): self.cleaned_data["user"] = new_user_obj -class EditGroupForm(forms.ModelForm): +class EditGroupForm(ExtensibleForm): + layout = Layout( + Fieldset(_("Common data"), "name", "short_name"), + Fieldset(_("Persons"), "members", "owners", "parent_groups"), + ) + class Meta: model = Group - fields = ["name", "short_name", "members", "owners", "parent_groups"] + exclude = [] widgets = { "members": ModelSelect2MultipleWidget( search_fields=[ @@ -130,13 +155,20 @@ class EditGroupForm(forms.ModelForm): } -class EditSchoolForm(forms.ModelForm): +class EditSchoolForm(ExtensibleForm): + layout = Layout( + Fieldset(_("School name"), "name", "name_official"), + Fieldset(_("School logo"), Row("logo", "logo_cropping")), + ) + class Meta: model = School fields = ["name", "name_official", "logo", "logo_cropping"] -class EditTermForm(forms.ModelForm): +class EditTermForm(ExtensibleForm): + layout = Layout("caption", Row("date_start", "date_end")) + class Meta: model = SchoolTerm fields = ["caption", "date_start", "date_end"] @@ -152,7 +184,9 @@ class AnnouncementForm(ExtensibleForm): valid_until_date = forms.DateField(label=_("Date")) valid_until_time = forms.TimeField(label=_("Time")) - persons = forms.ModelMultipleChoiceField(Person.objects.all(), label=_("Persons"), required=False) + persons = forms.ModelMultipleChoiceField( + Person.objects.all(), label=_("Persons"), required=False + ) groups = forms.ModelMultipleChoiceField(Group.objects.all(), label=_("Groups"), required=False) layout = Layout( diff --git a/aleksis/core/locale/de_DE/LC_MESSAGES/django.po b/aleksis/core/locale/de_DE/LC_MESSAGES/django.po index df3f09466923b65baf06bf60f955a0c5347e1d54..ccd9c971f5d0615838e6d81eb5b9c56f6344601a 100644 --- a/aleksis/core/locale/de_DE/LC_MESSAGES/django.po +++ b/aleksis/core/locale/de_DE/LC_MESSAGES/django.po @@ -8,9 +8,10 @@ msgstr "" "Project-Id-Version: AlekSIS (School Information System) 0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-03-30 09:18+0000\n" -"PO-Revision-Date: 2020-01-24 14:49+0000\n" +"PO-Revision-Date: 2020-04-14 18:42+0000\n" "Last-Translator: Tom Teichler <tom.teichler@teckids.org>\n" -"Language-Team: German <https://translate.edugit.org/projects/aleksis/aleksis/de/>\n" +"Language-Team: German <https://translate.edugit.org/projects/aleksis/aleksis/" +"de/>\n" "Language: de_DE\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -36,11 +37,11 @@ msgstr "Neues Benutzerkonto erstellen" #: forms.py:149 forms.py:152 msgid "Date" -msgstr "" +msgstr "Datum" #: forms.py:150 forms.py:153 msgid "Time" -msgstr "" +msgstr "Zeit" #: forms.py:155 menus.py:127 models.py:95 templates/core/persons.html:8 #: templates/core/persons.html:9 @@ -54,27 +55,31 @@ msgstr "Gruppen" #: forms.py:160 msgid "From when until when should the announcement be displayed?" -msgstr "" +msgstr "Von wann bis wann soll die Ankündigung angezeigt werden?" #: forms.py:163 msgid "Who should see the announcement?" -msgstr "" +msgstr "Wer soll die Ankündigung sehen?" #: forms.py:164 msgid "Write your announcement:" -msgstr "" +msgstr "Schreiben Sie ihre Ankündigung:" #: forms.py:203 msgid "You are not allowed to create announcements which are only valid in the past." msgstr "" +"Sie dürfen keine Ankündigungen erstellen, die nur für die Vergangenheit " +"gültig sind." #: forms.py:207 msgid "The from date and time must be earlier then the until date and time." msgstr "" +"Das Startdatum und die Startzeit müssen vor dem Enddatum und der Endzeit " +"sein." #: forms.py:215 msgid "You need at least one recipient." -msgstr "" +msgstr "Sie benötigen mindestens einen Empfänger." #: menus.py:7 templates/registration/login.html:21 #: templates/two_factor/core/login.html:6 @@ -85,7 +90,7 @@ msgstr "Anmelden" #: menus.py:13 msgid "Dashboard" -msgstr "" +msgstr "Dashboard" #: menus.py:19 msgid "Account" @@ -110,7 +115,7 @@ msgstr "Admin" #: menus.py:61 models.py:395 templates/core/announcement/list.html:7 #: templates/core/announcement/list.html:8 msgid "Announcements" -msgstr "" +msgstr "Ankündigungen" #: menus.py:70 templates/core/data_management.html:6 #: templates/core/data_management.html:7 @@ -132,7 +137,7 @@ msgstr "Schulverwaltung" #: menus.py:106 msgid "Backend Admin" -msgstr "" +msgstr "Backend-Administration" #: menus.py:117 msgid "People" @@ -168,16 +173,12 @@ msgid "School logo" msgstr "Schullogo" #: models.py:51 -#, fuzzy -#| msgid "School logo" msgid "School" -msgstr "Schullogo" +msgstr "Schule" #: models.py:52 -#, fuzzy -#| msgid "School logo" msgid "Schools" -msgstr "Schullogo" +msgstr "Schulen" #: models.py:60 msgid "Visible caption of the term" @@ -192,16 +193,12 @@ msgid "Effective end date of term" msgstr "Enddatum des Schuljahres" #: models.py:83 -#, fuzzy -#| msgid "Edit school term" msgid "School term" -msgstr "Schuljahr bearbeiten" +msgstr "Schuljahr" #: models.py:84 -#, fuzzy -#| msgid "Edit school term" msgid "School terms" -msgstr "Schuljahr bearbeiten" +msgstr "Schuljahre" #: models.py:94 templates/core/persons_accounts.html:36 msgid "Person" @@ -302,53 +299,51 @@ msgstr "Übergeordnete Gruppen" #: models.py:268 models.py:285 models.py:363 #: templates/core/announcement/list.html:18 msgid "Title" -msgstr "" +msgstr "Titel" #: models.py:269 models.py:286 models.py:364 msgid "Description" -msgstr "" +msgstr "Beschreibung" #: models.py:271 msgid "Application" -msgstr "" +msgstr "Anwendung" #: models.py:277 msgid "Activity" -msgstr "" +msgstr "Aktivität" #: models.py:278 msgid "Activities" -msgstr "" +msgstr "Aktivitäten" #: models.py:282 -#, fuzzy -#| msgid "Send" msgid "Sender" -msgstr "Absenden" +msgstr "Absender" #: models.py:287 models.py:365 models.py:518 msgid "Link" -msgstr "" +msgstr "Link" #: models.py:289 msgid "Read" -msgstr "" +msgstr "Gelesen" #: models.py:290 msgid "Sent" -msgstr "" +msgstr "Versandt" #: models.py:301 msgid "Notification" -msgstr "" +msgstr "Benachrichtigung" #: models.py:302 msgid "Notifications" -msgstr "" +msgstr "Benachrichtigungen" #: models.py:368 msgid "Date and time from when to show" -msgstr "" +msgstr "Datum und Uhrzeit des Anzeigestarts" #: models.py:371 msgid "Date and time until when to show" @@ -356,63 +351,63 @@ msgstr "" #: models.py:394 msgid "Announcement" -msgstr "" +msgstr "Ankündigung" #: models.py:422 msgid "Announcement recipient" -msgstr "" +msgstr "Empfänger der Ankündigung" #: models.py:423 msgid "Announcement recipients" -msgstr "" +msgstr "Empfänger der Ankündigung" #: models.py:473 msgid "Widget Title" -msgstr "" +msgstr "Widget-Titel" #: models.py:474 msgid "Activate Widget" -msgstr "" +msgstr "Widget aktivieren" #: models.py:486 msgid "Dashboard Widget" -msgstr "" +msgstr "Dashboard-Widget" #: models.py:487 msgid "Dashboard Widgets" -msgstr "" +msgstr "Dashboard-Widgets" #: models.py:491 msgid "Menu ID" -msgstr "" +msgstr "Menü-ID" #: models.py:492 msgid "Menu name" -msgstr "" +msgstr "Menü-Name" #: models.py:509 msgid "Custom menu" -msgstr "" +msgstr "Benutzerdefiniertes Menü" #: models.py:510 msgid "Custom menus" -msgstr "" +msgstr "Benutzerdefinierte Menüs" #: models.py:515 msgid "Menu" -msgstr "" +msgstr "Menü" #: models.py:520 msgid "Icon" -msgstr "" +msgstr "Icon" #: models.py:527 msgid "Custom menu item" -msgstr "" +msgstr "Benutzerdefiniertes Menüelement" #: models.py:528 msgid "Custom menu items" -msgstr "" +msgstr "Benutzerdefinierte Menüelemente" #: settings.py:254 msgid "German" @@ -424,65 +419,55 @@ msgstr "Englisch" #: settings.py:373 msgid "Site title" -msgstr "" +msgstr "Seitentitel" #: settings.py:374 msgid "Site description" -msgstr "" +msgstr "Seitenbeschreibung" #: settings.py:375 msgid "Primary colour" -msgstr "" +msgstr "Primärfarbe" #: settings.py:376 msgid "Secondary colour" -msgstr "" +msgstr "Akzentfarbe" #: settings.py:377 -#, fuzzy -#| msgid "Last name" msgid "Mail out name" -msgstr "Nachname" +msgstr "Ausgangsmailname" #: settings.py:378 -#, fuzzy -#| msgid "E-mail address" msgid "Mail out address" -msgstr "E-Mail-Adresse" +msgstr "E-Mail-Ausgangsadresse" #: settings.py:379 msgid "Link to privacy policy" -msgstr "" +msgstr "Link zur Datenschutzerklärung" #: settings.py:380 msgid "Link to imprint" -msgstr "" +msgstr "Link zum Impressum" #: settings.py:381 msgid "Name format of adresses" -msgstr "" +msgstr "Namensformat von Anreden" #: settings.py:382 msgid "Channels to allow for notifications" -msgstr "" +msgstr "Kanäle, welche für Benachrichtigungen erlaubt sind" #: settings.py:383 msgid "Regular expression to match primary group, e.g. '^Class .*'" -msgstr "" +msgstr "Regulärer Ausdruck um Primärgruppen zu finden, z. B. '^Class .*'" #: templates/403.html:10 -#, fuzzy -#| msgid "You are not allowed to access the requested page or object." msgid "Error (403): You are not allowed to access the requested page or object." -msgstr "Es ist Ihnen nicht erlaubt, auf die angefragte Seite oder das angefragte Objekt zuzugreifen." +msgstr "" +"Fehler(403): Es ist Ihnen nicht erlaubt, auf die angefragte Seite oder das " +"angefragte Objekt zuzugreifen." #: templates/403.html:12 -#, fuzzy -#| msgid "" -#| "\n" -#| " If you think this is an error in AlekSIS, please contact your site\n" -#| " administrators.\n" -#| " " msgid "" "\n" " If you think this is an error in AlekSIS, please contact your site\n" @@ -490,15 +475,16 @@ msgid "" " " msgstr "" "\n" -" Wenn Sie der Meinung sind, dass es sich um einen Fehler in AlekSIS handelt, kontaktieren Sie bitte einen Ihrer\n" +" Wenn Sie der Meinung sind, dass es sich um einen Fehler in AlekSIS " +"handelt, kontaktieren Sie bitte einen Ihrer\n" " Systemadministratoren:\n" -" " +" " #: templates/404.html:10 -#, fuzzy -#| msgid "The requested page or object was not found." msgid "Error (404): The requested page or object was not found." -msgstr "Die angefragte Seite oder das angefragte Objekt wurde nicht gefunden." +msgstr "" +"Fehler (404): Die angefragte Seite oder das angefragte Objekt wurde nicht " +"gefunden." #: templates/404.html:12 #, fuzzy @@ -514,16 +500,11 @@ msgid "" " " msgstr "" "\n" -" Wenn Sie über einen Link auf einer externen Seite hierher gelangt sind, ist es möglich, dass dieser veraltet war.\n" -" " +" Wenn Sie über einen Link auf einer externen Seite hierher gelangt " +"sind, ist es möglich, dass dieser veraltet war.\n" +" " #: templates/404.html:16 -#, fuzzy -#| msgid "" -#| "\n" -#| " If you think this is an error in AlekSIS, please contact your site\n" -#| " administrators.\n" -#| " " msgid "" "\n" " If you think this is an error in AlekSIS, please contact your site\n" @@ -531,29 +512,16 @@ msgid "" " " msgstr "" "\n" -" Wenn Sie der Meinung sind, dass es sich um einen Fehler in AlekSIS handelt, kontaktieren Sie bitte einen Ihrer\n" +" Wenn Sie der Meinung sind, dass es sich um einen Fehler in AlekSIS " +"handelt, kontaktieren Sie bitte einen Ihrer\n" " Systemadministratoren:\n" -" " +" " #: templates/500.html:10 -#, fuzzy -#| msgid "" -#| "\n" -#| " An unexpected error has occured.\n" -#| " " msgid "Error (500): An unexpected error has occured.." -msgstr "" -"\n" -" Ein unerwarteter Fehler ist aufgetreten.\n" -" " +msgstr "Error (500): Ein unerwarteter Fehler ist aufgetreten.." #: templates/500.html:12 -#, fuzzy -#| msgid "" -#| "\n" -#| " Your site administrators will automatically be notified about this\n" -#| " error.\n" -#| " " msgid "" "\n" " Your site administrators will automatically be notified about this\n" @@ -561,63 +529,59 @@ msgid "" " " msgstr "" "\n" -" Ihre Administratoren werden automatisch über diesen Fehler informiert.\n" -" " +" Ihre Administratoren werden automatisch über diesen Fehler informiert." +"\n" +" " #: templates/503.html:10 msgid "The maintenance mode is currently enabled. Please try again later." msgstr "Der Wartungsmodus ist aktuell aktiviert. Bitte versuchen Sie es später erneut." #: templates/503.html:12 -#, fuzzy -#| msgid "" -#| "\n" -#| " If you think this is an error in AlekSIS, please contact your site\n" -#| " administrators.\n" -#| " " msgid "" "\n" " This page is currently unavailable. If this error stays, contact your site administrators:\n" " " msgstr "" "\n" -" Wenn Sie der Meinung sind, dass es sich um einen Fehler in AlekSIS handelt, kontaktieren Sie bitte einen Ihrer\n" +" Diese Seite ist aktuell nicht erreichbar. Wenn dieser Fehler bestehen " +"bleibt, kontaktieren Sie bitte einen Ihrer\n" " Systemadministratoren:\n" -" " +" " #: templates/core/announcement/form.html:10 #: templates/core/announcement/form.html:17 msgid "Edit announcement" -msgstr "" +msgstr "Ankündigung bearbeiten" #: templates/core/announcement/form.html:12 msgid "Publish announcement" -msgstr "" +msgstr "Ankündigung veröffentlichen" #: templates/core/announcement/form.html:19 #: templates/core/announcement/list.html:13 msgid "Publish new announcement" -msgstr "" +msgstr "Neue Ankündigung veröffentlichen" #: templates/core/announcement/form.html:30 msgid "Save und publish announcement" -msgstr "" +msgstr "Ankündigung speichern und veröffentlichen" #: templates/core/announcement/list.html:19 msgid "Valid from" -msgstr "" +msgstr "Gültig von" #: templates/core/announcement/list.html:20 msgid "Valid until" -msgstr "" +msgstr "Gültig bis" #: templates/core/announcement/list.html:21 msgid "Recipients" -msgstr "" +msgstr "Empfänger" #: templates/core/announcement/list.html:22 msgid "Actions" -msgstr "" +msgstr "Aktionen" #: templates/core/announcement/list.html:36 templates/core/group_full.html:15 #: templates/core/person_full.html:15 @@ -626,11 +590,11 @@ msgstr "Bearbeiten" #: templates/core/announcement/list.html:42 msgid "Delete" -msgstr "" +msgstr "Löschen" #: templates/core/announcement/list.html:50 msgid "There are no announcements." -msgstr "" +msgstr "Es gibt aktuell keine Ankündigungen." #: templates/core/announcements.html:9 templates/core/announcements.html:36 #, python-format @@ -639,6 +603,9 @@ msgid "" " Valid for %(from)s\n" " " msgstr "" +"\n" +" Gültig für %(from)s\n" +" " #: templates/core/announcements.html:13 #, python-format @@ -647,6 +614,9 @@ msgid "" " Valid from %(from)s until %(until)s\n" " " msgstr "" +"\n" +" Gültig von %(from)s bis %(until)s\n" +" " #: templates/core/announcements.html:40 #, python-format @@ -655,22 +625,25 @@ msgid "" " Valid for %(from)s – %(until)s\n" " " msgstr "" +"\n" +" Gültig von %(from)s – %(until)s\n" +" " #: templates/core/base.html:54 msgid "Logged in as" -msgstr "" +msgstr "Angemeldet als" #: templates/core/base.html:146 msgid "Impress" -msgstr "" +msgstr "Impressum" #: templates/core/base.html:154 msgid "Privacy Policy" -msgstr "" +msgstr "Datenschutzerklärung" #: templates/core/base_print.html:60 msgid "Powered by AlekSIS" -msgstr "" +msgstr "Betrieben mit AlekSIS" #: templates/core/edit_group.html:6 templates/core/edit_group.html:7 msgid "Edit group" @@ -693,57 +666,38 @@ msgid "Members" msgstr "Mitglieder" #: templates/core/groups.html:14 -#, fuzzy -#| msgid "Parent groups" msgid "Create group" -msgstr "Übergeordnete Gruppen" +msgstr "Gruppe erstellen" #: templates/core/index.html:4 msgid "Home" -msgstr "" +msgstr "Startseite" #: templates/core/index.html:11 -#, fuzzy -#| msgid "" -#| "\n" -#| " AlekSIS (School Information System)\n" -#| " " msgid "AlekSIS (School Information System)" -msgstr "" -"\n" -" AlekSIS (Schulinformationssystem)\n" -" " +msgstr "AlekSIS (Schulinformationssystem)" #: templates/core/index.html:43 msgid "Last activities" -msgstr "" +msgstr "Letzte Aktivitäten" #: templates/core/index.html:61 msgid "No activities available yet." -msgstr "" +msgstr "Aktuell keine Aktivitäten verfügbar." #: templates/core/index.html:66 msgid "Recent notifications" -msgstr "" +msgstr "Letzte Benachrichtigungen" #: templates/core/index.html:82 -#, fuzzy -#| msgid "Edit school information" msgid "More information →" -msgstr "Schulinformationen bearbeiten" +msgstr "Mehr Informationen →" #: templates/core/index.html:89 msgid "No notifications available yet." -msgstr "" +msgstr "Aktuell keine Benachrichtigungen verfügbar." #: templates/core/no_person.html:11 -#, fuzzy -#| msgid "" -#| "\n" -#| " Your user account is not linked to a person. This means you\n" -#| " cannot access any school-related information. Please contact\n" -#| " the managers of AlekSIS at your school.\n" -#| " " msgid "" "\n" " Your user account is not linked to a person. This means you\n" @@ -752,14 +706,16 @@ msgid "" " " msgstr "" "\n" -" Ihr Benutzerkonto ist nicht mit einer Person verknüpft. Das bedeutet, dass Sie\n" -" keine schulbezogenen Informationen aufrufen können. Bitte wenden Sie sich an\n" -" die Verwaltenden von AlekSIS an Ihrer Schule.\n" -" " +" Ihr Benutzerkonto ist nicht mit einer Person verknüpft. Das " +"bedeutet, dass Sie\n" +" keine schulbezogenen Informationen aufrufen können. Bitte wenden Sie " +"sich an\n" +" die Verwaltenden von AlekSIS an Ihrer Schule.\n" +" " #: templates/core/offline.html:6 msgid "No internet connection." -msgstr "" +msgstr "Keine Internetverbindung." #: templates/core/offline.html:9 msgid "" @@ -767,6 +723,13 @@ msgid "" " There was an error accessing this page. You probably don't have an internet connection. Check to see if your WiFi or mobile data is turned on and try again. If you think you are connected, please contact the system administrators:\n" " " msgstr "" +"\n" +" Es ist ein Fehler beim Aufrufen der Seite aufgetreten. Eventuell " +"haben Sie keine Internetverbindung. Bitte prüfen Sie, ob WLAN oder mobile " +"Daten aktiv sind, und probieren Sie es erneut. Wenn Sie der Meinung sind, " +"dass Sie mit dem Internet verbunden sind, kontaktieren Sie bitte einen Ihrer " +"Systemadministratoren:\n" +" " #: templates/core/person_full.html:19 msgid "Contact details" @@ -808,7 +771,7 @@ msgstr "Neues Konto" #: templates/core/save_button.html:3 msgid "Save" -msgstr "" +msgstr "Speichern" #: templates/core/school_management.html:6 #: templates/core/school_management.html:7 @@ -824,13 +787,15 @@ msgid "Maintenance mode enabled" msgstr "Wartungsmodus aktiviert" #: templates/core/system_status.html:23 -#, fuzzy -#| msgid "Only admin and visitors from internal IPs can access the site." msgid "" "\n" " Only admin and visitors from internal IPs can access thesite.\n" " " -msgstr "Nur Administratoren und Besucher von internen IP-Adressen können die Seite aufrufen." +msgstr "" +"\n" +" Nur Administratoren und Besucher von internen IP-Adressen " +"können die Seite aufrufen.\n" +" " #: templates/core/system_status.html:34 msgid "Maintenance mode disabled" @@ -845,26 +810,30 @@ msgid "Debug mode enabled" msgstr "Debug-Modus aktiviert" #: templates/core/system_status.html:47 -#, fuzzy -#| msgid "The web server throws back debug information on errors. Do not use in production!" msgid "" "\n" " The web server throws back debug information on errors. Do not use in production!\n" " " -msgstr "Der Server gibt Debug-Informationen bei Fehlern zurück. Nicht im Produktivbetrieb nutzen!" +msgstr "" +"\n" +" Der Server gibt Debug-Informationen bei Fehlern zurück. " +"Nicht im Produktivbetrieb nutzen!\n" +" " #: templates/core/system_status.html:54 msgid "Debug mode disabled" msgstr "Debug-Modus deaktivert" #: templates/core/system_status.html:56 -#, fuzzy -#| msgid "Debug mode is disabled. Default error pages are displayed on errors." msgid "" "\n" " Debug mode is disabled. Default error pages are displayed on errors.\n" " " -msgstr "Debug-Modus ist deaktiviert. Standard-Fehlerseiten werden bei Fehlern angezeigt." +msgstr "" +"\n" +" Debug-Modus ist deaktiviert. Standard-Fehlerseiten werden " +"bei Fehlern angezeigt.\n" +" " #: templates/impersonate/list_users.html:8 msgid "Impersonate user" @@ -872,23 +841,23 @@ msgstr "Als Benutzer verkleiden" #: templates/martor/editor.html:27 msgid "Uploading... please wait..." -msgstr "" +msgstr "Lädt hoch… bitte warten…" #: templates/martor/editor.html:36 msgid "Nothing to preview" -msgstr "" +msgstr "Keine Vorschau" #: templates/martor/emoji.html:4 msgid "Select Emoji to Insert" -msgstr "" +msgstr "Wählen Sie ein Emoji zum Einfügen aus" #: templates/martor/emoji.html:8 msgid "Preparing emojis..." -msgstr "" +msgstr "Bereite Emoji vor…" #: templates/martor/guide.html:8 msgid "Markdown Guide" -msgstr "" +msgstr "Markdown-Anleitung" #: templates/martor/guide.html:9 #, python-format @@ -897,14 +866,17 @@ msgid "" " documentation,\n" " <a href=\"%(doc_url)s\" target=\"_blank\">click here</a>" msgstr "" +"Diese Seite wird mit Markdown betrieben. Für komplette\n" +" Dokumentation,\n" +" <a href=\"%(doc_url)s\" target=\"_blank\">hier klicken</a>" #: templates/martor/guide.html:15 templates/martor/toolbar.html:42 msgid "Code" -msgstr "" +msgstr "Code" #: templates/martor/guide.html:16 msgid "Or" -msgstr "" +msgstr "oder" #: templates/martor/guide.html:19 msgid "... to Get" @@ -912,82 +884,82 @@ msgstr "" #: templates/martor/toolbar.html:3 msgid "Bold" -msgstr "" +msgstr "Fett" #: templates/martor/toolbar.html:6 msgid "Italic" -msgstr "" +msgstr "kursiv" #: templates/martor/toolbar.html:10 msgid "Horizontal Line" -msgstr "" +msgstr "horizontale Linie" #: templates/martor/toolbar.html:15 msgid "Heading" -msgstr "" +msgstr "Überschrift" #: templates/martor/toolbar.html:20 templates/martor/toolbar.html:23 #: templates/martor/toolbar.html:26 msgid "H" -msgstr "" +msgstr "H" #: templates/martor/toolbar.html:31 msgid "Pre or Code" -msgstr "" +msgstr "Pre oder Code" #: templates/martor/toolbar.html:38 msgid "Pre" -msgstr "" +msgstr "Pre" #: templates/martor/toolbar.html:48 msgid "Quote" -msgstr "" +msgstr "Zitat" #: templates/martor/toolbar.html:52 msgid "Unordered List" -msgstr "" +msgstr "Unsortierte Liste" #: templates/martor/toolbar.html:56 msgid "Ordered List" -msgstr "" +msgstr "Sortierte Liste" #: templates/martor/toolbar.html:60 msgid "URL/Link" -msgstr "" +msgstr "URL/Link" #: templates/martor/toolbar.html:82 msgid "Full Screen" -msgstr "" +msgstr "Vollbild" #: templates/martor/toolbar.html:86 msgid "Markdown Guide (Help)" -msgstr "" +msgstr "Markdown-Anleitung (Hilfe)" #: templates/two_factor/_base_focus.html:6 #: templates/two_factor/core/otp_required.html:22 #: templates/two_factor/core/setup.html:5 #: templates/two_factor/profile/profile.html:87 msgid "Enable Two-Factor Authentication" -msgstr "" +msgstr "Zwei-Faktor-Authentifizierung aktivieren" #: templates/two_factor/_wizard_actions.html:6 msgid "Cancel" -msgstr "" +msgstr "Abbrechen" #: templates/two_factor/_wizard_actions.html:15 #: templates/two_factor/_wizard_actions.html:20 msgid "Back" -msgstr "" +msgstr "Zurück" #: templates/two_factor/_wizard_actions.html:26 msgid "Next" -msgstr "" +msgstr "Weiter" #: templates/two_factor/core/backup_tokens.html:5 #: templates/two_factor/core/backup_tokens.html:9 #: templates/two_factor/profile/profile.html:46 msgid "Backup Tokens" -msgstr "" +msgstr "Backup-Token" #: templates/two_factor/core/backup_tokens.html:14 msgid "" @@ -999,55 +971,66 @@ msgid "" " below will be valid.\n" " " msgstr "" +"\n" +" Backup-Token können genutzt werden, wenn Ihre primären und Backup-\n" +" Telefonnummern nicht verfügbar sind. Die Backup-Tokens unten können " +"für\n" +" die Anmeldungsverifizierung genutzt werden. Wenn Sie alle Backup-" +"Tokens genutzt haben,\n" +" müssen Sie neue generieren. Nur gültige Backup-Tokens werden " +"angezeigt.\n" +" " #: templates/two_factor/core/backup_tokens.html:33 -#, fuzzy -#| msgid "" -#| "\n" -#| " There is no person with this id.\n" -#| " " msgid "" "\n" " Print these tokens and keep them somewhere safe.\n" " " msgstr "" "\n" -" Es existiert keine Person mit dieser ID.\n" +" Drucken Sie diese Tokens aus und bewahren Sie sie gut auf.\n" " " #: templates/two_factor/core/backup_tokens.html:39 msgid "You don't have any backup codes yet." -msgstr "" +msgstr "Sie haben aktuell keine Backup-Codes." #: templates/two_factor/core/backup_tokens.html:45 msgid "Back to Account Security" -msgstr "" +msgstr "Zurück zur Kontosicherheit" #: templates/two_factor/core/backup_tokens.html:49 msgid "Generate Tokens" -msgstr "" +msgstr "Tokens generieren" #: templates/two_factor/core/login.html:17 msgid "Enter your credentials." -msgstr "" +msgstr "Geben Sie Ihre Zugangsdaten ein." #: templates/two_factor/core/login.html:20 msgid "" "We are calling your phone right now, please enter the\n" " digits you hear." msgstr "" +"Wir rufen Ihr Telefon jetzt an, bitte geben Sie die\n" +" Zahlen ein, die Sie hören." #: templates/two_factor/core/login.html:23 msgid "" "We sent you a text message, please enter the tokens we\n" " sent." msgstr "" +"Wir haben Ihnen eine Textnachricht geschickt. Bitte geben Sie die Tokens ein," +"\n" +" die wir Ihnen geschickt haben." #: templates/two_factor/core/login.html:26 msgid "" "Please enter the tokens generated by your token\n" " generator." msgstr "" +"Bitte geben Sie den von Ihrem Token-Generator\n" +" generierten Token ein." #: templates/two_factor/core/login.html:30 msgid "" @@ -1058,19 +1041,19 @@ msgstr "" #: templates/two_factor/core/login.html:47 msgid "Or, alternatively, use one of your backup phones:" -msgstr "" +msgstr "Oder, alternativ, nutzen Sie eins Ihrer Backup-Telefone:" #: templates/two_factor/core/login.html:57 msgid "As a last resort, you can use a backup token:" -msgstr "" +msgstr "Als letzte Möglichkeit können Sie einen Backup-Token nutzen:" #: templates/two_factor/core/login.html:60 msgid "Use Backup Token" -msgstr "" +msgstr "Backup-Token nutzen" #: templates/two_factor/core/otp_required.html:9 msgid "Permission Denied" -msgstr "" +msgstr "Zugriff verwehrt" #: templates/two_factor/core/otp_required.html:10 msgid "" @@ -1088,12 +1071,12 @@ msgstr "" #: templates/two_factor/core/otp_required.html:19 msgid "Go back" -msgstr "" +msgstr "Zurück" #: templates/two_factor/core/phone_register.html:5 #: templates/two_factor/core/phone_register.html:9 msgid "Add Backup Phone" -msgstr "" +msgstr "Backup-Telefon hinzufügen" #: templates/two_factor/core/phone_register.html:12 msgid "" @@ -1185,7 +1168,7 @@ msgstr "" #: templates/two_factor/core/setup_complete.html:5 #: templates/two_factor/core/setup_complete.html:9 msgid "Two-Factor Authentication successfully enabled" -msgstr "" +msgstr "Zwei-Faktor-Authentifizierung erfolgreich aktiviert" #: templates/two_factor/core/setup_complete.html:14 msgid "" @@ -1193,18 +1176,20 @@ msgid "" " Congratulations, you've successfully enabled two-factor authentication.\n" " " msgstr "" +"\n" +" Gratulation, Sie haben die Zwei-Faktor-Authentifizierung erfolgreich " +"aktiviert.\n" +" " #: templates/two_factor/core/setup_complete.html:24 #: templates/two_factor/core/setup_complete.html:44 msgid "Back to Profile" -msgstr "" +msgstr "Zurück zum Profil" #: templates/two_factor/core/setup_complete.html:28 #: templates/two_factor/core/setup_complete.html:48 -#, fuzzy -#| msgid "Recent backup cron jobs" msgid "Generate backup codes" -msgstr "Letzte Backup-Cron-Jobs" +msgstr "Backup-Codes generieren" #: templates/two_factor/core/setup_complete.html:34 msgid "" @@ -1218,46 +1203,46 @@ msgstr "" #: templates/two_factor/core/setup_complete.html:52 #: templates/two_factor/profile/profile.html:41 msgid "Add Phone Number" -msgstr "" +msgstr "Telefonnummer hinzufügen" #: templates/two_factor/profile/disable.html:5 #: templates/two_factor/profile/disable.html:9 #: templates/two_factor/profile/profile.html:63 #: templates/two_factor/profile/profile.html:73 msgid "Disable Two-Factor Authentication" -msgstr "" +msgstr "Zwei-Faktor-Authentifizierung deaktiveren" #: templates/two_factor/profile/disable.html:12 msgid "You are about to disable two-factor authentication. This weakens your account security, are you sure?" msgstr "" +"Sie sind dabei, Zwei-Faktor-Authentifizierung zu deaktivieren. Das " +"verschlechtert Ihre Kontosicherheit. Sind Sie sicher?" #: templates/two_factor/profile/disable.html:26 msgid "Disable" -msgstr "" +msgstr "Deaktivieren" #: templates/two_factor/profile/profile.html:5 #: templates/two_factor/profile/profile.html:10 -#, fuzzy -#| msgid "Account" msgid "Account Security" -msgstr "Konto" +msgstr "Kontosicherheit" #: templates/two_factor/profile/profile.html:15 msgid "Tokens will be generated by your token generator." -msgstr "" +msgstr "Tokens werden von Ihrem Token-Generator generiert." #: templates/two_factor/profile/profile.html:17 #, python-format msgid "Primary method: %(primary)s" -msgstr "" +msgstr "Primäre Methode: %(primary)s" #: templates/two_factor/profile/profile.html:19 msgid "Tokens will be generated by your YubiKey." -msgstr "" +msgstr "Tokens werden von Ihrem YubiKey generiert." #: templates/two_factor/profile/profile.html:23 msgid "Backup Phone Numbers" -msgstr "" +msgstr "Backup-Telefonnummern" #: templates/two_factor/profile/profile.html:24 msgid "" @@ -1267,7 +1252,7 @@ msgstr "" #: templates/two_factor/profile/profile.html:33 msgid "Unregister" -msgstr "" +msgstr "Abmelden" #: templates/two_factor/profile/profile.html:48 msgid "" @@ -1276,11 +1261,7 @@ msgid "" msgstr "" #: templates/two_factor/profile/profile.html:50 -#, fuzzy, python-format -#| msgid "" -#| "\n" -#| " You are not linked to a person\n" -#| " " +#, python-format msgid "" "\n" " You have only one backup token remaining.\n" @@ -1291,16 +1272,16 @@ msgid_plural "" " " msgstr[0] "" "\n" -" Sie sind nicht mit einer Person verknüpft\n" +" Sie haben keinen Backup-Token übrig.\n" " " msgstr[1] "" "\n" -" Sie sind nicht mit einer Person verknüpft\n" +" Sie haben %(counter)s Backup-Tokens übrig.\n" " " #: templates/two_factor/profile/profile.html:59 msgid "Show Codes" -msgstr "" +msgstr "Codes anzeigen" #: templates/two_factor/profile/profile.html:65 msgid "" @@ -1321,11 +1302,11 @@ msgstr "" #: util/notifications.py:66 msgid "E-Mail" -msgstr "" +msgstr "E-Mail" #: util/notifications.py:67 msgid "SMS" -msgstr "" +msgstr "SMS" #: views.py:172 msgid "The person has been saved." @@ -1344,22 +1325,18 @@ msgid "The term has been saved." msgstr "Das Schuljahr wurde gespeichert." #: views.py:272 -#, fuzzy -#| msgid "You are not allowed to access the requested page or object." msgid "You are not allowed to mark notifications from other users as read!" -msgstr "Es ist Ihnen nicht erlaubt, auf die angefragte Seite oder das angefragte Objekt zuzugreifen." +msgstr "" +"Es ist Ihnen nicht erlaubt, Benachrichtigungen von anderen Benutzern als " +"gelesen zu markieren!" #: views.py:307 -#, fuzzy -#| msgid "The term has been saved." msgid "The announcement has been saved." -msgstr "Das Schuljahr wurde gespeichert." +msgstr "Die Ankündigung wurde gespeichert." #: views.py:320 -#, fuzzy -#| msgid "The term has been saved." msgid "The announcement has been deleted." -msgstr "Das Schuljahr wurde gespeichert." +msgstr "Ankündigung wurde gelöscht." #~ msgid "Website" #~ msgstr "Website" diff --git a/aleksis/core/locale/la/LC_MESSAGES/django.po b/aleksis/core/locale/la/LC_MESSAGES/django.po index b511f033217d5d5cb72a934b4c1275be8c9361f1..753ec75d839f32e2238bca0315c607df5559d70e 100644 --- a/aleksis/core/locale/la/LC_MESSAGES/django.po +++ b/aleksis/core/locale/la/LC_MESSAGES/django.po @@ -3,20 +3,21 @@ # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # -#, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-03-30 09:18+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"Language: \n" +"PO-Revision-Date: 2020-04-14 18:42+0000\n" +"Last-Translator: Jonathan Weth <teckids@jonathanweth.de>\n" +"Language-Team: Latin <https://translate.edugit.org/projects/aleksis/aleksis/" +"la/>\n" +"Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 3.8\n" #: forms.py:38 forms.py:93 msgid "You cannot set a new username when also selecting an existing user." @@ -36,16 +37,16 @@ msgstr "" #: forms.py:149 forms.py:152 msgid "Date" -msgstr "" +msgstr "dies" #: forms.py:150 forms.py:153 msgid "Time" -msgstr "" +msgstr "tempus" #: forms.py:155 menus.py:127 models.py:95 templates/core/persons.html:8 #: templates/core/persons.html:9 msgid "Persons" -msgstr "" +msgstr "personae" #: forms.py:156 menus.py:133 models.py:232 templates/core/groups.html:8 #: templates/core/groups.html:9 templates/core/person_full.html:79 @@ -62,7 +63,7 @@ msgstr "" #: forms.py:164 msgid "Write your announcement:" -msgstr "" +msgstr "Scribe nuntium:" #: forms.py:203 msgid "You are not allowed to create announcements which are only valid in the past." @@ -85,7 +86,7 @@ msgstr "" #: menus.py:13 msgid "Dashboard" -msgstr "" +msgstr "Forum" #: menus.py:19 msgid "Account" @@ -105,22 +106,22 @@ msgstr "" #: menus.py:52 msgid "Admin" -msgstr "" +msgstr "Administratio" #: menus.py:61 models.py:395 templates/core/announcement/list.html:7 #: templates/core/announcement/list.html:8 msgid "Announcements" -msgstr "" +msgstr "Nuntii" #: menus.py:70 templates/core/data_management.html:6 #: templates/core/data_management.html:7 msgid "Data management" -msgstr "" +msgstr "Adminstratio datarum" #: menus.py:79 templates/core/system_status.html:5 #: templates/core/system_status.html:7 msgid "System status" -msgstr "" +msgstr "Status systemae" #: menus.py:88 msgid "Impersonation" @@ -128,7 +129,7 @@ msgstr "" #: menus.py:97 msgid "Manage school" -msgstr "" +msgstr "Administra scholam" #: menus.py:106 msgid "Backend Admin" @@ -136,40 +137,40 @@ msgstr "" #: menus.py:117 msgid "People" -msgstr "" +msgstr "Personae" #: menus.py:139 msgid "Persons and accounts" -msgstr "" +msgstr "Personae et computi" #: menus.py:152 msgid "Edit school information" -msgstr "" +msgstr "Muta informationes scolae" #: menus.py:153 templates/core/edit_schoolterm.html:8 #: templates/core/edit_schoolterm.html:9 msgid "Edit school term" -msgstr "" +msgstr "Muta anum scolae" #: models.py:31 models.py:517 msgid "Name" -msgstr "" +msgstr "Nomen" #: models.py:33 msgid "Official name" -msgstr "" +msgstr "Officialis nomen" #: models.py:35 msgid "Official name of the school, e.g. as given by supervisory authority" -msgstr "" +msgstr "Officialis nomen scolae, e. g." #: models.py:38 msgid "School logo" -msgstr "" +msgstr "Imago scolae" #: models.py:51 msgid "School" -msgstr "" +msgstr "Scola" #: models.py:52 msgid "Schools" @@ -189,23 +190,23 @@ msgstr "" #: models.py:83 msgid "School term" -msgstr "" +msgstr "Anus scolae" #: models.py:84 msgid "School terms" -msgstr "" +msgstr "ani scolae" #: models.py:94 templates/core/persons_accounts.html:36 msgid "Person" -msgstr "" +msgstr "Persona" #: models.py:97 msgid "female" -msgstr "" +msgstr "femininum" #: models.py:97 msgid "male" -msgstr "" +msgstr "maskulinum" #: models.py:102 msgid "Is person active?" @@ -213,47 +214,47 @@ msgstr "" #: models.py:104 msgid "First name" -msgstr "" +msgstr "Primus nomen" #: models.py:105 msgid "Last name" -msgstr "" +msgstr "Secondus nomen" #: models.py:107 msgid "Additional name(s)" -msgstr "" +msgstr "addita nomines" #: models.py:111 msgid "Short name" -msgstr "" +msgstr "Breve nomen" #: models.py:114 msgid "Street" -msgstr "" +msgstr "Via" #: models.py:115 msgid "Street number" -msgstr "" +msgstr "Numerus domini" #: models.py:116 msgid "Postal code" -msgstr "" +msgstr "Numerus directorius" #: models.py:117 msgid "Place" -msgstr "" +msgstr "Urbs" #: models.py:119 msgid "Home phone" -msgstr "" +msgstr "Numerus telephoni domi" #: models.py:120 msgid "Mobile phone" -msgstr "" +msgstr "Numerus telephoni mobilis" #: models.py:122 msgid "E-mail address" -msgstr "" +msgstr "Inscriptio electronica" #: models.py:124 msgid "Date of birth" diff --git a/aleksis/core/menus.py b/aleksis/core/menus.py index 8e5e4a0aef23e09c650d6c1749569a69cc1696ac..1ed63d98fe397c11836350d0d11bea8e2750ffaf 100644 --- a/aleksis/core/menus.py +++ b/aleksis/core/menus.py @@ -1,5 +1,5 @@ from django.conf import settings -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ MENUS = { "NAV_MENU_CORE": [ @@ -46,6 +46,12 @@ MENUS = { lambda request: "two_factor" in settings.INSTALLED_APPS, ], }, + { + "name": _("Me"), + "url": "person", + "icon": "insert_emoticon", + "validators": ["menu_generator.validators.is_authenticated"], + }, ], }, { diff --git a/aleksis/core/migrations/0021_person_description_field.py b/aleksis/core/migrations/0021_person_description_field.py new file mode 100644 index 0000000000000000000000000000000000000000..6e8aa927c1b04a2b5812dd54b86d0a0a67397cb1 --- /dev/null +++ b/aleksis/core/migrations/0021_person_description_field.py @@ -0,0 +1,18 @@ +# Generated by Django 3.0.5 on 2020-04-13 13:24 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0020_incease_length_of_fields'), + ] + + operations = [ + migrations.AddField( + model_name='person', + name='description', + field=models.TextField(blank=True, null=True, verbose_name='Description'), + ), + ] diff --git a/aleksis/core/migrations/0022_group_types.py b/aleksis/core/migrations/0022_group_types.py new file mode 100644 index 0000000000000000000000000000000000000000..c521da4a6f5a5d6f6c314ee0b34e57cb374c9e7c --- /dev/null +++ b/aleksis/core/migrations/0022_group_types.py @@ -0,0 +1,33 @@ +# Generated by Django 3.0.5 on 2020-04-13 13:44 + +import django.contrib.postgres.fields.jsonb +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0021_person_description_field'), + ] + + operations = [ + migrations.CreateModel( + name='GroupType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('extended_data', django.contrib.postgres.fields.jsonb.JSONField(default=dict, editable=False)), + ('name', models.CharField(max_length=50, verbose_name='Title of type')), + ('description', models.CharField(max_length=500, verbose_name='Description')), + ], + options={ + 'verbose_name': 'Group type', + 'verbose_name_plural': 'Group types', + }, + ), + migrations.AddField( + model_name='group', + name='type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='type', to='core.GroupType', verbose_name='Type of group'), + ), + ] diff --git a/aleksis/core/mixins.py b/aleksis/core/mixins.py index 7df1ba631626152828749cdf4fd28aa0fcd2d36d..574cf185cc2350e3e7b45f7723c8e9313a631790 100644 --- a/aleksis/core/mixins.py +++ b/aleksis/core/mixins.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import Any, Callable, Optional +from typing import Any, Callable, Optional, Union from django.contrib.contenttypes.models import ContentType from django.db import models @@ -223,7 +223,7 @@ class ExtensibleForm(ModelForm, metaclass=_ExtensibleFormMetaclass): """ @classmethod - def add_node_to_layout(cls, node: LayoutNode): + def add_node_to_layout(cls, node: Union[LayoutNode, str]): """ Add a node to `layout` attribute diff --git a/aleksis/core/models.py b/aleksis/core/models.py index 6c994a9fe983c8034630abc1bb8fb239f3c48379..b9b29ea5f7372e54a626081e3d79e516a9b863d8 100644 --- a/aleksis/core/models.py +++ b/aleksis/core/models.py @@ -2,6 +2,7 @@ from datetime import date, datetime from typing import Optional, Iterable, Union, Sequence, List from django.contrib.auth import get_user_model +from django.contrib.auth.models import Group as DjangoGroup from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType from django.db import models @@ -9,14 +10,14 @@ from django.db.models import QuerySet from django.forms.widgets import Media from django.urls import reverse from django.utils import timezone -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from image_cropping import ImageCropField, ImageRatioField from phonenumber_field.modelfields import PhoneNumberField from polymorphic.models import PolymorphicModel from .mixins import ExtensibleModel, PureDjangoModel +from .tasks import send_notification from .util.core_helpers import now_tomorrow -from .util.notifications import send_notification from .util.model_helpers import ICONS from constance import config @@ -136,6 +137,9 @@ class Person(ExtensibleModel): primary_group = models.ForeignKey("Group", models.SET_NULL, null=True, blank=True) + description = models.TextField(verbose_name=_("Description"), blank=True, null=True) + + def get_absolute_url(self) -> str: return reverse("person_by_id", args=[self.id]) @@ -172,6 +176,18 @@ class Person(ExtensibleModel): else: return f"{self.first_name} {self.last_name}" + @property + def age(self): + return self.age_at(timezone.datetime.now().date()) + + def age_at(self, today): + years = today.year - self.date_of_birth.year + if (self.date_of_birth.month > today.month + or (self.date_of_birth.month == today.month + and self.date_of_birth.day > today.day)): + years -= 1 + return years + def save(self, *args, **kwargs): super().save(*args, **kwargs) @@ -182,6 +198,10 @@ class Person(ExtensibleModel): self.user.email = self.email self.user.save() + # Save all related groups once to keep synchronisation with Django + for group in self.member_of.union(self.owner_of.all()).all(): + group.save() + self.auto_select_primary_group() def __str__(self) -> str: @@ -245,8 +265,12 @@ class Group(ExtensibleModel): blank=True, ) +<<<<<<< HEAD def get_absolute_url(self) -> str: return reverse("group_by_id", args=[self.id]) +======= + type = models.ForeignKey("GroupType", on_delete=models.CASCADE, related_name="type", verbose_name=_("Type of group"), null=True, blank=True) +>>>>>>> master @property def announcement_recipients(self): @@ -255,6 +279,20 @@ class Group(ExtensibleModel): def __str__(self) -> str: return "%s (%s)" % (self.name, self.short_name) + def save(self, *args, **kwargs): + super().save(*args, **kwargs) + + # Synchronise group to Django group with same name + dj_group, _ = DjangoGroup.objects.get_or_create(name=self.name) + dj_group.user_set.set( + list( + self.members.filter(user__isnull=False).values_list("user", flat=True).union( + self.owners.filter(user__isnull=False).values_list("user", flat=True) + ) + ) + ) + dj_group.save() + class Activity(ExtensibleModel): user = models.ForeignKey("Person", on_delete=models.CASCADE, related_name="activities") @@ -287,7 +325,8 @@ class Notification(ExtensibleModel): return str(self.title) def save(self, **kwargs): - send_notification(self) + if not self.sent: + send_notification(self.pk, resend=True) self.sent = True super().save(**kwargs) @@ -520,3 +559,11 @@ class CustomMenuItem(ExtensibleModel): class Meta: verbose_name = _("Custom menu item") verbose_name_plural = _("Custom menu items") + +class GroupType(ExtensibleModel): + name = models.CharField(verbose_name=_("Title of type"), max_length=50) + description = models.CharField(verbose_name=_("Description"), max_length=500) + + class Meta: + verbose_name = _("Group type") + verbose_name_plural = _("Group types") diff --git a/aleksis/core/settings.py b/aleksis/core/settings.py index 2db6002c03a413eac30b6180075c0b9ec3bc6151..eb4b3e07401fae2a830c530212747877ced2af93 100644 --- a/aleksis/core/settings.py +++ b/aleksis/core/settings.py @@ -56,6 +56,7 @@ INSTALLED_APPS = [ "haystack", "polymorphic", "django_global_request", + "dbbackup", "settings_context_processor", "sass_processor", "easyaudit", @@ -281,6 +282,7 @@ YARN_INSTALLED_APPS = [ "materialize-css", "material-design-icons-iconfont", "select2", + "select2-materialize", "paper-css", ] @@ -301,6 +303,7 @@ ANY_JS = { "css_url": JS_URL + "/material-design-icons-iconfont/dist/material-design-icons.css" }, "paper-css": {"css_url": JS_URL + "/paper-css/paper.min.css"}, + "select2-materialize": {"css_url": JS_URL + "/select2-materialize/select2-materialize.css", "js_url": JS_URL + "/select2-materialize/index.js"}, } merge_app_settings("ANY_JS", ANY_JS, True) @@ -406,6 +409,16 @@ MAINTENANCE_MODE_STATE_FILE_PATH = _settings.get( "maintenance.statefile", "maintenance_mode_state.txt" ) +DBBACKUP_STORAGE = _settings.get("backup.storage", "django.core.files.storage.FileSystemStorage") +DBBACKUP_STORAGE_OPTIONS = {"location": _settings.get("backup.location", "/var/backups/aleksis")} +DBBACKUP_CLEANUP_KEEP = _settings.get("backup.database.keep", 10) +DBBACKUP_CLEANUP_KEEP_MEDIA = _settings.get("backup.media.keep", 10) +DBBACKUP_GPG_RECIPIENT = _settings.get("backup.gpg_recipient", None) +DBBACKUP_COMPRESS_DB = _settings.get("backup.database.compress", True) +DBBACKUP_ENCRYPT_DB = _settings.get("backup.database.encrypt", DBBACKUP_GPG_RECIPIENT is not None) +DBBACKUP_COMPRESS_MEDIA = _settings.get("backup.media.compress", True) +DBBACKUP_ENCRYPT_MEDIA = _settings.get("backup.media.encrypt", DBBACKUP_GPG_RECIPIENT is not None) + IMPERSONATE = {"USE_HTTP_REFERER": True, "REQUIRE_SUPERUSER": True, "ALLOW_SUPERUSER": True} DJANGO_TABLES2_TEMPLATE = "django_tables2/materialize.html" @@ -437,7 +450,7 @@ if _settings.get("twilio.sid", None): if _settings.get("celery.enabled", False): INSTALLED_APPS += ("django_celery_beat", "django_celery_results") - CELERY_BROKER_URL = "redis://localhost" + CELERY_BROKER_URL = _settings.get("celery.broker", "redis://localhost") CELERY_RESULT_BACKEND = "django-db" CELERY_CACHE_BACKEND = "django-cache" CELERY_BEAT_SCHEDULER = "django_celery_beat.schedulers:DatabaseScheduler" diff --git a/aleksis/core/static/js/main.js b/aleksis/core/static/js/main.js index 275e3ae6e7765823308ba3f4bc91c2c462211b16..403837da22d351d8e97ed3cf6c27c79e30514497 100644 --- a/aleksis/core/static/js/main.js +++ b/aleksis/core/static/js/main.js @@ -68,4 +68,16 @@ $(document).ready( function () { // Initialise auto-completion for search bar window.autocomplete = new Autocomplete({}); window.autocomplete.setup(); + + // Initialize text collapsibles [MAT, own work] + $(".text-collapsible").addClass("closed").removeClass("opened"); + + $(".text-collapsible .open-icon").click(function (e) { + var el = $(e.target).parent(); + el.addClass("opened").removeClass("closed"); + }); + $(".text-collapsible .close-icon").click(function (e) { + var el = $(e.target).parent(); + el.addClass("closed").removeClass("opened"); + }); }); diff --git a/aleksis/core/static/style.scss b/aleksis/core/static/style.scss index a312014a4f7d0709a1ad4867a06ee1c016a8642a..a9f12fa7caddaea4c9650c5a95fa099c066a558a 100644 --- a/aleksis/core/static/style.scss +++ b/aleksis/core/static/style.scss @@ -462,6 +462,27 @@ main .alert p:first-child, main .alert div:first-child { margin-right: -10px; } +// Text collapsible + +.text-collapsible > .material-icons { + font-size: 20px; + line-height: 15px; + margin-bottom: 2px; + margin-left: -1px; + vertical-align: middle; + cursor: pointer; + color: #6d6d6d; +} + +.text-collapsible.opened .a, +.text-collapsible.opened > .material-icons.open-icon { + display: none; +} + +.text-collapsible.closed .b, +.text-collapsible.closed > .material-icons.close-icon { + display: none; +} // Helpers diff --git a/aleksis/core/tasks.py b/aleksis/core/tasks.py new file mode 100644 index 0000000000000000000000000000000000000000..2c4c40a8f218d95efa0c26c2e30a8388cce305dd --- /dev/null +++ b/aleksis/core/tasks.py @@ -0,0 +1,18 @@ +from django.core import management + +from .util.core_helpers import celery_optional +from .util.notifications import send_notification as _send_notification + + +@celery_optional +def send_notification(notification: int, resend: bool = False) -> None: + _send_notification(notification, resend) + + +@celery_optional +def backup_data() -> None: + db_options = "-z " * settings.DBBACKUP_COMPRESS_DB + "-e" * settings.DBBACKUP_ENCRYPT_DB + media_options = "-z " * settings.DBBACKUP_COMPRESS_MEDIA + "-e" * settings.DBBACKUP_ENCRYPT_MEDIA + + management.call_command("dbbackup", db_options) + management.call_command("mediabackup", media_options) diff --git a/aleksis/core/templates/components/text_collapsible.html b/aleksis/core/templates/components/text_collapsible.html new file mode 100644 index 0000000000000000000000000000000000000000..7096e8e9311d7fdcd5f6cffb6af0934fa9d56977 --- /dev/null +++ b/aleksis/core/templates/components/text_collapsible.html @@ -0,0 +1,13 @@ +<span class="text-collapsible opened"> + <span class="a"> + {% include template with item=qs.first %} – + {% include template with item=qs.last %} + </span> + <i class="material-icons open-icon" title="Show more">add_circle_outline</i> + <span class="b"> + {% for item in qs %} + {% include template with item=item %} + {% endfor %} + </span> + <i class="material-icons close-icon" title="Show less">remove_circle_outline</i> +</span> diff --git a/aleksis/core/util/core_helpers.py b/aleksis/core/util/core_helpers.py index 67e9fe71ba5d038b9da729430a3e37bc837bc4c2..9f91154c30913ae14eff1332b5f6bea3207bfa86 100644 --- a/aleksis/core/util/core_helpers.py +++ b/aleksis/core/util/core_helpers.py @@ -116,11 +116,12 @@ def celery_optional(orig: Callable) -> Callable: and it is executed synchronously. """ + if hasattr(settings, "CELERY_RESULT_BACKEND"): + from ..celery import app # noqa + task = app.task(orig) + def wrapped(*args, **kwargs): if hasattr(settings, "CELERY_RESULT_BACKEND"): - from ..celery import app # noqa - task = app.task(orig) - task.delay(*args, **kwargs) else: orig(*args, **kwargs) diff --git a/aleksis/core/util/notifications.py b/aleksis/core/util/notifications.py index 5f6f8fded9a00323b2695e27268d4d4a744c0525..7f309d1cc2e0a0a046334683f5e2100f28fdae2c 100644 --- a/aleksis/core/util/notifications.py +++ b/aleksis/core/util/notifications.py @@ -68,7 +68,6 @@ _CHANNELS_MAP = { } -@celery_optional def send_notification(notification: Union[int, "Notification"], resend: bool = False) -> None: """ Send a notification through enabled channels. diff --git a/aleksis/core/views.py b/aleksis/core/views.py index 850167f71e0e6ffc3ba8ce241a5bbfbfa3866707..d3ead324d90b313ffeec3a5068df24c90bc379f4 100644 --- a/aleksis/core/views.py +++ b/aleksis/core/views.py @@ -4,7 +4,7 @@ from django.contrib.auth.decorators import login_required from django.core.exceptions import PermissionDenied from django.http import Http404, HttpRequest, HttpResponse from django.shortcuts import get_object_or_404, redirect, render -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django_tables2 import RequestConfig from haystack.inputs import AutoQuery @@ -68,12 +68,15 @@ def persons(request: HttpRequest) -> HttpResponse: @login_required -def person(request: HttpRequest, id_: int) -> HttpResponse: +def person(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse: context = {} # Get person and check access try: - person = Person.objects.get(pk=id_) + if id_ is None: + person = request.user.person + else: + person = Person.objects.get(pk=id_) except Person.DoesNotExist as e: # Turn not-found object into a 404 error raise Http404 from e @@ -81,7 +84,7 @@ def person(request: HttpRequest, id_: int) -> HttpResponse: context["person"] = person # Get groups where person is member of - groups = Group.objects.filter(members=id_) + groups = Group.objects.filter(members=person) # Build table groups_table = GroupsTable(groups) diff --git a/apps/official/AlekSIS-App-Alsijil b/apps/official/AlekSIS-App-Alsijil index 30e3f7163be7591d4770fc9621c75ded2108ee79..a364de906be9f46b15c137d4f43fbad4f2fec047 160000 --- a/apps/official/AlekSIS-App-Alsijil +++ b/apps/official/AlekSIS-App-Alsijil @@ -1 +1 @@ -Subproject commit 30e3f7163be7591d4770fc9621c75ded2108ee79 +Subproject commit a364de906be9f46b15c137d4f43fbad4f2fec047 diff --git a/apps/official/AlekSIS-App-Chronos b/apps/official/AlekSIS-App-Chronos index f899554d32d7948786522d8f66565d97aaeb5021..6b05dfc0613ff143fa292aa67eb349c90439d7ee 160000 --- a/apps/official/AlekSIS-App-Chronos +++ b/apps/official/AlekSIS-App-Chronos @@ -1 +1 @@ -Subproject commit f899554d32d7948786522d8f66565d97aaeb5021 +Subproject commit 6b05dfc0613ff143fa292aa67eb349c90439d7ee diff --git a/apps/official/AlekSIS-App-DashboardFeeds b/apps/official/AlekSIS-App-DashboardFeeds index b4cf1e8e2bc5c4c1d40e3c7ccfd75c1a1723ef92..894dc89ac4fd4f6c33b51020288eabe9b6169256 160000 --- a/apps/official/AlekSIS-App-DashboardFeeds +++ b/apps/official/AlekSIS-App-DashboardFeeds @@ -1 +1 @@ -Subproject commit b4cf1e8e2bc5c4c1d40e3c7ccfd75c1a1723ef92 +Subproject commit 894dc89ac4fd4f6c33b51020288eabe9b6169256 diff --git a/apps/official/AlekSIS-App-Exlibris b/apps/official/AlekSIS-App-Exlibris index 8cac01059cfdd9f89e0e8f020e9cccaf575bf534..736a7ea53be4e0fa7de7bf3dd66cd47965e36bed 160000 --- a/apps/official/AlekSIS-App-Exlibris +++ b/apps/official/AlekSIS-App-Exlibris @@ -1 +1 @@ -Subproject commit 8cac01059cfdd9f89e0e8f020e9cccaf575bf534 +Subproject commit 736a7ea53be4e0fa7de7bf3dd66cd47965e36bed diff --git a/apps/official/AlekSIS-App-LDAP b/apps/official/AlekSIS-App-LDAP index 6a3d678f817b45a1e97515399ae3f1a2234b53a2..c0bc552d9a7e04560b54c261b5e8d690958d2968 160000 --- a/apps/official/AlekSIS-App-LDAP +++ b/apps/official/AlekSIS-App-LDAP @@ -1 +1 @@ -Subproject commit 6a3d678f817b45a1e97515399ae3f1a2234b53a2 +Subproject commit c0bc552d9a7e04560b54c261b5e8d690958d2968 diff --git a/docker-compose.yml b/docker-compose.yml index 32a73fe9576c80506bd3c826a6b7d73b7b9d37a0..56d9d1edb57546360eaf73a18d2a95097b950288 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,9 +22,41 @@ services: - ALEKSIS_caching__memcached__enabled=true - ALEKSIS_database__host=db - ALEKSIS_maintenance__debug=${ALEKSIS_maintenance__debug:-false} + - ALEKSIS_backup__location=/var/lib/aleksis/backups depends_on: - db - memcached + worker: + build: . + image: registry.edugit.org/aleksis/official/aleksis:${ALEKSIS_IMAGE_TAG:-latest} + volumes: + - aleksis_data:/var/lib/aleksis/ + - aleksis_static:/usr/share/aleksis/static/ + command: celery_worker + environment: + - ALEKSIS_http__allowed_hosts="['*']" + - ALEKSIS_caching__memcached__address=memcached:11211 + - ALEKSIS_caching__memcached__enabled=true + - ALEKSIS_database__host=db + - ALEKSIS_maintenance__debug=${ALEKSIS_maintenance__debug:-false} + - ALEKSIS_backup__location=/var/lib/aleksis/backups + depends_on: + - app + scheduler: + build: . + image: registry.edugit.org/aleksis/official/aleksis:${ALEKSIS_IMAGE_TAG:-latest} + volumes: + - aleksis_data:/var/lib/aleksis/ + - aleksis_static:/usr/share/aleksis/static/ + command: celery_beat + environment: + - ALEKSIS_http__allowed_hosts="['*']" + - ALEKSIS_caching__memcached__address=memcached:11211 + - ALEKSIS_caching__memcached__enabled=true + - ALEKSIS_database__host=db + - ALEKSIS_maintenance__debug=${ALEKSIS_maintenance__debug:-false} + depends_on: + - worker web: build: ./docker/nginx image: registry.edugit.org/aleksis/official/aleksis/nginx:${ALEKSIS_IMAGE_TAG:-latest} @@ -39,3 +71,4 @@ services: volumes: postgres_data: aleksis_data: + aleksis_static: diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index d66dbdd7707d66a32f005c0f62174aebd23847e7..8c9c64e55abb848ae6d67d42f99e5434f9916a94 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -21,8 +21,12 @@ python manage.py compilescss python manage.py collectstatic --no-input --clear python manage.py migrate -if [[ -n "$@" ]]; then - exec "$@" +ARG=${$1:-"gunicorn"} + +if [ $ARG = "celery_worker" ]; then + exec celery -A aleksis.core worker -l info +elif [ $ARG = "celery_beat" ]; then + exec celery -A aleksis.core beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler else exec gunicorn aleksis.core.wsgi --bind ${GUNICORN_BIND} fi diff --git a/poetry.lock b/poetry.lock index 280bdffed477915ed3d5edc5da7ba69b4e570800..591849c3413c4492ebc30c577f706574f7c8470a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -91,10 +91,10 @@ description = "Screen-scraping library" name = "beautifulsoup4" optional = false python-versions = "*" -version = "4.8.2" +version = "4.9.0" [package.dependencies] -soupsieve = ">=1.2" +soupsieve = [">1.2", "<2.0"] [package.extras] html5lib = ["html5lib"] @@ -213,7 +213,7 @@ description = "Python package for providing Mozilla's CA Bundle." name = "certifi" optional = false python-versions = "*" -version = "2019.11.28" +version = "2020.4.5.1" [[package]] category = "main" @@ -268,7 +268,7 @@ description = "Code coverage measurement for Python" name = "coverage" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" -version = "5.0.4" +version = "5.1" [package.extras] toml = ["toml"] @@ -295,7 +295,7 @@ description = "A high-level Python Web framework that encourages rapid developme name = "django" optional = false python-versions = ">=3.6" -version = "3.0.4" +version = "3.0.5" [package.dependencies] asgiref = ">=3.2,<4.0" @@ -323,11 +323,10 @@ description = "A helper class for handling configuration defaults of packaged ap name = "django-appconf" optional = false python-versions = "*" -version = "1.0.3" +version = "1.0.4" [package.dependencies] django = "*" -six = "*" [[package]] category = "main" @@ -419,7 +418,7 @@ description = "simple color field for your models with a nice color-picker in th name = "django-colorfield" optional = false python-versions = "*" -version = "0.2.1" +version = "0.2.2" [[package]] category = "main" @@ -456,7 +455,7 @@ description = "Yet another Django audit log app, hopefully the simplest one." name = "django-easy-audit" optional = false python-versions = "*" -version = "1.2.2b3" +version = "1.2.2b4" [package.dependencies] beautifulsoup4 = "*" @@ -503,8 +502,8 @@ category = "main" description = "A reusable app for cropping images easily and non-destructively in Django" name = "django-image-cropping" optional = false -python-versions = "*" -version = "1.3.0" +python-versions = ">=3.5" +version = "1.4.0" [package.dependencies] django-appconf = ">=1.0.2" @@ -734,7 +733,7 @@ description = "Table/data-grid framework for Django" name = "django-tables2" optional = false python-versions = "*" -version = "2.2.1" +version = "2.3.1" [package.dependencies] Django = ">=1.11" @@ -894,7 +893,7 @@ description = "Faker is a Python package that generates fake data for you." name = "faker" optional = false python-versions = ">=3.4" -version = "4.0.2" +version = "4.0.3" [package.dependencies] python-dateutil = ">=2.4" @@ -1054,7 +1053,7 @@ description = "Git Object Database" name = "gitdb" optional = false python-versions = ">=3.4" -version = "4.0.2" +version = "4.0.4" [package.dependencies] smmap = ">=3.0.1,<4" @@ -1065,7 +1064,7 @@ description = "Python Git Library" name = "gitpython" optional = false python-versions = ">=3.4" -version = "3.1.0" +version = "3.1.1" [package.dependencies] gitdb = ">=4.0.1,<5" @@ -1130,7 +1129,7 @@ description = "A very fast and expressive template engine." name = "jinja2" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.11.1" +version = "2.11.2" [package.dependencies] MarkupSafe = ">=0.23" @@ -1246,7 +1245,7 @@ description = "Utility library for gitignore style pattern matching of file path name = "pathspec" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.7.0" +version = "0.8.0" [[package]] category = "dev" @@ -1254,7 +1253,7 @@ description = "Python Build Reasonableness" name = "pbr" optional = false python-versions = "*" -version = "5.4.4" +version = "5.4.5" [[package]] category = "dev" @@ -1262,10 +1261,10 @@ description = "PostgreSQL interface library" name = "pg8000" optional = false python-versions = ">=3.5" -version = "1.14.1" +version = "1.15.1" [package.dependencies] -scramp = "1.1.0" +scramp = "1.1.1" [[package]] category = "main" @@ -1281,7 +1280,7 @@ description = "Python Imaging Library (Fork)" name = "pillow" optional = false python-versions = ">=3.5" -version = "7.0.0" +version = "7.1.1" [[package]] category = "dev" @@ -1320,7 +1319,7 @@ description = "psycopg2 - Python-PostgreSQL Database Adapter" name = "psycopg2" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" -version = "2.8.4" +version = "2.8.5" [[package]] category = "dev" @@ -1390,7 +1389,7 @@ description = "Python parsing module" name = "pyparsing" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -version = "2.4.6" +version = "2.4.7" [[package]] category = "dev" @@ -1595,7 +1594,7 @@ description = "Alternative regular expression module, to replace re." name = "regex" optional = false python-versions = "*" -version = "2020.2.20" +version = "2020.4.4" [[package]] category = "main" @@ -1647,7 +1646,7 @@ description = "An implementation of the SCRAM protocol." name = "scramp" optional = false python-versions = ">=3.5" -version = "1.1.0" +version = "1.1.1" [[package]] category = "dev" @@ -1674,7 +1673,7 @@ description = "A pure Python implementation of a sliding window memory map manag name = "smmap" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.0.1" +version = "3.0.2" [[package]] category = "dev" @@ -1689,8 +1688,8 @@ category = "main" description = "A modern CSS selector implementation for Beautiful Soup." name = "soupsieve" optional = false -python-versions = ">=3.5" -version = "2.0" +python-versions = "*" +version = "1.9.5" [[package]] category = "dev" @@ -1906,7 +1905,7 @@ description = "Fast, Extensible Progress Meter" name = "tqdm" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*" -version = "4.44.1" +version = "4.45.0" [package.extras] dev = ["py-make (>=0.1.0)", "twine", "argopt", "pydoc-markdown"] @@ -1925,7 +1924,7 @@ description = "Backported and Experimental Type Hints for Python 3.5+" name = "typing-extensions" optional = false python-versions = "*" -version = "3.7.4.1" +version = "3.7.4.2" [[package]] category = "main" @@ -1954,7 +1953,7 @@ description = "Virtual Python Environment builder" name = "virtualenv" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -version = "20.0.15" +version = "20.0.17" [package.dependencies] appdirs = ">=1.4.3,<2" @@ -1968,7 +1967,7 @@ version = ">=0.12,<2" [package.extras] docs = ["sphinx (>=2.0.0,<3)", "sphinx-argparse (>=0.2.5,<1)", "sphinx-rtd-theme (>=0.4.3,<1)", "towncrier (>=19.9.0rc1)", "proselint (>=0.10.2,<1)"] -testing = ["pytest (>=4.0.0,<6)", "coverage (>=4.5.1,<6)", "pytest-mock (>=2.0.0,<3)", "pytest-env (>=0.6.2,<1)", "pytest-timeout (>=1.3.4,<2)", "packaging (>=20.0)", "xonsh (>=0.9.13,<1)"] +testing = ["pytest (>=4.0.0,<6)", "coverage (>=4.5.1,<6)", "pytest-mock (>=2.0.0,<3)", "pytest-env (>=0.6.2,<1)", "pytest-timeout (>=1.3.4,<2)", "packaging (>=20.0)", "xonsh (>=0.9.16,<1)"] [[package]] category = "dev" @@ -2049,9 +2048,9 @@ bandit = [ {file = "bandit-1.6.2.tar.gz", hash = "sha256:41e75315853507aa145d62a78a2a6c5e3240fe14ee7c601459d0df9418196065"}, ] beautifulsoup4 = [ - {file = "beautifulsoup4-4.8.2-py2-none-any.whl", hash = "sha256:e1505eeed31b0f4ce2dbb3bc8eb256c04cc2b3b72af7d551a4ab6efd5cbe5dae"}, - {file = "beautifulsoup4-4.8.2-py3-none-any.whl", hash = "sha256:9fbb4d6e48ecd30bcacc5b63b94088192dcda178513b2ae3c394229f8911b887"}, - {file = "beautifulsoup4-4.8.2.tar.gz", hash = "sha256:05fd825eb01c290877657a56df4c6e4c311b3965bda790c613a3d6fb01a5462a"}, + {file = "beautifulsoup4-4.9.0-py2-none-any.whl", hash = "sha256:a4bbe77fd30670455c5296242967a123ec28c37e9702a8a81bd2f20a4baf0368"}, + {file = "beautifulsoup4-4.9.0-py3-none-any.whl", hash = "sha256:d4e96ac9b0c3a6d3f0caae2e4124e6055c5dcafde8e2f831ff194c104f0775a0"}, + {file = "beautifulsoup4-4.9.0.tar.gz", hash = "sha256:594ca51a10d2b3443cbac41214e12dbb2a1cd57e1a7344659849e2e20ba6a8d8"}, ] billiard = [ {file = "billiard-3.6.3.0-py3-none-any.whl", hash = "sha256:bff575450859a6e0fbc2f9877d9b715b0bbc07c3565bb7ed2280526a0cdf5ede"}, @@ -2074,8 +2073,8 @@ celery = [ {file = "celery-4.4.2.tar.gz", hash = "sha256:108a0bf9018a871620936c33a3ee9f6336a89f8ef0a0f567a9001f4aa361415f"}, ] certifi = [ - {file = "certifi-2019.11.28-py2.py3-none-any.whl", hash = "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3"}, - {file = "certifi-2019.11.28.tar.gz", hash = "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"}, + {file = "certifi-2020.4.5.1-py2.py3-none-any.whl", hash = "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304"}, + {file = "certifi-2020.4.5.1.tar.gz", hash = "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519"}, ] chardet = [ {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, @@ -2097,37 +2096,37 @@ configobj = [ {file = "configobj-5.0.6.tar.gz", hash = "sha256:a2f5650770e1c87fb335af19a9b7eb73fc05ccf22144eb68db7d00cd2bcb0902"}, ] coverage = [ - {file = "coverage-5.0.4-cp27-cp27m-macosx_10_12_x86_64.whl", hash = "sha256:8a620767b8209f3446197c0e29ba895d75a1e272a36af0786ec70fe7834e4307"}, - {file = "coverage-5.0.4-cp27-cp27m-macosx_10_13_intel.whl", hash = "sha256:73aa6e86034dad9f00f4bbf5a666a889d17d79db73bc5af04abd6c20a014d9c8"}, - {file = "coverage-5.0.4-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:408ce64078398b2ee2ec08199ea3fcf382828d2f8a19c5a5ba2946fe5ddc6c31"}, - {file = "coverage-5.0.4-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:cda33311cb9fb9323958a69499a667bd728a39a7aa4718d7622597a44c4f1441"}, - {file = "coverage-5.0.4-cp27-cp27m-win32.whl", hash = "sha256:5f587dfd83cb669933186661a351ad6fc7166273bc3e3a1531ec5c783d997aac"}, - {file = "coverage-5.0.4-cp27-cp27m-win_amd64.whl", hash = "sha256:9fad78c13e71546a76c2f8789623eec8e499f8d2d799f4b4547162ce0a4df435"}, - {file = "coverage-5.0.4-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:2e08c32cbede4a29e2a701822291ae2bc9b5220a971bba9d1e7615312efd3037"}, - {file = "coverage-5.0.4-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:922fb9ef2c67c3ab20e22948dcfd783397e4c043a5c5fa5ff5e9df5529074b0a"}, - {file = "coverage-5.0.4-cp35-cp35m-macosx_10_12_x86_64.whl", hash = "sha256:c3fc325ce4cbf902d05a80daa47b645d07e796a80682c1c5800d6ac5045193e5"}, - {file = "coverage-5.0.4-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:046a1a742e66d065d16fb564a26c2a15867f17695e7f3d358d7b1ad8a61bca30"}, - {file = "coverage-5.0.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6ad6ca45e9e92c05295f638e78cd42bfaaf8ee07878c9ed73e93190b26c125f7"}, - {file = "coverage-5.0.4-cp35-cp35m-win32.whl", hash = "sha256:eda55e6e9ea258f5e4add23bcf33dc53b2c319e70806e180aecbff8d90ea24de"}, - {file = "coverage-5.0.4-cp35-cp35m-win_amd64.whl", hash = "sha256:4a8a259bf990044351baf69d3b23e575699dd60b18460c71e81dc565f5819ac1"}, - {file = "coverage-5.0.4-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:f372cdbb240e09ee855735b9d85e7f50730dcfb6296b74b95a3e5dea0615c4c1"}, - {file = "coverage-5.0.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a37c6233b28e5bc340054cf6170e7090a4e85069513320275a4dc929144dccf0"}, - {file = "coverage-5.0.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:443be7602c790960b9514567917af538cac7807a7c0c0727c4d2bbd4014920fd"}, - {file = "coverage-5.0.4-cp36-cp36m-win32.whl", hash = "sha256:165a48268bfb5a77e2d9dbb80de7ea917332a79c7adb747bd005b3a07ff8caf0"}, - {file = "coverage-5.0.4-cp36-cp36m-win_amd64.whl", hash = "sha256:0a907199566269e1cfa304325cc3b45c72ae341fbb3253ddde19fa820ded7a8b"}, - {file = "coverage-5.0.4-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:513e6526e0082c59a984448f4104c9bf346c2da9961779ede1fc458e8e8a1f78"}, - {file = "coverage-5.0.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:3844c3dab800ca8536f75ae89f3cf566848a3eb2af4d9f7b1103b4f4f7a5dad6"}, - {file = "coverage-5.0.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:641e329e7f2c01531c45c687efcec8aeca2a78a4ff26d49184dce3d53fc35014"}, - {file = "coverage-5.0.4-cp37-cp37m-win32.whl", hash = "sha256:db1d4e38c9b15be1521722e946ee24f6db95b189d1447fa9ff18dd16ba89f732"}, - {file = "coverage-5.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:62061e87071497951155cbccee487980524d7abea647a1b2a6eb6b9647df9006"}, - {file = "coverage-5.0.4-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:65a7e00c00472cd0f59ae09d2fb8a8aaae7f4a0cf54b2b74f3138d9f9ceb9cb2"}, - {file = "coverage-5.0.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1f66cf263ec77af5b8fe14ef14c5e46e2eb4a795ac495ad7c03adc72ae43fafe"}, - {file = "coverage-5.0.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:85596aa5d9aac1bf39fe39d9fa1051b0f00823982a1de5766e35d495b4a36ca9"}, - {file = "coverage-5.0.4-cp38-cp38-win32.whl", hash = "sha256:86a0ea78fd851b313b2e712266f663e13b6bc78c2fb260b079e8b67d970474b1"}, - {file = "coverage-5.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:03f630aba2b9b0d69871c2e8d23a69b7fe94a1e2f5f10df5049c0df99db639a0"}, - {file = "coverage-5.0.4-cp39-cp39-win32.whl", hash = "sha256:7c9762f80a25d8d0e4ab3cb1af5d9dffbddb3ee5d21c43e3474c84bf5ff941f7"}, - {file = "coverage-5.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:4482f69e0701139d0f2c44f3c395d1d1d37abd81bfafbf9b6efbe2542679d892"}, - {file = "coverage-5.0.4.tar.gz", hash = "sha256:1b60a95fc995649464e0cd48cecc8288bac5f4198f21d04b8229dc4097d76823"}, + {file = "coverage-5.1-cp27-cp27m-macosx_10_12_x86_64.whl", hash = "sha256:0cb4be7e784dcdc050fc58ef05b71aa8e89b7e6636b99967fadbdba694cf2b65"}, + {file = "coverage-5.1-cp27-cp27m-macosx_10_13_intel.whl", hash = "sha256:c317eaf5ff46a34305b202e73404f55f7389ef834b8dbf4da09b9b9b37f76dd2"}, + {file = "coverage-5.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:b83835506dfc185a319031cf853fa4bb1b3974b1f913f5bb1a0f3d98bdcded04"}, + {file = "coverage-5.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5f2294dbf7875b991c381e3d5af2bcc3494d836affa52b809c91697449d0eda6"}, + {file = "coverage-5.1-cp27-cp27m-win32.whl", hash = "sha256:de807ae933cfb7f0c7d9d981a053772452217df2bf38e7e6267c9cbf9545a796"}, + {file = "coverage-5.1-cp27-cp27m-win_amd64.whl", hash = "sha256:bf9cb9a9fd8891e7efd2d44deb24b86d647394b9705b744ff6f8261e6f29a730"}, + {file = "coverage-5.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:acf3763ed01af8410fc36afea23707d4ea58ba7e86a8ee915dfb9ceff9ef69d0"}, + {file = "coverage-5.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:dec5202bfe6f672d4511086e125db035a52b00f1648d6407cc8e526912c0353a"}, + {file = "coverage-5.1-cp35-cp35m-macosx_10_12_x86_64.whl", hash = "sha256:7a5bdad4edec57b5fb8dae7d3ee58622d626fd3a0be0dfceda162a7035885ecf"}, + {file = "coverage-5.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:1601e480b9b99697a570cea7ef749e88123c04b92d84cedaa01e117436b4a0a9"}, + {file = "coverage-5.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:dbe8c6ae7534b5b024296464f387d57c13caa942f6d8e6e0346f27e509f0f768"}, + {file = "coverage-5.1-cp35-cp35m-win32.whl", hash = "sha256:a027ef0492ede1e03a8054e3c37b8def89a1e3c471482e9f046906ba4f2aafd2"}, + {file = "coverage-5.1-cp35-cp35m-win_amd64.whl", hash = "sha256:0e61d9803d5851849c24f78227939c701ced6704f337cad0a91e0972c51c1ee7"}, + {file = "coverage-5.1-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:2d27a3f742c98e5c6b461ee6ef7287400a1956c11421eb574d843d9ec1f772f0"}, + {file = "coverage-5.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:66460ab1599d3cf894bb6baee8c684788819b71a5dc1e8fa2ecc152e5d752019"}, + {file = "coverage-5.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5c542d1e62eece33c306d66fe0a5c4f7f7b3c08fecc46ead86d7916684b36d6c"}, + {file = "coverage-5.1-cp36-cp36m-win32.whl", hash = "sha256:2742c7515b9eb368718cd091bad1a1b44135cc72468c731302b3d641895b83d1"}, + {file = "coverage-5.1-cp36-cp36m-win_amd64.whl", hash = "sha256:dead2ddede4c7ba6cb3a721870f5141c97dc7d85a079edb4bd8d88c3ad5b20c7"}, + {file = "coverage-5.1-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:01333e1bd22c59713ba8a79f088b3955946e293114479bbfc2e37d522be03355"}, + {file = "coverage-5.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:e1ea316102ea1e1770724db01998d1603ed921c54a86a2efcb03428d5417e489"}, + {file = "coverage-5.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:adeb4c5b608574a3d647011af36f7586811a2c1197c861aedb548dd2453b41cd"}, + {file = "coverage-5.1-cp37-cp37m-win32.whl", hash = "sha256:782caea581a6e9ff75eccda79287daefd1d2631cc09d642b6ee2d6da21fc0a4e"}, + {file = "coverage-5.1-cp37-cp37m-win_amd64.whl", hash = "sha256:00f1d23f4336efc3b311ed0d807feb45098fc86dee1ca13b3d6768cdab187c8a"}, + {file = "coverage-5.1-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:402e1744733df483b93abbf209283898e9f0d67470707e3c7516d84f48524f55"}, + {file = "coverage-5.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:a3f3654d5734a3ece152636aad89f58afc9213c6520062db3978239db122f03c"}, + {file = "coverage-5.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6402bd2fdedabbdb63a316308142597534ea8e1895f4e7d8bf7476c5e8751fef"}, + {file = "coverage-5.1-cp38-cp38-win32.whl", hash = "sha256:8fa0cbc7ecad630e5b0f4f35b0f6ad419246b02bc750de7ac66db92667996d24"}, + {file = "coverage-5.1-cp38-cp38-win_amd64.whl", hash = "sha256:79a3cfd6346ce6c13145731d39db47b7a7b859c0272f02cdb89a3bdcbae233a0"}, + {file = "coverage-5.1-cp39-cp39-win32.whl", hash = "sha256:a82b92b04a23d3c8a581fc049228bafde988abacba397d57ce95fe95e0338ab4"}, + {file = "coverage-5.1-cp39-cp39-win_amd64.whl", hash = "sha256:bb28a7245de68bf29f6fb199545d072d1036a1917dca17a1e75bbb919e14ee8e"}, + {file = "coverage-5.1.tar.gz", hash = "sha256:f90bfc4ad18450c80b024036eaf91e4a246ae287701aaa88eaebebf150868052"}, ] distlib = [ {file = "distlib-0.3.0.zip", hash = "sha256:2e166e231a26b36d6dfe35a48c4464346620f8645ed0ace01ee31822b288de21"}, @@ -2137,15 +2136,15 @@ dj-database-url = [ {file = "dj_database_url-0.5.0-py2.py3-none-any.whl", hash = "sha256:851785365761ebe4994a921b433062309eb882fedd318e1b0fcecc607ed02da9"}, ] django = [ - {file = "Django-3.0.4-py3-none-any.whl", hash = "sha256:89e451bfbb815280b137e33e454ddd56481fdaa6334054e6e031041ee1eda360"}, - {file = "Django-3.0.4.tar.gz", hash = "sha256:50b781f6cbeb98f673aa76ed8e572a019a45e52bdd4ad09001072dfd91ab07c8"}, + {file = "Django-3.0.5-py3-none-any.whl", hash = "sha256:642d8eceab321ca743ae71e0f985ff8fdca59f07aab3a9fb362c617d23e33a76"}, + {file = "Django-3.0.5.tar.gz", hash = "sha256:d4666c2edefa38c5ede0ec1655424c56dc47ceb04b6d8d62a7eac09db89545c1"}, ] django-any-js = [ {file = "django-any-js-1.0.3.post0.tar.gz", hash = "sha256:1da88b44b861b0f54f6b8ea0eb4c7c4fa1a5772e9a4320532cd4e0871a4e23f7"}, ] django-appconf = [ - {file = "django-appconf-1.0.3.tar.gz", hash = "sha256:35f13ca4d567f132b960e2cd4c832c2d03cb6543452d34e29b7ba10371ba80e3"}, - {file = "django_appconf-1.0.3-py2.py3-none-any.whl", hash = "sha256:c98a7af40062e996b921f5962a1c4f3f0c979fa7885f7be4710cceb90ebe13a6"}, + {file = "django-appconf-1.0.4.tar.gz", hash = "sha256:be58deb54a43d77d2e1621fe59f787681376d3cd0b8bd8e4758ef6c3a6453380"}, + {file = "django_appconf-1.0.4-py2.py3-none-any.whl", hash = "sha256:1b1d0e1069c843ebe8ae5aa48ec52403b1440402b320c3e3a206a0907e97bb06"}, ] django-auth-ldap = [ {file = "django-auth-ldap-2.1.1.tar.gz", hash = "sha256:fabbbc35a5d28ce6a12e3f6309229d82bfe6a410391914938593e4b96ce42ec8"}, @@ -2176,8 +2175,8 @@ django-ckeditor = [ {file = "django_ckeditor-5.9.0-py2.py3-none-any.whl", hash = "sha256:71c3c7bb46b0cbfb9712ef64af0d2a406eab233f44ecd7c42c24bdfa39ae3bde"}, ] django-colorfield = [ - {file = "django-colorfield-0.2.1.tar.gz", hash = "sha256:2a20722384a1703ff9b91a395de6e2649a8786161f8baff4d21998ba839f9017"}, - {file = "django_colorfield-0.2.1-py2-none-any.whl", hash = "sha256:c22c9cdae8608432adcde09d6e9e05dd4c498207e1cda0ab8fba0ab3ceb85dcd"}, + {file = "django-colorfield-0.2.2.tar.gz", hash = "sha256:49cfce71365de88130e65ced8f2c5c4826b31e9ab0c5f0e721ff13a830b5be76"}, + {file = "django_colorfield-0.2.2-py2-none-any.whl", hash = "sha256:ecb8af68f35028e35f973ddb687c2dcae86d028c6da1b72580c0d3fae915d3b7"}, ] django-constance = [ {file = "django-constance-2.6.0.tar.gz", hash = "sha256:12d827f9d5552ee39884fb6fb356f231f32b1ab8958acc715e3d1a6ecf913653"}, @@ -2187,8 +2186,8 @@ django-debug-toolbar = [ {file = "django_debug_toolbar-2.2-py3-none-any.whl", hash = "sha256:ff94725e7aae74b133d0599b9bf89bd4eb8f5d2c964106e61d11750228c8774c"}, ] django-easy-audit = [ - {file = "django-easy-audit-1.2.2b3.tar.gz", hash = "sha256:ad2a40ee3eb60af344d4617714a9a6972e7f5eea734dc6f58cbde4451bd565db"}, - {file = "django_easy_audit-1.2.2b3-py3-none-any.whl", hash = "sha256:a0bbbd827ca0a56d9f67efeed348d41ac1123aa7b19c7344a0be3e0ba60fa81e"}, + {file = "django-easy-audit-1.2.2b4.tar.gz", hash = "sha256:eac94b76882c6ad3fdb76d15f4f4ea281dc61e0897e92a457e058b87ed21ff68"}, + {file = "django_easy_audit-1.2.2b4-py3-none-any.whl", hash = "sha256:49ef3beea7bf439b349daa66d5e3d7624a7c9005d3bfd51f54d15dd5dcfaa202"}, ] django-filter = [ {file = "django-filter-2.2.0.tar.gz", hash = "sha256:c3deb57f0dd7ff94d7dce52a047516822013e2b441bed472b722a317658cfd14"}, @@ -2203,7 +2202,8 @@ django-hattori = [ {file = "django_hattori-0.2.1-py2.py3-none-any.whl", hash = "sha256:e529ed7af8fc34a0169c797c477672b687a205a56f3f5206f90c260acb83b7ac"}, ] django-image-cropping = [ - {file = "django-image-cropping-1.3.0.tar.gz", hash = "sha256:5c102d87bc66de025517ad06e485c100f73313ebf725e7482a728944276f6463"}, + {file = "django-image-cropping-1.4.0.tar.gz", hash = "sha256:6cc4a6bd8901e69b710caceea29b942fdb202da26626313cd9271ae989a83a52"}, + {file = "django_image_cropping-1.4.0-py3-none-any.whl", hash = "sha256:fe6a139c6d5dfc480f2a1d4e7e3e928d5edaefc898e17be66bc5f73140762ad9"}, ] django-impersonate = [ {file = "django-impersonate-1.5.tar.gz", hash = "sha256:2c10bcb1c42fe6495d915f4cc4cfd7c5f8375ba39a06b0f062ce6f1e2ff76585"}, @@ -2277,8 +2277,8 @@ django-stubs = [ {file = "django_stubs-1.5.0-py3-none-any.whl", hash = "sha256:4a03df70e062f4133085efc461148d0934f36ccfd60a2b6d7bc35821f62008b6"}, ] django-tables2 = [ - {file = "django-tables2-2.2.1.tar.gz", hash = "sha256:0d9b17f5c030ba1b5fcaeb206d8397bf58f1fdfc6beaf56e7874841b8647aa94"}, - {file = "django_tables2-2.2.1-py2.py3-none-any.whl", hash = "sha256:6afa0496695e15b332e98537265d09fe01a55b28c75a85323d8e6b0dc2350280"}, + {file = "django-tables2-2.3.1.tar.gz", hash = "sha256:28da782f81f046c7d921246f43e7ba2df430cafe5a0e00a0f9dadef25a0e487d"}, + {file = "django_tables2-2.3.1-py2.py3-none-any.whl", hash = "sha256:7e425ad51e22caf5470351981f0fcd4fd35d4cf2d4c3b76fa1b7bf56251778d1"}, ] django-templated-email = [ {file = "django-templated-email-2.3.0.tar.gz", hash = "sha256:536c4e5ae099eabfb9aab36087d4d7799948c654e73da55a744213d086d5bb33"}, @@ -2318,8 +2318,8 @@ entrypoints = [ {file = "entrypoints-0.3.tar.gz", hash = "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"}, ] faker = [ - {file = "Faker-4.0.2-py3-none-any.whl", hash = "sha256:b89aa33837498498e15c709eb40c31386408a901a53c7a5e12a425737a767976"}, - {file = "Faker-4.0.2.tar.gz", hash = "sha256:2d3f866ef25e1a5af80e7b0ceeacc3c92dec5d0fdbad3e2cb6adf6e60b22188f"}, + {file = "Faker-4.0.3-py3-none-any.whl", hash = "sha256:53bf2c8a2de8af271466e7b9cc2f08ecf83c4c947981680eb61080779a0adace"}, + {file = "Faker-4.0.3.tar.gz", hash = "sha256:7292806948ed848f1bcea1e7b963bae6f398687d1da0ea096e156fea2787f454"}, ] filelock = [ {file = "filelock-3.0.12-py3-none-any.whl", hash = "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836"}, @@ -2366,12 +2366,12 @@ flake8-rst-docstrings = [ {file = "flake8-rst-docstrings-0.0.13.tar.gz", hash = "sha256:b1b619d81d879b874533973ac04ee5d823fdbe8c9f3701bfe802bb41813997b4"}, ] gitdb = [ - {file = "gitdb-4.0.2-py3-none-any.whl", hash = "sha256:284a6a4554f954d6e737cddcff946404393e030b76a282c6640df8efd6b3da5e"}, - {file = "gitdb-4.0.2.tar.gz", hash = "sha256:598e0096bb3175a0aab3a0b5aedaa18a9a25c6707e0eca0695ba1a0baf1b2150"}, + {file = "gitdb-4.0.4-py3-none-any.whl", hash = "sha256:ba1132c0912e8c917aa8aa990bee26315064c7b7f171ceaaac0afeb1dc656c6a"}, + {file = "gitdb-4.0.4.tar.gz", hash = "sha256:6f0ecd46f99bb4874e5678d628c3a198e2b4ef38daea2756a2bfd8df7dd5c1a5"}, ] gitpython = [ - {file = "GitPython-3.1.0-py3-none-any.whl", hash = "sha256:43da89427bdf18bf07f1164c6d415750693b4d50e28fc9b68de706245147b9dd"}, - {file = "GitPython-3.1.0.tar.gz", hash = "sha256:e426c3b587bd58c482f0b7fe6145ff4ac7ae6c82673fc656f489719abca6f4cb"}, + {file = "GitPython-3.1.1-py3-none-any.whl", hash = "sha256:71b8dad7409efbdae4930f2b0b646aaeccce292484ffa0bc74f1195582578b3d"}, + {file = "GitPython-3.1.1.tar.gz", hash = "sha256:6d4f10e2aaad1864bb0f17ec06a2c2831534140e5883c350d58b4e85189dab74"}, ] html2text = [ {file = "html2text-2020.1.16-py3-none-any.whl", hash = "sha256:c7c629882da0cf377d66f073329ccf34a12ed2adf0169b9285ae4e63ef54c82b"}, @@ -2394,8 +2394,8 @@ isort = [ {file = "isort-4.3.21.tar.gz", hash = "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1"}, ] jinja2 = [ - {file = "Jinja2-2.11.1-py2.py3-none-any.whl", hash = "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49"}, - {file = "Jinja2-2.11.1.tar.gz", hash = "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250"}, + {file = "Jinja2-2.11.2-py2.py3-none-any.whl", hash = "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"}, + {file = "Jinja2-2.11.2.tar.gz", hash = "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0"}, ] kombu = [ {file = "kombu-4.6.8-py2.py3-none-any.whl", hash = "sha256:598e7e749d6ab54f646b74b2d2df67755dee13894f73ab02a2a9feb8870c7cb2"}, @@ -2409,7 +2409,6 @@ libsass = [ {file = "libsass-0.19.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:81a013a4c2a614927fd1ef7a386eddabbba695cbb02defe8f31cf495106e974c"}, {file = "libsass-0.19.4-cp35-cp35m-win32.whl", hash = "sha256:fcb7ab4dc81889e5fc99cafbc2017bc76996f9992fc6b175f7a80edac61d71df"}, {file = "libsass-0.19.4-cp35-cp35m-win_amd64.whl", hash = "sha256:fc5f8336750f76f1bfae82f7e9e89ae71438d26fc4597e3ab4c05ca8fcd41d8a"}, - {file = "libsass-0.19.4-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:53f87116e7441827878bd79bbad8debac23e1930423f61ab8d837ec4a4c36e0c"}, {file = "libsass-0.19.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:9b59afa0d755089c4165516400a39a289b796b5612eeef5736ab7a1ebf96a67c"}, {file = "libsass-0.19.4-cp36-cp36m-win32.whl", hash = "sha256:c93df526eeef90b1ea4799c1d33b6cd5aea3e9f4633738fb95c1287c13e6b404"}, {file = "libsass-0.19.4-cp36-cp36m-win_amd64.whl", hash = "sha256:0fd8b4337b3b101c6e6afda9112cc0dc4bacb9133b59d75d65968c7317aa3272"}, @@ -2417,7 +2416,6 @@ libsass = [ {file = "libsass-0.19.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:338e9ae066bf1fde874e335324d5355c52d2081d978b4f74fc59536564b35b08"}, {file = "libsass-0.19.4-cp37-cp37m-win32.whl", hash = "sha256:e318f06f06847ff49b1f8d086ac9ebce1e63404f7ea329adab92f4f16ba0e00e"}, {file = "libsass-0.19.4-cp37-cp37m-win_amd64.whl", hash = "sha256:a7e685466448c9b1bf98243339793978f654a1151eb5c975f09b83c7a226f4c1"}, - {file = "libsass-0.19.4-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:0fb4399f7bbecab7b181f2c2d82c3a0ba2916bf9169714b96e425355a5b23b9f"}, {file = "libsass-0.19.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6a51393d75f6e3c812785b0fa0b7d67c54258c28011921f204643b55f7355ec0"}, {file = "libsass-0.19.4.tar.gz", hash = "sha256:8b5b6d1a7c4ea1d954e0982b04474cc076286493f6af2d0a13c2e950fbe0be95"}, ] @@ -2489,44 +2487,45 @@ packaging = [ {file = "packaging-20.3.tar.gz", hash = "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3"}, ] pathspec = [ - {file = "pathspec-0.7.0-py2.py3-none-any.whl", hash = "sha256:163b0632d4e31cef212976cf57b43d9fd6b0bac6e67c26015d611a647d5e7424"}, - {file = "pathspec-0.7.0.tar.gz", hash = "sha256:562aa70af2e0d434367d9790ad37aed893de47f1693e4201fd1d3dca15d19b96"}, + {file = "pathspec-0.8.0-py2.py3-none-any.whl", hash = "sha256:7d91249d21749788d07a2d0f94147accd8f845507400749ea19c1ec9054a12b0"}, + {file = "pathspec-0.8.0.tar.gz", hash = "sha256:da45173eb3a6f2a5a487efba21f050af2b41948be6ab52b6a1e3ff22bb8b7061"}, ] pbr = [ - {file = "pbr-5.4.4-py2.py3-none-any.whl", hash = "sha256:61aa52a0f18b71c5cc58232d2cf8f8d09cd67fcad60b742a60124cb8d6951488"}, - {file = "pbr-5.4.4.tar.gz", hash = "sha256:139d2625547dbfa5fb0b81daebb39601c478c21956dc57e2e07b74450a8c506b"}, + {file = "pbr-5.4.5-py2.py3-none-any.whl", hash = "sha256:579170e23f8e0c2f24b0de612f71f648eccb79fb1322c814ae6b3c07b5ba23e8"}, + {file = "pbr-5.4.5.tar.gz", hash = "sha256:07f558fece33b05caf857474a366dfcc00562bca13dd8b47b2b3e22d9f9bf55c"}, ] pg8000 = [ - {file = "pg8000-1.14.1-py3-none-any.whl", hash = "sha256:0665ddb8a3ac64d6cbce827763ef060a310f7f097df5efbc80ee87aa32217fdd"}, - {file = "pg8000-1.14.1.tar.gz", hash = "sha256:7e87f5ec51eab2bb1f2a75a687b681152d60ec26828c93c244f00d5d085da64a"}, + {file = "pg8000-1.15.1-py3-none-any.whl", hash = "sha256:1f17917c8e2580581f4f689ed5e6eefef4ba873e7a9550d04afcb07fd43be83d"}, + {file = "pg8000-1.15.1.tar.gz", hash = "sha256:01033498ffb27e780f6fb9ec877655ad97ceb26a50efdd77ca3b39ab2271f37c"}, ] phonenumbers = [ {file = "phonenumbers-8.12.1-py2.py3-none-any.whl", hash = "sha256:bebf881ef0e775b93062fbd107bf164b5baef877a7b8f702e93a9a5d24ae4065"}, {file = "phonenumbers-8.12.1.tar.gz", hash = "sha256:59ae9cb25fb03027c9f2bf5584098e699be7eca12c443838b83752956be15cda"}, ] pillow = [ - {file = "Pillow-7.0.0-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:5f3546ceb08089cedb9e8ff7e3f6a7042bb5b37c2a95d392fb027c3e53a2da00"}, - {file = "Pillow-7.0.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:9d2ba4ed13af381233e2d810ff3bab84ef9f18430a9b336ab69eaf3cd24299ff"}, - {file = "Pillow-7.0.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:ff3797f2f16bf9d17d53257612da84dd0758db33935777149b3334c01ff68865"}, - {file = "Pillow-7.0.0-cp35-cp35m-win32.whl", hash = "sha256:c18f70dc27cc5d236f10e7834236aff60aadc71346a5bc1f4f83a4b3abee6386"}, - {file = "Pillow-7.0.0-cp35-cp35m-win_amd64.whl", hash = "sha256:875358310ed7abd5320f21dd97351d62de4929b0426cdb1eaa904b64ac36b435"}, - {file = "Pillow-7.0.0-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:ab76e5580b0ed647a8d8d2d2daee170e8e9f8aad225ede314f684e297e3643c2"}, - {file = "Pillow-7.0.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a62ec5e13e227399be73303ff301f2865bf68657d15ea50b038d25fc41097317"}, - {file = "Pillow-7.0.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8ac6ce7ff3892e5deaab7abaec763538ffd011f74dc1801d93d3c5fc541feee2"}, - {file = "Pillow-7.0.0-cp36-cp36m-win32.whl", hash = "sha256:91b710e3353aea6fc758cdb7136d9bbdcb26b53cefe43e2cba953ac3ee1d3313"}, - {file = "Pillow-7.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:bf598d2e37cf8edb1a2f26ed3fb255191f5232badea4003c16301cb94ac5bdd0"}, - {file = "Pillow-7.0.0-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:5bfef0b1cdde9f33881c913af14e43db69815c7e8df429ceda4c70a5e529210f"}, - {file = "Pillow-7.0.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:dc058b7833184970d1248135b8b0ab702e6daa833be14035179f2acb78ff5636"}, - {file = "Pillow-7.0.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:c5ed816632204a2fc9486d784d8e0d0ae754347aba99c811458d69fcdfd2a2f9"}, - {file = "Pillow-7.0.0-cp37-cp37m-win32.whl", hash = "sha256:54ebae163e8412aff0b9df1e88adab65788f5f5b58e625dc5c7f51eaf14a6837"}, - {file = "Pillow-7.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:87269cc6ce1e3dee11f23fa515e4249ae678dbbe2704598a51cee76c52e19cda"}, - {file = "Pillow-7.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0a628977ac2e01ca96aaae247ec2bd38e729631ddf2221b4b715446fd45505be"}, - {file = "Pillow-7.0.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:62a889aeb0a79e50ecf5af272e9e3c164148f4bd9636cc6bcfa182a52c8b0533"}, - {file = "Pillow-7.0.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bf4003aa538af3f4205c5fac56eacaa67a6dd81e454ffd9e9f055fff9f1bc614"}, - {file = "Pillow-7.0.0-cp38-cp38-win32.whl", hash = "sha256:7406f5a9b2fd966e79e6abdaf700585a4522e98d6559ce37fc52e5c955fade0a"}, - {file = "Pillow-7.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:5f7ae9126d16194f114435ebb79cc536b5682002a4fa57fa7bb2cbcde65f2f4d"}, - {file = "Pillow-7.0.0-pp373-pypy36_pp73-win32.whl", hash = "sha256:8453f914f4e5a3d828281a6628cf517832abfa13ff50679a4848926dac7c0358"}, - {file = "Pillow-7.0.0.tar.gz", hash = "sha256:4d9ed9a64095e031435af120d3c910148067087541131e82b3e8db302f4c8946"}, + {file = "Pillow-7.1.1-cp35-cp35m-macosx_10_10_intel.whl", hash = "sha256:b7453750cf911785009423789d2e4e5393aae9cbb8b3f471dab854b85a26cb89"}, + {file = "Pillow-7.1.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4510c6b33277970b1af83c987277f9a08ec2b02cc20ac0f9234e4026136bb137"}, + {file = "Pillow-7.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b99b2607b6cd58396f363b448cbe71d3c35e28f03e442ab00806463439629c2c"}, + {file = "Pillow-7.1.1-cp35-cp35m-win32.whl", hash = "sha256:cd47793f7bc9285a88c2b5551d3f16a2ddd005789614a34c5f4a598c2a162383"}, + {file = "Pillow-7.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:04a10558320eba9137d6a78ca6fc8f4a5801f1b971152938851dc4629d903579"}, + {file = "Pillow-7.1.1-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:50a10b048f4dd81c092adad99fa5f7ba941edaf2f9590510109ac2a15e706695"}, + {file = "Pillow-7.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:721c04d3c77c38086f1f95d1cd8df87f2f9a505a780acf8575912b3206479da1"}, + {file = "Pillow-7.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:a5dc9f28c0239ec2742d4273bd85b2aa84655be2564db7ad1eb8f64b1efcdc4c"}, + {file = "Pillow-7.1.1-cp36-cp36m-win32.whl", hash = "sha256:d6bf085f6f9ec6a1724c187083b37b58a8048f86036d42d21802ed5d1fae4853"}, + {file = "Pillow-7.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:251e5618125ec12ac800265d7048f5857a8f8f1979db9ea3e11382e159d17f68"}, + {file = "Pillow-7.1.1-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:433bbc2469a2351bea53666d97bb1eb30f0d56461735be02ea6b27654569f80f"}, + {file = "Pillow-7.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:eb84e7e5b07ff3725ab05977ac56d5eeb0c510795aeb48e8b691491be3c5745b"}, + {file = "Pillow-7.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3713386d1e9e79cea1c5e6aaac042841d7eef838cc577a3ca153c8bedf570287"}, + {file = "Pillow-7.1.1-cp37-cp37m-win32.whl", hash = "sha256:291bad7097b06d648222b769bbfcd61e40d0abdfe10df686d20ede36eb8162b6"}, + {file = "Pillow-7.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:6c1924ed7dbc6ad0636907693bbbdd3fdae1d73072963e71f5644b864bb10b4d"}, + {file = "Pillow-7.1.1-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:670e58d3643971f4afd79191abd21623761c2ebe61db1c2cb4797d817c4ba1a7"}, + {file = "Pillow-7.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:8d5799243050c2833c2662b824dfb16aa98e408d2092805edea4300a408490e7"}, + {file = "Pillow-7.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:da737ab273f4d60ae552f82ad83f7cbd0e173ca30ca20b160f708c92742ee212"}, + {file = "Pillow-7.1.1-cp38-cp38-win32.whl", hash = "sha256:b2f3e8cc52ecd259b94ca880fea0d15f4ebc6da2cd3db515389bb878d800270f"}, + {file = "Pillow-7.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:2f0b52a08d175f10c8ea36685115681a484c55d24d0933f9fd911e4111c04144"}, + {file = "Pillow-7.1.1-pp373-pypy36_pp73-win32.whl", hash = "sha256:90cd441a1638ae176eab4d8b6b94ab4ec24b212ed4c3fbee2a6e74672481d4f8"}, + {file = "Pillow-7.1.1-py3.8-macosx-10.9-x86_64.egg", hash = "sha256:5eef904c82b5f8e4256e8d420c971357da2884c0b812ba4efa15a7ad2ec66247"}, + {file = "Pillow-7.1.1.tar.gz", hash = "sha256:0f89ddc77cf421b8cd34ae852309501458942bf370831b4a9b406156b599a14e"}, ] pipenv = [ {file = "pipenv-2018.11.26-py2-none-any.whl", hash = "sha256:7df8e33a2387de6f537836f48ac6fcd94eda6ed9ba3d5e3fd52e35b5bc7ff49e"}, @@ -2538,19 +2537,19 @@ pluggy = [ {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, ] psycopg2 = [ - {file = "psycopg2-2.8.4-cp27-cp27m-win32.whl", hash = "sha256:72772181d9bad1fa349792a1e7384dde56742c14af2b9986013eb94a240f005b"}, - {file = "psycopg2-2.8.4-cp27-cp27m-win_amd64.whl", hash = "sha256:893c11064b347b24ecdd277a094413e1954f8a4e8cdaf7ffbe7ca3db87c103f0"}, - {file = "psycopg2-2.8.4-cp34-cp34m-win32.whl", hash = "sha256:9ab75e0b2820880ae24b7136c4d230383e07db014456a476d096591172569c38"}, - {file = "psycopg2-2.8.4-cp34-cp34m-win_amd64.whl", hash = "sha256:b0845e3bdd4aa18dc2f9b6fb78fbd3d9d371ad167fd6d1b7ad01c0a6cdad4fc6"}, - {file = "psycopg2-2.8.4-cp35-cp35m-win32.whl", hash = "sha256:ef6df7e14698e79c59c7ee7cf94cd62e5b869db369ed4b1b8f7b729ea825712a"}, - {file = "psycopg2-2.8.4-cp35-cp35m-win_amd64.whl", hash = "sha256:965c4c93e33e6984d8031f74e51227bd755376a9df6993774fd5b6fb3288b1f4"}, - {file = "psycopg2-2.8.4-cp36-cp36m-win32.whl", hash = "sha256:ed686e5926929887e2c7ae0a700e32c6129abb798b4ad2b846e933de21508151"}, - {file = "psycopg2-2.8.4-cp36-cp36m-win_amd64.whl", hash = "sha256:dca2d7203f0dfce8ea4b3efd668f8ea65cd2b35112638e488a4c12594015f67b"}, - {file = "psycopg2-2.8.4-cp37-cp37m-win32.whl", hash = "sha256:8396be6e5ff844282d4d49b81631772f80dabae5658d432202faf101f5283b7c"}, - {file = "psycopg2-2.8.4-cp37-cp37m-win_amd64.whl", hash = "sha256:47fc642bf6f427805daf52d6e52619fe0637648fe27017062d898f3bf891419d"}, - {file = "psycopg2-2.8.4-cp38-cp38-win32.whl", hash = "sha256:4212ca404c4445dc5746c0d68db27d2cbfb87b523fe233dc84ecd24062e35677"}, - {file = "psycopg2-2.8.4-cp38-cp38-win_amd64.whl", hash = "sha256:92a07dfd4d7c325dd177548c4134052d4842222833576c8391aab6f74038fc3f"}, - {file = "psycopg2-2.8.4.tar.gz", hash = "sha256:f898e5cc0a662a9e12bde6f931263a1bbd350cfb18e1d5336a12927851825bb6"}, + {file = "psycopg2-2.8.5-cp27-cp27m-win32.whl", hash = "sha256:a0984ff49e176062fcdc8a5a2a670c9bb1704a2f69548bce8f8a7bad41c661bf"}, + {file = "psycopg2-2.8.5-cp27-cp27m-win_amd64.whl", hash = "sha256:acf56d564e443e3dea152efe972b1434058244298a94348fc518d6dd6a9fb0bb"}, + {file = "psycopg2-2.8.5-cp34-cp34m-win32.whl", hash = "sha256:440a3ea2c955e89321a138eb7582aa1d22fe286c7d65e26a2c5411af0a88ae72"}, + {file = "psycopg2-2.8.5-cp34-cp34m-win_amd64.whl", hash = "sha256:6b306dae53ec7f4f67a10942cf8ac85de930ea90e9903e2df4001f69b7833f7e"}, + {file = "psycopg2-2.8.5-cp35-cp35m-win32.whl", hash = "sha256:d3b29d717d39d3580efd760a9a46a7418408acebbb784717c90d708c9ed5f055"}, + {file = "psycopg2-2.8.5-cp35-cp35m-win_amd64.whl", hash = "sha256:6a471d4d2a6f14c97a882e8d3124869bc623f3df6177eefe02994ea41fd45b52"}, + {file = "psycopg2-2.8.5-cp36-cp36m-win32.whl", hash = "sha256:27c633f2d5db0fc27b51f1b08f410715b59fa3802987aec91aeb8f562724e95c"}, + {file = "psycopg2-2.8.5-cp36-cp36m-win_amd64.whl", hash = "sha256:2df2bf1b87305bd95eb3ac666ee1f00a9c83d10927b8144e8e39644218f4cf81"}, + {file = "psycopg2-2.8.5-cp37-cp37m-win32.whl", hash = "sha256:ac5b23d0199c012ad91ed1bbb971b7666da651c6371529b1be8cbe2a7bf3c3a9"}, + {file = "psycopg2-2.8.5-cp37-cp37m-win_amd64.whl", hash = "sha256:2c0afb40cfb4d53487ee2ebe128649028c9a78d2476d14a67781e45dc287f080"}, + {file = "psycopg2-2.8.5-cp38-cp38-win32.whl", hash = "sha256:2327bf42c1744a434ed8ed0bbaa9168cac7ee5a22a9001f6fc85c33b8a4a14b7"}, + {file = "psycopg2-2.8.5-cp38-cp38-win_amd64.whl", hash = "sha256:132efc7ee46a763e68a815f4d26223d9c679953cd190f1f218187cb60decf535"}, + {file = "psycopg2-2.8.5.tar.gz", hash = "sha256:f7d46240f7a1ae1dd95aab38bd74f7428d46531f69219954266d669da60c0818"}, ] py = [ {file = "py-1.8.1-py2.py3-none-any.whl", hash = "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0"}, @@ -2603,8 +2602,8 @@ pygments = [ {file = "Pygments-2.6.1.tar.gz", hash = "sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44"}, ] pyparsing = [ - {file = "pyparsing-2.4.6-py2.py3-none-any.whl", hash = "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec"}, - {file = "pyparsing-2.4.6.tar.gz", hash = "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f"}, + {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, + {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, ] pytest = [ {file = "pytest-5.4.1-py3-none-any.whl", hash = "sha256:0e5b30f5cb04e887b91b1ee519fa3d89049595f428c1db76e73bd7f17b09b172"}, @@ -2674,27 +2673,27 @@ redis = [ {file = "redis-3.4.1.tar.gz", hash = "sha256:0dcfb335921b88a850d461dc255ff4708294943322bd55de6cfd68972490ca1f"}, ] regex = [ - {file = "regex-2020.2.20-cp27-cp27m-win32.whl", hash = "sha256:99272d6b6a68c7ae4391908fc15f6b8c9a6c345a46b632d7fdb7ef6c883a2bbb"}, - {file = "regex-2020.2.20-cp27-cp27m-win_amd64.whl", hash = "sha256:974535648f31c2b712a6b2595969f8ab370834080e00ab24e5dbb9d19b8bfb74"}, - {file = "regex-2020.2.20-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5de40649d4f88a15c9489ed37f88f053c15400257eeb18425ac7ed0a4e119400"}, - {file = "regex-2020.2.20-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:82469a0c1330a4beb3d42568f82dffa32226ced006e0b063719468dcd40ffdf0"}, - {file = "regex-2020.2.20-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:d58a4fa7910102500722defbde6e2816b0372a4fcc85c7e239323767c74f5cbc"}, - {file = "regex-2020.2.20-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:f1ac2dc65105a53c1c2d72b1d3e98c2464a133b4067a51a3d2477b28449709a0"}, - {file = "regex-2020.2.20-cp36-cp36m-win32.whl", hash = "sha256:8c2b7fa4d72781577ac45ab658da44c7518e6d96e2a50d04ecb0fd8f28b21d69"}, - {file = "regex-2020.2.20-cp36-cp36m-win_amd64.whl", hash = "sha256:269f0c5ff23639316b29f31df199f401e4cb87529eafff0c76828071635d417b"}, - {file = "regex-2020.2.20-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:bed7986547ce54d230fd8721aba6fd19459cdc6d315497b98686d0416efaff4e"}, - {file = "regex-2020.2.20-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:046e83a8b160aff37e7034139a336b660b01dbfe58706f9d73f5cdc6b3460242"}, - {file = "regex-2020.2.20-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:b33ebcd0222c1d77e61dbcd04a9fd139359bded86803063d3d2d197b796c63ce"}, - {file = "regex-2020.2.20-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:bba52d72e16a554d1894a0cc74041da50eea99a8483e591a9edf1025a66843ab"}, - {file = "regex-2020.2.20-cp37-cp37m-win32.whl", hash = "sha256:01b2d70cbaed11f72e57c1cfbaca71b02e3b98f739ce33f5f26f71859ad90431"}, - {file = "regex-2020.2.20-cp37-cp37m-win_amd64.whl", hash = "sha256:113309e819634f499d0006f6200700c8209a2a8bf6bd1bdc863a4d9d6776a5d1"}, - {file = "regex-2020.2.20-cp38-cp38-manylinux1_i686.whl", hash = "sha256:25f4ce26b68425b80a233ce7b6218743c71cf7297dbe02feab1d711a2bf90045"}, - {file = "regex-2020.2.20-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9b64a4cc825ec4df262050c17e18f60252cdd94742b4ba1286bcfe481f1c0f26"}, - {file = "regex-2020.2.20-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:9ff16d994309b26a1cdf666a6309c1ef51ad4f72f99d3392bcd7b7139577a1f2"}, - {file = "regex-2020.2.20-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:c7f58a0e0e13fb44623b65b01052dae8e820ed9b8b654bb6296bc9c41f571b70"}, - {file = "regex-2020.2.20-cp38-cp38-win32.whl", hash = "sha256:200539b5124bc4721247a823a47d116a7a23e62cc6695744e3eb5454a8888e6d"}, - {file = "regex-2020.2.20-cp38-cp38-win_amd64.whl", hash = "sha256:7f78f963e62a61e294adb6ff5db901b629ef78cb2a1cfce3cf4eeba80c1c67aa"}, - {file = "regex-2020.2.20.tar.gz", hash = "sha256:9e9624440d754733eddbcd4614378c18713d2d9d0dc647cf9c72f64e39671be5"}, + {file = "regex-2020.4.4-cp27-cp27m-win32.whl", hash = "sha256:90742c6ff121a9c5b261b9b215cb476eea97df98ea82037ec8ac95d1be7a034f"}, + {file = "regex-2020.4.4-cp27-cp27m-win_amd64.whl", hash = "sha256:24f4f4062eb16c5bbfff6a22312e8eab92c2c99c51a02e39b4eae54ce8255cd1"}, + {file = "regex-2020.4.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:08119f707f0ebf2da60d2f24c2f39ca616277bb67ef6c92b72cbf90cbe3a556b"}, + {file = "regex-2020.4.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c9423a150d3a4fc0f3f2aae897a59919acd293f4cb397429b120a5fcd96ea3db"}, + {file = "regex-2020.4.4-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:c087bff162158536387c53647411db09b6ee3f9603c334c90943e97b1052a156"}, + {file = "regex-2020.4.4-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:1cbe0fa0b7f673400eb29e9ef41d4f53638f65f9a2143854de6b1ce2899185c3"}, + {file = "regex-2020.4.4-cp36-cp36m-win32.whl", hash = "sha256:0ce9537396d8f556bcfc317c65b6a0705320701e5ce511f05fc04421ba05b8a8"}, + {file = "regex-2020.4.4-cp36-cp36m-win_amd64.whl", hash = "sha256:7e1037073b1b7053ee74c3c6c0ada80f3501ec29d5f46e42669378eae6d4405a"}, + {file = "regex-2020.4.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4385f12aa289d79419fede43f979e372f527892ac44a541b5446617e4406c468"}, + {file = "regex-2020.4.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a58dd45cb865be0ce1d5ecc4cfc85cd8c6867bea66733623e54bd95131f473b6"}, + {file = "regex-2020.4.4-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:ccccdd84912875e34c5ad2d06e1989d890d43af6c2242c6fcfa51556997af6cd"}, + {file = "regex-2020.4.4-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:ea4adf02d23b437684cd388d557bf76e3afa72f7fed5bbc013482cc00c816948"}, + {file = "regex-2020.4.4-cp37-cp37m-win32.whl", hash = "sha256:2294f8b70e058a2553cd009df003a20802ef75b3c629506be20687df0908177e"}, + {file = "regex-2020.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:e91ba11da11cf770f389e47c3f5c30473e6d85e06d7fd9dcba0017d2867aab4a"}, + {file = "regex-2020.4.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5635cd1ed0a12b4c42cce18a8d2fb53ff13ff537f09de5fd791e97de27b6400e"}, + {file = "regex-2020.4.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:23069d9c07e115537f37270d1d5faea3e0bdded8279081c4d4d607a2ad393683"}, + {file = "regex-2020.4.4-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:c162a21e0da33eb3d31a3ac17a51db5e634fc347f650d271f0305d96601dc15b"}, + {file = "regex-2020.4.4-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:fb95debbd1a824b2c4376932f2216cc186912e389bdb0e27147778cf6acb3f89"}, + {file = "regex-2020.4.4-cp38-cp38-win32.whl", hash = "sha256:2a3bf8b48f8e37c3a40bb3f854bf0121c194e69a650b209628d951190b862de3"}, + {file = "regex-2020.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:5bfed051dbff32fd8945eccca70f5e22b55e4148d2a8a45141a3b053d6455ae3"}, + {file = "regex-2020.4.4.tar.gz", hash = "sha256:295badf61a51add2d428a46b8580309c520d8b26e769868b922750cf3ce67142"}, ] requests = [ {file = "requests-2.23.0-py2.py3-none-any.whl", hash = "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee"}, @@ -2708,8 +2707,8 @@ safety = [ {file = "safety-1.8.7.tar.gz", hash = "sha256:3016631e0dd17193d6cf12e8ed1af92df399585e8ee0e4b1300d9e7e32b54903"}, ] scramp = [ - {file = "scramp-1.1.0-py3-none-any.whl", hash = "sha256:e09d2a9be5adeb94cbeb56fc54a61fc5f5b6e140e679b2b60d1f7a8d6478d906"}, - {file = "scramp-1.1.0.tar.gz", hash = "sha256:475aa6296deb2737b86e9df9098e8eca0f30c8ad1cc0a8adadb99ef012a5ceba"}, + {file = "scramp-1.1.1-py3-none-any.whl", hash = "sha256:a2c740624642de84f77327da8f56b2f030c5afd10deccaedbb8eb6108a66dfc1"}, + {file = "scramp-1.1.1.tar.gz", hash = "sha256:b57eb0ae2f9240b15b5d0dab2ea8e40b43eef13ac66d3f627a79ef85a6da0927"}, ] selenium = [ {file = "selenium-3.141.0-py2.py3-none-any.whl", hash = "sha256:2d7131d7bc5a5b99a2d9b04aaf2612c411b03b8ca1b1ee8d3de5845a9be2cb3c"}, @@ -2720,16 +2719,16 @@ six = [ {file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"}, ] smmap = [ - {file = "smmap-3.0.1-py2.py3-none-any.whl", hash = "sha256:5fead614cf2de17ee0707a8c6a5f2aa5a2fc6c698c70993ba42f515485ffda78"}, - {file = "smmap-3.0.1.tar.gz", hash = "sha256:171484fe62793e3626c8b05dd752eb2ca01854b0c55a1efc0dc4210fccb65446"}, + {file = "smmap-3.0.2-py2.py3-none-any.whl", hash = "sha256:52ea78b3e708d2c2b0cfe93b6fc3fbeec53db913345c26be6ed84c11ed8bebc1"}, + {file = "smmap-3.0.2.tar.gz", hash = "sha256:b46d3fc69ba5f367df96d91f8271e8ad667a198d5a28e215a6c3d9acd133a911"}, ] snowballstemmer = [ {file = "snowballstemmer-2.0.0-py2.py3-none-any.whl", hash = "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0"}, {file = "snowballstemmer-2.0.0.tar.gz", hash = "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"}, ] soupsieve = [ - {file = "soupsieve-2.0-py2.py3-none-any.whl", hash = "sha256:fcd71e08c0aee99aca1b73f45478549ee7e7fc006d51b37bec9e9def7dc22b69"}, - {file = "soupsieve-2.0.tar.gz", hash = "sha256:e914534802d7ffd233242b785229d5ba0766a7f487385e3f714446a07bf540ae"}, + {file = "soupsieve-1.9.5-py2.py3-none-any.whl", hash = "sha256:bdb0d917b03a1369ce964056fc195cfdff8819c40de04695a80bc813c3cfa1f5"}, + {file = "soupsieve-1.9.5.tar.gz", hash = "sha256:e2c1c5dee4a1c36bcb790e0fabd5492d874b8ebd4617622c4f6a731701060dda"}, ] sphinx = [ {file = "Sphinx-2.4.4-py3-none-any.whl", hash = "sha256:fc312670b56cb54920d6cc2ced455a22a547910de10b3142276495ced49231cb"}, @@ -2800,8 +2799,8 @@ toml = [ {file = "toml-0.10.0.tar.gz", hash = "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c"}, ] tqdm = [ - {file = "tqdm-4.44.1-py2.py3-none-any.whl", hash = "sha256:be5ddeec77d78ba781ea41eacb2358a77f74cc2407f54b82222d7ee7dc8c8ccf"}, - {file = "tqdm-4.44.1.tar.gz", hash = "sha256:03d2366c64d44c7f61e74c700d9b202d57e9efe355ea5c28814c52bfe7a50b8c"}, + {file = "tqdm-4.45.0-py2.py3-none-any.whl", hash = "sha256:ea9e3fd6bd9a37e8783d75bfc4c1faf3c6813da6bd1c3e776488b41ec683af94"}, + {file = "tqdm-4.45.0.tar.gz", hash = "sha256:00339634a22c10a7a22476ee946bbde2dbe48d042ded784e4d88e0236eca5d81"}, ] typed-ast = [ {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3"}, @@ -2827,9 +2826,9 @@ typed-ast = [ {file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"}, ] typing-extensions = [ - {file = "typing_extensions-3.7.4.1-py2-none-any.whl", hash = "sha256:910f4656f54de5993ad9304959ce9bb903f90aadc7c67a0bef07e678014e892d"}, - {file = "typing_extensions-3.7.4.1-py3-none-any.whl", hash = "sha256:cf8b63fedea4d89bab840ecbb93e75578af28f76f66c35889bd7065f5af88575"}, - {file = "typing_extensions-3.7.4.1.tar.gz", hash = "sha256:091ecc894d5e908ac75209f10d5b4f118fbdb2eb1ede6a63544054bb1edb41f2"}, + {file = "typing_extensions-3.7.4.2-py2-none-any.whl", hash = "sha256:f8d2bd89d25bc39dabe7d23df520442fa1d8969b82544370e03d88b5a591c392"}, + {file = "typing_extensions-3.7.4.2-py3-none-any.whl", hash = "sha256:6e95524d8a547a91e08f404ae485bbb71962de46967e1b71a0cb89af24e761c5"}, + {file = "typing_extensions-3.7.4.2.tar.gz", hash = "sha256:79ee589a3caca649a9bfd2a8de4709837400dfa00b6cc81962a1e6a1815969ae"}, ] urllib3 = [ {file = "urllib3-1.25.8-py2.py3-none-any.whl", hash = "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc"}, @@ -2840,8 +2839,8 @@ vine = [ {file = "vine-1.3.0.tar.gz", hash = "sha256:133ee6d7a9016f177ddeaf191c1f58421a1dcc6ee9a42c58b34bed40e1d2cd87"}, ] virtualenv = [ - {file = "virtualenv-20.0.15-py2.py3-none-any.whl", hash = "sha256:4e399f48c6b71228bf79f5febd27e3bbb753d9d5905776a86667bc61ab628a25"}, - {file = "virtualenv-20.0.15.tar.gz", hash = "sha256:9e81279f4a9d16d1c0654a127c2c86e5bca2073585341691882c1e66e31ef8a5"}, + {file = "virtualenv-20.0.17-py2.py3-none-any.whl", hash = "sha256:00cfe8605fb97f5a59d52baab78e6070e72c12ca64f51151695407cc0eb8a431"}, + {file = "virtualenv-20.0.17.tar.gz", hash = "sha256:c8364ec469084046c779c9a11ae6340094e8a0bf1d844330fc55c1cefe67c172"}, ] virtualenv-clone = [ {file = "virtualenv-clone-0.5.4.tar.gz", hash = "sha256:665e48dd54c84b98b71a657acb49104c54e7652bce9c1c4f6c6976ed4c827a29"}, diff --git a/pyproject.toml b/pyproject.toml index 816630c7f32205e8d4edc4e39a1244e3e142c17b..02448d52ad00c58009c4ba7cb4244f2a3c7da808 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,6 +70,7 @@ django-bleach = "^0.6.1" django-memoize = "^2.2.1" django-haystack = "^3.0" celery-haystack = {version="^0.3.1", optional=true} +django-dbbackup = "^3.3.0" [tool.poetry.extras] ldap = ["django-auth-ldap"]