diff --git a/.gitignore b/.gitignore index 767581f76153ad5ac9f16422ee895a14b7a67f32..0faf3e4c3ecc7ff5de08a7c56ee313c488b183f6 100644 --- a/.gitignore +++ b/.gitignore @@ -65,6 +65,7 @@ docs/_build/ aleksis/node_modules/ aleksis/static/ aleksis/whoosh_index/ +poetry.lock .coverage .mypy_cache/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index af5d314dbcc470d8e5aa3791d3ebe3957f26996c..a4349087629ec1c1a04444327e503b6b775cbc4b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,8 @@ include: - project: "AlekSIS/official/AlekSIS" file: /ci/general.yml + - project: "AlekSIS/official/AlekSIS" + file: /ci/prepare/lock.yml - project: "AlekSIS/official/AlekSIS" file: /ci/test/test.yml - project: "AlekSIS/official/AlekSIS" diff --git a/.mailmap b/.mailmap index f813351a7160f9a16f64e1e26868a139ce60ae56..c41b8aad5213d38c135d502ffc643f79a036bcf6 100644 --- a/.mailmap +++ b/.mailmap @@ -8,7 +8,9 @@ Jonathan Weth <git@jonathanweth.de> Jonathan Weth <joniweth@gmx.de> Jonathan Weth <git@jonathanweth.de> Jonathan Weth <mail@jonathanweth.de> Jonathan Weth <git@jonathanweth.de> Jonathan Weth <wethjo@katharineum.de> Julian Leucker <leuckerj@gmail.com> Julian <leuckerj@gmail.com> +Lloyd Meins <git@lloydmeins.de> Aithus <lloydmeins@gmx.net> Silas Della Contrada <s.developer@4-dc.de> sdcieo0330 <silasdc0@gmail.com> +Tom Teichler <tom.teichler@teckids.org> Tom Teichler <t.teichler@babiel.com> mirabilos <thorsten.glaser@teckids.org> mirabilos <mirabilos@evolvis.org> mirabilos <thorsten.glaser@teckids.org> mirabilos <t.glaser@tarent.de> root (Skolelinux) <root@tjener.intern> root <root@tjener.intern> diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5cd079bca115d28e7caccf0566ead90ac2b66fca..e79c84b72de33640303c9b1f01044e5d3521c9b7 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -12,14 +12,132 @@ Unreleased Added ~~~~~ +* Add preference for configuring the default phone number country code. + +Added +~~~~~ + +* OpenID Connect RSA keys can now be passed as string in config files +* Views filtering for person names now also search the username of a linked user +* OAuth2 applications now take an icon which is shown in the authorization progress. +* Add support for hiding the main side nav in ``base.html``. + +Fixed +~~~~~ + +* GroupManager.get_queryset() returned an incomplete QuerySet +* OAuth was broken by a non-semver-adhering django-oauth-toolkit update +* Too long texts in chips didn't result in a larger chip. +* The ``Person`` model had an ``is_active`` flag that was used in unclear ways; it is now removed +* The data check results list view didn't work if a related object had been deleted in the meanwhile. +* Socialaccount login template was not overriden + +Changed +~~~~~~~ + +* Configuration files are now deep merged by default +* Improvements for shell_plus module loading + + * core.Group model now takes precedence over auth.Group + * Name collisions are resolved by prefixing with the app label + * Apps can extend SHELL_PLUS_APP_PREFIXES and SHELL_PLUS_DONT_LOAD + +* [Docker] Base image now contains curl, grep, less, sed, and pspg +* Views raising a 404 error can now customise the message that is displayed on the error page +* OpenID Connect is enabled by default now, without RSA support +* Login and authorization pages for OAuth2/OpenID Connect now indicate that the user is in progress + to authorize an external application. + +`2.5`_ – 2022-01-02 +------------------- + +Added +~~~~~ + +* Recursive helper methods for group hierarchies + +Fixed +~~~~~ + +* Remove left-over reference to preferences in a form definition that caused + form extensions in downstream apps to break +* Allow non-LDAP users to authenticate if LDAP is used with password handling +* Additional button on progress page for background tasks was shown even if the task failed. +* Register preference for available allowed oauth grants. + +`2.4`_ – 2021-12-24 +------------------- + +Added +~~~~~ + +* Allow configuration of database options +* User invitations with invite codes and targeted invites for existing + persons + +Fixed +~~~~~ + +* Correctly update theme colours on change again +* Use correct favicon as default AlekSIS favicon +* Show all years in a 200 year range around the current year in date pickers +* Imprint is now called "Imprint" and not "Impress". +* Logo files weren't uploaded to public namespace. +* Limit LDAP network timeouts to not hang indefinitely on login if LDAP + server is unreachable + +Changed +~~~~~~~ + +* Modified the appearance of tables for mobile users to be more user friendly +* [Dev] Remove lock file; locking dependencies is the distribution's + responsibility + +Removed +~~~~~~~ + +* Remove old generated AlekSIS icons + +`2.3.1`_ – 2021-12-17 +--------------------- + +Fixed +~~~~~ + +* Small files could fail to upload to S3 storage due to MemoryFileUploadHandler +* Corrected typos in previous changelog + +`2.3`_ – 2021-12-15 +------------------- + +Added +~~~~~ + * [OAuth] Allow apps to fill in their own claim data matching their scopes Fixed ~~~~~ * View for assigning permissions didn't work with some global permissions. +* PDFs generated in background didn't contain logo or site title. +* Admins were redirected to their user preferences + while they wanted to edit the preferences of another user. +* Some CharFields were using NULL values in database when field is empty +* Optional dependecy `sentry-sdk` was not optional + +Changed +~~~~~~~ + +* Docker base image ships PostgreSQL 14 client binaries for maximum compatibility +* Docker base image contains Sentry client by default (disabled in config by default) + +Removed +~~~~~~~ + +* Remove impersonation page. Use the impersonation button on the person + detail view instead. -`2.2.1_ – 2021-12-02 +`2.2.1`_ – 2021-12-02 -------------------- Fixed @@ -514,3 +632,7 @@ Fixed .. _2.1.1: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.1.1 .. _2.2: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.2 .. _2.2.1: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.2.1 +.. _2.3: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.3 +.. _2.3.1: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.3.1 +.. _2.4: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.4 +.. _2.5: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.5 diff --git a/Dockerfile b/Dockerfile index a44a0ce8021f06d34e39c7d6c594602cb623f690..acb08f98ffe79dccc32f048590bb123c2763302f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM debian:bullseye-slim AS core # Build arguments -ARG EXTRAS="ldap,s3" +ARG EXTRAS="ldap,s3,sentry" ARG APP_VERSION="" # Configure Python to be nice inside Docker and pip to stfu @@ -19,20 +19,25 @@ ENV ALEKSIS_static__root /usr/share/aleksis/static ENV ALEKSIS_media__root /var/lib/aleksis/media ENV ALEKSIS_backup__location /var/lib/aleksis/backups ENV ALEKSIS_dev__uwsgi__celery false +ENV PSQL_PAGER=pspg # Install necessary Debian and PyPI packages for build and runtime RUN apt-get -y update && \ - apt-get -y install eatmydata && \ + apt-get -y install eatmydata gnupg postgresql-common && \ + /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y && \ eatmydata apt-get -y upgrade && \ eatmydata apt-get install -y --no-install-recommends \ build-essential \ chromium \ + curl \ dumb-init \ gettext \ - libpq5 \ + grep \ + less \ libpq-dev \ libssl-dev \ - postgresql-client \ + postgresql-client-14 \ + pspg \ python3-dev \ python3-magic \ python3-pip \ @@ -76,6 +81,7 @@ RUN set -e; \ eatmydata apt-get remove --purge -y \ build-essential \ gettext \ + gnupg \ libpq-dev \ libssl-dev \ libldap2-dev \ diff --git a/README.rst b/README.rst index 20780a642a74b8560bc21d1137193e78f7681642..2ffdcdca8d82845a1d3cdf838d10ca1290118e1e 100644 --- a/README.rst +++ b/README.rst @@ -6,7 +6,7 @@ This is the core of the AlekSIS framework and the official distribution developers and administrators. If you are looking for the AlekSIS standard distribution, i.e. the complete -software product ready for installation and usage, please visit the `AlekSIS`_ +software product ready for installation and usage, please visit the `AlekSIS®`_ website or the distribution repository on `EduGit`_. Features @@ -83,7 +83,7 @@ AlekSIS® is a registered trademark of the AlekSIS open source project, represen by Teckids e.V. Please refer to the `trademark policy`_ for hints on using the trademark AlekSIS®. -.. _AlekSIS: https://aleksis.org +.. _AlekSIS®: https://aleksis.org .. _European Union Public Licence: https://eupl.eu/ .. _EduGit: https://edugit.org/AlekSIS/official/AlekSIS .. _trademark policy: https://aleksis.org/pages/about diff --git a/aleksis/core/filters.py b/aleksis/core/filters.py index eb5724b322232381017aa0b84e4ab111a9304eda..0bccc2664489f3698fc77bbe7299a9210ed81dac 100644 --- a/aleksis/core/filters.py +++ b/aleksis/core/filters.py @@ -54,6 +54,7 @@ class PersonFilter(FilterSet): "additional_name__icontains", "last_name__icontains", "short_name__icontains", + "user__username__icontains", ], label=_("Search by name"), ) @@ -72,11 +73,11 @@ class PersonFilter(FilterSet): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.form.layout = Layout(Row("name", "contact"), Row("is_active", "sex", "primary_group")) + self.form.layout = Layout(Row("name", "contact"), Row("sex", "primary_group")) class Meta: model = Person - fields = ["sex", "is_active", "primary_group"] + fields = ["sex", "primary_group"] class PermissionFilter(FilterSet): diff --git a/aleksis/core/forms.py b/aleksis/core/forms.py index 7d32fd45b29dc4338fbdc1aa4e971e3015695715..459d4d8bb067f5915a41677ff3f941caa1de154d 100644 --- a/aleksis/core/forms.py +++ b/aleksis/core/forms.py @@ -6,7 +6,7 @@ from django.conf import settings from django.contrib.auth import get_user_model from django.contrib.auth.models import Permission from django.contrib.sites.models import Site -from django.core.exceptions import ValidationError +from django.core.exceptions import SuspiciousOperation, ValidationError from django.db.models import QuerySet from django.http import HttpRequest from django.utils.translation import gettext_lazy as _ @@ -14,6 +14,7 @@ from django.utils.translation import gettext_lazy as _ from allauth.account.adapter import get_adapter from allauth.account.forms import SignupForm from allauth.account.utils import setup_user_email +from dj_cleavejs import CleaveWidget from django_select2.forms import ModelSelect2MultipleWidget, ModelSelect2Widget, Select2Widget from dynamic_preferences.forms import PreferenceForm from guardian.shortcuts import assign_perm @@ -47,7 +48,6 @@ class PersonForm(ExtensibleForm): _("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")), @@ -66,7 +66,6 @@ class PersonForm(ExtensibleForm): model = Person fields = [ "user", - "is_active", "first_name", "last_name", "additional_name", @@ -401,6 +400,27 @@ DashboardWidgetOrderFormSet = forms.formset_factory( ) +class InvitationCodeForm(forms.Form): + """Form to enter an invitation code.""" + + code = forms.CharField( + label=_("Invitation code"), + help_text=_("Please enter your invitation code."), + ) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # Calculate number of fields + length = get_site_preferences()["auth__invite_code_length"] + packet_size = get_site_preferences()["auth__invite_code_packet_size"] + blocks = [ + packet_size, + ] * length + + self.fields["code"].widget = CleaveWidget(blocks=blocks, delimiter="-", uppercase=True) + + class SelectPermissionForm(forms.Form): """Select a permission to assign.""" @@ -521,13 +541,42 @@ class AccountRegisterForm(SignupForm, ExtensibleForm): """Form to register new user accounts.""" class Meta: - model = Group - fields = [] + model = Person + fields = [ + "first_name", + "additional_name", + "last_name", + "street", + "housenumber", + "postal_code", + "place", + "date_of_birth", + "place_of_birth", + "sex", + "photo", + "mobile_number", + "phone_number", + "short_name", + "description", + ] layout = Layout( Fieldset( _("Base data"), - Row("first_name", "last_name"), + Row("first_name", "additional_name", "last_name"), + "short_name", + ), + Fieldset( + _("Adress data"), + Row("street", "housenumber"), + Row("postal_code", "place"), + ), + Fieldset(_("Contact data"), Row("mobile_number", "phone_number")), + Fieldset( + _("Additional data"), + Row("date_of_birth", "place_of_birth"), + Row("sex", "photo"), + "description", ), Fieldset( _("Account data"), @@ -535,72 +584,46 @@ class AccountRegisterForm(SignupForm, ExtensibleForm): Row("email", "email2"), Row("password1", "password2"), ), - Fieldset( - _("Consents"), - Row("privacy_policy"), - ), ) - def __init__(self, *args, **kwargs): - super(AccountRegisterForm, self).__init__(*args, **kwargs) - self.fields["password1"] = forms.CharField(label=_("Password"), widget=forms.PasswordInput) - - privacy_policy = get_site_preferences()["footer__privacy_url"] - - if settings.SIGNUP_PASSWORD_ENTER_TWICE: - self.fields["password2"] = forms.CharField( - label=_("Password (again)"), widget=forms.PasswordInput - ) - - self.fields["first_name"] = forms.CharField( - required=True, - ) + password1 = forms.CharField(label=_("Password"), widget=forms.PasswordInput) - self.fields["last_name"] = forms.CharField( - required=True, - ) + if settings.SIGNUP_PASSWORD_ENTER_TWICE: + password2 = forms.CharField(label=_("Password (again)"), widget=forms.PasswordInput) - self.fields["privacy_policy"] = forms.BooleanField( - help_text=_( - f"I have read the <a href='{privacy_policy}'>Privacy policy</a>" - " and agree with them." - ), - required=True, - ) + def __init__(self, *args, **kwargs): + request = kwargs.pop("request", None) + super(AccountRegisterForm, self).__init__(*args, **kwargs) - def clean(self): - super(AccountRegisterForm, self).clean() + if request.session.get("account_verified_email"): + email = request.session["account_verified_email"] - dummy_user = get_user_model() - password = self.cleaned_data.get("password1") - if password: try: - get_adapter().clean_password(password, user=dummy_user) - except forms.ValidationError as e: - self.add_error("password1", e) + person = Person.objects.get(email=email) + except (Person.DoesNotExist, Person.MultipleObjectsReturned): + raise SuspiciousOperation() - if ( - settings.SIGNUP_PASSWORD_ENTER_TWICE - and "password1" in self.cleaned_data - and "password2" in self.cleaned_data - ): - if self.cleaned_data["password1"] != self.cleaned_data["password2"]: - self.add_error( - "password2", - _("You must type the same password each time."), - ) - return self.cleaned_data + self.fields["email"].disabled = True + self.fields["email2"].disabled = True + + if person: + available_fields = [field.name for field in Person._meta.get_fields()] + for field in self.fields: + if field in available_fields and getattr(person, field): + self.fields[field].disabled = True + self.fields[field].initial = getattr(person, field) def save(self, request): adapter = get_adapter(request) user = adapter.new_user(request) adapter.save_user(request, user, self) - Person.objects.create( - first_name=self.cleaned_data["first_name"], - last_name=self.cleaned_data["last_name"], - email=self.cleaned_data["email"], - user=user, - ) + # Create person + data = {} + for field in Person._meta.get_fields(): + if field.name in self.cleaned_data: + data[field.name] = self.cleaned_data[field.name] + if not Person.objects.filter(email=data["email"]): + _person, created = Person.objects.update_or_create(user=user, **data) self.custom_signup(request, user) setup_user_email(request, user, []) return user @@ -758,6 +781,7 @@ class OAuthApplicationForm(forms.ModelForm): model = OAuthApplication fields = ( "name", + "icon", "client_id", "client_secret", "client_type", diff --git a/aleksis/core/locale/ar/LC_MESSAGES/django.po b/aleksis/core/locale/ar/LC_MESSAGES/django.po index 33b5acc1cc5ba743104df96de5f85d64a90010c1..1ec59a49caf44641b442796d8e1ec3ebd502344d 100644 --- a/aleksis/core/locale/ar/LC_MESSAGES/django.po +++ b/aleksis/core/locale/ar/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: AlekSIS (School Information System) 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-29 09:59+0100\n" +"POT-Creation-Date: 2021-12-28 12:13+0100\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" @@ -18,26 +18,33 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" -#: aleksis/core/apps.py:151 +#: aleksis/core/apps.py:152 msgid "OpenID Connect scope" msgstr "" -#: aleksis/core/apps.py:152 +#: aleksis/core/apps.py:153 msgid "Given name, family name, link to profile and picture if existing." msgstr "" -#: aleksis/core/apps.py:153 +#: aleksis/core/apps.py:154 msgid "Full home postal address" msgstr "" -#: aleksis/core/apps.py:154 +#: aleksis/core/apps.py:155 msgid "Email address" msgstr "" -#: aleksis/core/apps.py:155 +#: aleksis/core/apps.py:156 msgid "Home and mobile phone" msgstr "" +#: aleksis/core/apps.py:157 aleksis/core/forms.py:223 aleksis/core/menus.py:265 +#: aleksis/core/models.py:414 aleksis/core/templates/core/group/list.html:8 +#: aleksis/core/templates/core/group/list.html:9 +#: aleksis/core/templates/core/person/full.html:152 +msgid "Groups" +msgstr "" + #: aleksis/core/data_checks.py:55 msgid "Ignore problem" msgstr "" @@ -84,156 +91,148 @@ msgstr "" msgid "Content type" msgstr "" -#: aleksis/core/filters.py:112 aleksis/core/models.py:579 +#: aleksis/core/filters.py:112 aleksis/core/models.py:581 msgid "User" msgstr "" -#: aleksis/core/filters.py:134 aleksis/core/models.py:411 +#: aleksis/core/filters.py:134 aleksis/core/models.py:413 msgid "Group" msgstr "" -#: aleksis/core/forms.py:46 aleksis/core/forms.py:514 +#: aleksis/core/forms.py:48 aleksis/core/forms.py:559 msgid "Base data" msgstr "" -#: aleksis/core/forms.py:52 +#: aleksis/core/forms.py:54 msgid "Address" msgstr "" -#: aleksis/core/forms.py:53 +#: aleksis/core/forms.py:55 aleksis/core/forms.py:568 msgid "Contact data" msgstr "" -#: aleksis/core/forms.py:55 +#: aleksis/core/forms.py:57 msgid "Advanced personal data" msgstr "" -#: aleksis/core/forms.py:103 +#: aleksis/core/forms.py:105 msgid "New user" msgstr "" -#: aleksis/core/forms.py:103 +#: aleksis/core/forms.py:105 msgid "Create a new account" msgstr "" -#: aleksis/core/forms.py:134 +#: aleksis/core/forms.py:136 msgid "You cannot set a new username when also selecting an existing user." msgstr "" -#: aleksis/core/forms.py:138 +#: aleksis/core/forms.py:140 msgid "This username is already in use." msgstr "" -#: aleksis/core/forms.py:155 aleksis/core/models.py:125 +#: aleksis/core/forms.py:157 aleksis/core/models.py:129 msgid "School term" msgstr "" -#: aleksis/core/forms.py:156 +#: aleksis/core/forms.py:158 msgid "Common data" msgstr "" -#: aleksis/core/forms.py:157 aleksis/core/forms.py:208 -#: aleksis/core/menus.py:256 aleksis/core/models.py:148 +#: aleksis/core/forms.py:159 aleksis/core/forms.py:210 +#: aleksis/core/menus.py:254 aleksis/core/models.py:152 #: aleksis/core/templates/core/person/list.html:8 #: aleksis/core/templates/core/person/list.html:9 msgid "Persons" msgstr "" -#: aleksis/core/forms.py:158 +#: aleksis/core/forms.py:160 aleksis/core/forms.py:570 msgid "Additional data" msgstr "" -#: aleksis/core/forms.py:200 aleksis/core/forms.py:203 -#: aleksis/core/models.py:68 +#: aleksis/core/forms.py:202 aleksis/core/forms.py:205 +#: aleksis/core/models.py:72 msgid "Date" msgstr "" -#: aleksis/core/forms.py:201 aleksis/core/forms.py:204 -#: aleksis/core/models.py:76 +#: aleksis/core/forms.py:203 aleksis/core/forms.py:206 +#: aleksis/core/models.py:80 msgid "Time" msgstr "" -#: aleksis/core/forms.py:221 aleksis/core/menus.py:267 -#: aleksis/core/models.py:412 aleksis/core/templates/core/group/list.html:8 -#: aleksis/core/templates/core/group/list.html:9 -#: aleksis/core/templates/core/person/full.html:145 -msgid "Groups" -msgstr "" - -#: aleksis/core/forms.py:234 +#: aleksis/core/forms.py:236 msgid "From when until when should the announcement be displayed?" msgstr "" -#: aleksis/core/forms.py:237 +#: aleksis/core/forms.py:239 msgid "Who should see the announcement?" msgstr "" -#: aleksis/core/forms.py:238 +#: aleksis/core/forms.py:240 msgid "Write your announcement:" msgstr "" -#: aleksis/core/forms.py:277 +#: aleksis/core/forms.py:279 msgid "You are not allowed to create announcements which are only valid in the past." msgstr "" -#: aleksis/core/forms.py:281 +#: aleksis/core/forms.py:283 msgid "The from date and time must be earlier then the until date and time." msgstr "" -#: aleksis/core/forms.py:290 +#: aleksis/core/forms.py:292 msgid "You need at least one recipient." msgstr "" -#: aleksis/core/forms.py:411 +#: aleksis/core/forms.py:401 +msgid "Invitation code" +msgstr "" + +#: aleksis/core/forms.py:402 +msgid "Please enter your invitation code." +msgstr "" + +#: aleksis/core/forms.py:434 msgid "Who should get the permission?" msgstr "" -#: aleksis/core/forms.py:412 +#: aleksis/core/forms.py:435 msgid "On what?" msgstr "" -#: aleksis/core/forms.py:438 +#: aleksis/core/forms.py:461 msgid "Select objects which the permission should be granted for:" msgstr "" -#: aleksis/core/forms.py:441 +#: aleksis/core/forms.py:464 msgid "Grant the permission for all objects" msgstr "" -#: aleksis/core/forms.py:449 +#: aleksis/core/forms.py:472 msgid "You must select at least one group or person which should get the permission." msgstr "" -#: aleksis/core/forms.py:454 +#: aleksis/core/forms.py:477 msgid "You must grant the permission to all objects and/or to some objects." msgstr "" -#: aleksis/core/forms.py:518 -msgid "Account data" +#: aleksis/core/forms.py:564 +msgid "Adress data" msgstr "" -#: aleksis/core/forms.py:524 -msgid "Consents" +#: aleksis/core/forms.py:576 +msgid "Account data" msgstr "" -#: aleksis/core/forms.py:531 +#: aleksis/core/forms.py:583 msgid "Password" msgstr "" -#: aleksis/core/forms.py:537 +#: aleksis/core/forms.py:586 msgid "Password (again)" msgstr "" -#: aleksis/core/forms.py:550 -#, python-brace-format -msgid "I have read the <a href='{privacy_policy}'>Privacy policy</a> and agree with them." -msgstr "" - -#: aleksis/core/forms.py:575 -msgid "You must type the same password each time." -msgstr "" - -#: aleksis/core/forms.py:720 +#: aleksis/core/forms.py:752 msgid "No valid selection." msgstr "" @@ -241,24 +240,20 @@ msgstr "" msgid "There are unresolved data problems." msgstr "" -#: aleksis/core/health_checks.py:38 -msgid "The backup folder doesn't exist." -msgstr "" - -#: aleksis/core/health_checks.py:47 +#: aleksis/core/health_checks.py:44 #, python-brace-format msgid "Last backup {time_gone_since_backup}!" msgstr "" -#: aleksis/core/health_checks.py:49 +#: aleksis/core/health_checks.py:46 msgid "No backup found!" msgstr "" -#: aleksis/core/health_checks.py:76 +#: aleksis/core/health_checks.py:73 msgid "No backup result found!" msgstr "" -#: aleksis/core/health_checks.py:78 +#: aleksis/core/health_checks.py:75 #, python-brace-format msgid "{task.status} - {task.result}" msgstr "" @@ -274,34 +269,38 @@ msgstr "" msgid "Sign up" msgstr "" -#: aleksis/core/menus.py:24 +#: aleksis/core/menus.py:24 aleksis/core/templates/invitations/enter.html:7 +msgid "Accept invitation" +msgstr "" + +#: aleksis/core/menus.py:33 msgid "Dashboard" msgstr "" -#: aleksis/core/menus.py:32 aleksis/core/models.py:625 -#: aleksis/core/preferences.py:27 +#: aleksis/core/menus.py:41 aleksis/core/models.py:627 +#: aleksis/core/preferences.py:28 #: aleksis/core/templates/core/notifications.html:4 #: aleksis/core/templates/core/notifications.html:5 msgid "Notifications" msgstr "" -#: aleksis/core/menus.py:44 +#: aleksis/core/menus.py:53 msgid "Account" msgstr "" -#: aleksis/core/menus.py:51 +#: aleksis/core/menus.py:60 msgid "Stop impersonation" msgstr "" -#: aleksis/core/menus.py:60 aleksis/core/templates/core/base.html:80 +#: aleksis/core/menus.py:69 aleksis/core/templates/core/base.html:80 msgid "Logout" msgstr "" -#: aleksis/core/menus.py:66 +#: aleksis/core/menus.py:75 msgid "2FA" msgstr "" -#: aleksis/core/menus.py:74 +#: aleksis/core/menus.py:83 #: aleksis/core/templates/account/password_change.html:5 #: aleksis/core/templates/account/password_change.html:6 #: aleksis/core/templates/account/password_change.html:19 @@ -313,830 +312,850 @@ msgstr "" msgid "Change password" msgstr "" -#: aleksis/core/menus.py:86 +#: aleksis/core/menus.py:95 msgid "Me" msgstr "" -#: aleksis/core/menus.py:95 +#: aleksis/core/menus.py:104 #: aleksis/core/templates/dynamic_preferences/form.html:5 msgid "Preferences" msgstr "" -#: aleksis/core/menus.py:104 +#: aleksis/core/menus.py:113 msgid "Third-party accounts" msgstr "" -#: aleksis/core/menus.py:113 +#: aleksis/core/menus.py:122 #: aleksis/core/templates/oauth2_provider/authorized-tokens.html:5 #: aleksis/core/templates/oauth2_provider/authorized-tokens.html:6 msgid "Authorized applications" msgstr "" -#: aleksis/core/menus.py:124 +#: aleksis/core/menus.py:133 msgid "Admin" msgstr "" -#: aleksis/core/menus.py:132 aleksis/core/models.py:725 +#: aleksis/core/menus.py:141 aleksis/core/models.py:727 #: aleksis/core/templates/core/announcement/list.html:7 #: aleksis/core/templates/core/announcement/list.html:8 msgid "Announcements" msgstr "" -#: aleksis/core/menus.py:143 aleksis/core/models.py:126 +#: aleksis/core/menus.py:152 aleksis/core/models.py:130 #: aleksis/core/templates/core/school_term/list.html:8 #: aleksis/core/templates/core/school_term/list.html:9 msgid "School terms" msgstr "" -#: aleksis/core/menus.py:154 +#: aleksis/core/menus.py:163 #: aleksis/core/templates/core/dashboard_widget/list.html:8 #: aleksis/core/templates/core/dashboard_widget/list.html:9 msgid "Dashboard widgets" msgstr "" -#: aleksis/core/menus.py:165 +#: aleksis/core/menus.py:174 #: aleksis/core/templates/core/management/data_management.html:6 #: aleksis/core/templates/core/management/data_management.html:7 msgid "Data management" msgstr "" -#: aleksis/core/menus.py:176 +#: aleksis/core/menus.py:185 #: aleksis/core/templates/core/pages/system_status.html:5 #: aleksis/core/templates/core/pages/system_status.html:7 msgid "System status" msgstr "" -#: aleksis/core/menus.py:187 -msgid "Impersonation" -msgstr "" - -#: aleksis/core/menus.py:198 +#: aleksis/core/menus.py:196 msgid "Configuration" msgstr "" -#: aleksis/core/menus.py:209 aleksis/core/templates/core/data_check/list.html:9 +#: aleksis/core/menus.py:207 aleksis/core/templates/core/data_check/list.html:9 #: aleksis/core/templates/core/data_check/list.html:10 msgid "Data checks" msgstr "" -#: aleksis/core/menus.py:215 aleksis/core/templates/core/perms/list.html:13 +#: aleksis/core/menus.py:213 aleksis/core/templates/core/perms/list.html:13 #: aleksis/core/templates/core/perms/list.html:14 msgid "Manage permissions" msgstr "" -#: aleksis/core/menus.py:226 +#: aleksis/core/menus.py:224 msgid "Backend Admin" msgstr "" -#: aleksis/core/menus.py:234 +#: aleksis/core/menus.py:232 #: aleksis/core/templates/oauth2_provider/application/list.html:5 #: aleksis/core/templates/oauth2_provider/application/list.html:6 msgid "OAuth2 Applications" msgstr "" -#: aleksis/core/menus.py:247 +#: aleksis/core/menus.py:245 msgid "People" msgstr "" -#: aleksis/core/menus.py:278 aleksis/core/models.py:979 +#: aleksis/core/menus.py:276 aleksis/core/models.py:981 #: aleksis/core/templates/core/group_type/list.html:8 #: aleksis/core/templates/core/group_type/list.html:9 msgid "Group types" msgstr "" -#: aleksis/core/menus.py:289 +#: aleksis/core/menus.py:287 msgid "Groups and child groups" msgstr "" -#: aleksis/core/menus.py:300 aleksis/core/models.py:460 +#: aleksis/core/menus.py:298 aleksis/core/models.py:462 #: aleksis/core/templates/core/additional_field/list.html:8 #: aleksis/core/templates/core/additional_field/list.html:9 msgid "Additional fields" msgstr "" -#: aleksis/core/menus.py:315 +#: aleksis/core/menus.py:309 +msgid "Invite person" +msgstr "" + +#: aleksis/core/menus.py:322 #: aleksis/core/templates/core/group/child_groups.html:7 #: aleksis/core/templates/core/group/child_groups.html:9 msgid "Assign child groups to groups" msgstr "" -#: aleksis/core/mixins.py:508 +#: aleksis/core/mixins.py:511 msgid "Linked school term" msgstr "" -#: aleksis/core/models.py:66 +#: aleksis/core/models.py:70 msgid "Boolean (Yes/No)" msgstr "" -#: aleksis/core/models.py:67 +#: aleksis/core/models.py:71 msgid "Text (one line)" msgstr "" -#: aleksis/core/models.py:69 +#: aleksis/core/models.py:73 msgid "Date and time" msgstr "" -#: aleksis/core/models.py:70 +#: aleksis/core/models.py:74 msgid "Decimal number" msgstr "" -#: aleksis/core/models.py:71 aleksis/core/models.py:194 +#: aleksis/core/models.py:75 aleksis/core/models.py:198 msgid "E-mail address" msgstr "" -#: aleksis/core/models.py:72 +#: aleksis/core/models.py:76 msgid "Integer" msgstr "" -#: aleksis/core/models.py:73 +#: aleksis/core/models.py:77 msgid "IP address" msgstr "" -#: aleksis/core/models.py:74 +#: aleksis/core/models.py:78 msgid "Boolean or empty (Yes/No/Neither)" msgstr "" -#: aleksis/core/models.py:75 +#: aleksis/core/models.py:79 msgid "Text (multi-line)" msgstr "" -#: aleksis/core/models.py:77 +#: aleksis/core/models.py:81 msgid "URL / Link" msgstr "" -#: aleksis/core/models.py:89 aleksis/core/models.py:948 +#: aleksis/core/models.py:93 aleksis/core/models.py:950 msgid "Name" msgstr "" -#: aleksis/core/models.py:91 +#: aleksis/core/models.py:95 msgid "Start date" msgstr "" -#: aleksis/core/models.py:92 +#: aleksis/core/models.py:96 msgid "End date" msgstr "" -#: aleksis/core/models.py:111 +#: aleksis/core/models.py:115 msgid "The start date must be earlier than the end date." msgstr "" -#: aleksis/core/models.py:118 +#: aleksis/core/models.py:122 msgid "There is already a school term for this time or a part of this time." msgstr "" -#: aleksis/core/models.py:147 aleksis/core/models.py:897 +#: aleksis/core/models.py:151 aleksis/core/models.py:899 msgid "Person" msgstr "" -#: aleksis/core/models.py:150 +#: aleksis/core/models.py:154 msgid "Can view address" msgstr "" -#: aleksis/core/models.py:151 +#: aleksis/core/models.py:155 msgid "Can view contact details" msgstr "" -#: aleksis/core/models.py:152 +#: aleksis/core/models.py:156 msgid "Can view photo" msgstr "" -#: aleksis/core/models.py:153 +#: aleksis/core/models.py:157 msgid "Can view persons groups" msgstr "" -#: aleksis/core/models.py:154 +#: aleksis/core/models.py:158 msgid "Can view personal details" msgstr "" -#: aleksis/core/models.py:164 +#: aleksis/core/models.py:168 msgid "female" msgstr "" -#: aleksis/core/models.py:164 +#: aleksis/core/models.py:168 msgid "male" msgstr "" -#: aleksis/core/models.py:172 +#: aleksis/core/models.py:176 aleksis/core/models.py:1144 msgid "Linked user" msgstr "" -#: aleksis/core/models.py:174 +#: aleksis/core/models.py:178 msgid "Is person active?" msgstr "" -#: aleksis/core/models.py:176 +#: aleksis/core/models.py:180 msgid "First name" msgstr "" -#: aleksis/core/models.py:177 +#: aleksis/core/models.py:181 msgid "Last name" msgstr "" -#: aleksis/core/models.py:179 +#: aleksis/core/models.py:183 msgid "Additional name(s)" msgstr "" -#: aleksis/core/models.py:183 aleksis/core/models.py:429 +#: aleksis/core/models.py:187 aleksis/core/models.py:431 msgid "Short name" msgstr "" -#: aleksis/core/models.py:186 +#: aleksis/core/models.py:190 msgid "Street" msgstr "" -#: aleksis/core/models.py:187 +#: aleksis/core/models.py:191 msgid "Street number" msgstr "" -#: aleksis/core/models.py:188 +#: aleksis/core/models.py:192 msgid "Postal code" msgstr "" -#: aleksis/core/models.py:189 +#: aleksis/core/models.py:193 msgid "Place" msgstr "" -#: aleksis/core/models.py:191 +#: aleksis/core/models.py:195 msgid "Home phone" msgstr "" -#: aleksis/core/models.py:192 +#: aleksis/core/models.py:196 msgid "Mobile phone" msgstr "" -#: aleksis/core/models.py:196 +#: aleksis/core/models.py:200 msgid "Date of birth" msgstr "" -#: aleksis/core/models.py:198 +#: aleksis/core/models.py:201 msgid "Place of birth" msgstr "" -#: aleksis/core/models.py:200 +#: aleksis/core/models.py:202 msgid "Sex" msgstr "" -#: aleksis/core/models.py:202 +#: aleksis/core/models.py:204 msgid "Photo" msgstr "" -#: aleksis/core/models.py:206 aleksis/core/templates/core/person/full.html:138 +#: aleksis/core/models.py:208 aleksis/core/templates/core/person/full.html:145 msgid "Guardians / Parents" msgstr "" -#: aleksis/core/models.py:213 +#: aleksis/core/models.py:215 msgid "Primary group" msgstr "" -#: aleksis/core/models.py:216 aleksis/core/models.py:583 -#: aleksis/core/models.py:607 aleksis/core/models.py:692 -#: aleksis/core/models.py:972 aleksis/core/templates/core/person/full.html:121 +#: aleksis/core/models.py:218 aleksis/core/models.py:585 +#: aleksis/core/models.py:609 aleksis/core/models.py:694 +#: aleksis/core/models.py:974 aleksis/core/templates/core/person/full.html:128 msgid "Description" msgstr "" -#: aleksis/core/models.py:384 +#: aleksis/core/models.py:386 msgid "Title of field" msgstr "" -#: aleksis/core/models.py:386 +#: aleksis/core/models.py:388 msgid "Type of field" msgstr "" -#: aleksis/core/models.py:393 +#: aleksis/core/models.py:395 msgid "Addtitional field for groups" msgstr "" -#: aleksis/core/models.py:394 +#: aleksis/core/models.py:396 msgid "Addtitional fields for groups" msgstr "" -#: aleksis/core/models.py:414 +#: aleksis/core/models.py:416 msgid "Can assign child groups to groups" msgstr "" -#: aleksis/core/models.py:415 +#: aleksis/core/models.py:417 msgid "Can view statistics about group." msgstr "" -#: aleksis/core/models.py:427 +#: aleksis/core/models.py:429 msgid "Long name" msgstr "" -#: aleksis/core/models.py:437 aleksis/core/templates/core/group/full.html:85 +#: aleksis/core/models.py:439 aleksis/core/templates/core/group/full.html:85 msgid "Members" msgstr "" -#: aleksis/core/models.py:440 aleksis/core/templates/core/group/full.html:82 +#: aleksis/core/models.py:442 aleksis/core/templates/core/group/full.html:82 msgid "Owners" msgstr "" -#: aleksis/core/models.py:447 aleksis/core/templates/core/group/full.html:55 +#: aleksis/core/models.py:449 aleksis/core/templates/core/group/full.html:55 msgid "Parent groups" msgstr "" -#: aleksis/core/models.py:455 +#: aleksis/core/models.py:457 msgid "Type of group" msgstr "" -#: aleksis/core/models.py:582 aleksis/core/models.py:606 -#: aleksis/core/models.py:691 +#: aleksis/core/models.py:584 aleksis/core/models.py:608 +#: aleksis/core/models.py:693 #: aleksis/core/templates/core/announcement/list.html:18 msgid "Title" msgstr "" -#: aleksis/core/models.py:585 +#: aleksis/core/models.py:587 msgid "Application" msgstr "" -#: aleksis/core/models.py:591 +#: aleksis/core/models.py:593 msgid "Activity" msgstr "" -#: aleksis/core/models.py:592 +#: aleksis/core/models.py:594 msgid "Activities" msgstr "" -#: aleksis/core/models.py:598 +#: aleksis/core/models.py:600 msgid "Sender" msgstr "" -#: aleksis/core/models.py:603 +#: aleksis/core/models.py:605 msgid "Recipient" msgstr "" -#: aleksis/core/models.py:608 aleksis/core/models.py:949 +#: aleksis/core/models.py:610 aleksis/core/models.py:951 msgid "Link" msgstr "" -#: aleksis/core/models.py:610 +#: aleksis/core/models.py:612 msgid "Read" msgstr "" -#: aleksis/core/models.py:611 +#: aleksis/core/models.py:613 msgid "Sent" msgstr "" -#: aleksis/core/models.py:624 +#: aleksis/core/models.py:626 msgid "Notification" msgstr "" -#: aleksis/core/models.py:693 +#: aleksis/core/models.py:695 msgid "Link to detailed view" msgstr "" -#: aleksis/core/models.py:696 +#: aleksis/core/models.py:698 msgid "Date and time from when to show" msgstr "" -#: aleksis/core/models.py:699 +#: aleksis/core/models.py:701 msgid "Date and time until when to show" msgstr "" -#: aleksis/core/models.py:724 +#: aleksis/core/models.py:726 msgid "Announcement" msgstr "" -#: aleksis/core/models.py:762 +#: aleksis/core/models.py:764 msgid "Announcement recipient" msgstr "" -#: aleksis/core/models.py:763 +#: aleksis/core/models.py:765 msgid "Announcement recipients" msgstr "" -#: aleksis/core/models.py:818 +#: aleksis/core/models.py:820 msgid "Widget Title" msgstr "" -#: aleksis/core/models.py:819 +#: aleksis/core/models.py:821 msgid "Activate Widget" msgstr "" -#: aleksis/core/models.py:820 +#: aleksis/core/models.py:822 msgid "Widget is broken" msgstr "" -#: aleksis/core/models.py:823 +#: aleksis/core/models.py:825 msgid "Size on mobile devices" msgstr "" -#: aleksis/core/models.py:824 +#: aleksis/core/models.py:826 msgid "<= 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:829 +#: aleksis/core/models.py:831 msgid "Size on tablet devices" msgstr "" -#: aleksis/core/models.py:830 +#: aleksis/core/models.py:832 msgid "> 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:835 +#: aleksis/core/models.py:837 msgid "Size on desktop devices" msgstr "" -#: aleksis/core/models.py:836 +#: aleksis/core/models.py:838 msgid "> 992 px, 12 columns" msgstr "" -#: aleksis/core/models.py:841 +#: aleksis/core/models.py:843 msgid "Size on large desktop devices" msgstr "" -#: aleksis/core/models.py:842 +#: aleksis/core/models.py:844 msgid "> 1200 px>, 12 columns" msgstr "" -#: aleksis/core/models.py:873 +#: aleksis/core/models.py:875 msgid "Can edit default dashboard" msgstr "" -#: aleksis/core/models.py:874 +#: aleksis/core/models.py:876 msgid "Dashboard Widget" msgstr "" -#: aleksis/core/models.py:875 +#: aleksis/core/models.py:877 msgid "Dashboard Widgets" msgstr "" -#: aleksis/core/models.py:881 +#: aleksis/core/models.py:883 msgid "URL" msgstr "" -#: aleksis/core/models.py:882 +#: aleksis/core/models.py:884 msgid "Icon URL" msgstr "" -#: aleksis/core/models.py:888 +#: aleksis/core/models.py:890 msgid "External link widget" msgstr "" -#: aleksis/core/models.py:889 +#: aleksis/core/models.py:891 msgid "External link widgets" msgstr "" -#: aleksis/core/models.py:894 +#: aleksis/core/models.py:896 msgid "Dashboard widget" msgstr "" -#: aleksis/core/models.py:899 +#: aleksis/core/models.py:901 msgid "Order" msgstr "" -#: aleksis/core/models.py:900 +#: aleksis/core/models.py:902 msgid "Part of the default dashboard" msgstr "" -#: aleksis/core/models.py:915 +#: aleksis/core/models.py:917 msgid "Dashboard widget order" msgstr "" -#: aleksis/core/models.py:916 +#: aleksis/core/models.py:918 msgid "Dashboard widget orders" msgstr "" -#: aleksis/core/models.py:922 +#: aleksis/core/models.py:924 msgid "Menu ID" msgstr "" -#: aleksis/core/models.py:935 +#: aleksis/core/models.py:937 msgid "Custom menu" msgstr "" -#: aleksis/core/models.py:936 +#: aleksis/core/models.py:938 msgid "Custom menus" msgstr "" -#: aleksis/core/models.py:946 +#: aleksis/core/models.py:948 msgid "Menu" msgstr "" -#: aleksis/core/models.py:950 +#: aleksis/core/models.py:952 msgid "Icon" msgstr "" -#: aleksis/core/models.py:956 +#: aleksis/core/models.py:958 msgid "Custom menu item" msgstr "" -#: aleksis/core/models.py:957 +#: aleksis/core/models.py:959 msgid "Custom menu items" msgstr "" -#: aleksis/core/models.py:971 +#: aleksis/core/models.py:973 msgid "Title of type" msgstr "" -#: aleksis/core/models.py:978 aleksis/core/templates/core/group/full.html:47 +#: aleksis/core/models.py:980 aleksis/core/templates/core/group/full.html:47 msgid "Group type" msgstr "" -#: aleksis/core/models.py:992 +#: aleksis/core/models.py:994 msgid "Can view system status" msgstr "" -#: aleksis/core/models.py:993 +#: aleksis/core/models.py:995 msgid "Can manage data" msgstr "" -#: aleksis/core/models.py:994 +#: aleksis/core/models.py:996 msgid "Can impersonate" msgstr "" -#: aleksis/core/models.py:995 +#: aleksis/core/models.py:997 msgid "Can use search" msgstr "" -#: aleksis/core/models.py:996 +#: aleksis/core/models.py:998 msgid "Can change site preferences" msgstr "" -#: aleksis/core/models.py:997 +#: aleksis/core/models.py:999 msgid "Can change person preferences" msgstr "" -#: aleksis/core/models.py:998 +#: aleksis/core/models.py:1000 msgid "Can change group preferences" msgstr "" -#: aleksis/core/models.py:999 +#: aleksis/core/models.py:1001 msgid "Can test PDF generation" msgstr "" -#: aleksis/core/models.py:1035 +#: aleksis/core/models.py:1037 msgid "Related data check task" msgstr "" -#: aleksis/core/models.py:1043 +#: aleksis/core/models.py:1045 msgid "Issue solved" msgstr "" -#: aleksis/core/models.py:1044 +#: aleksis/core/models.py:1046 msgid "Notification sent" msgstr "" -#: aleksis/core/models.py:1057 +#: aleksis/core/models.py:1059 msgid "Data check result" msgstr "" -#: aleksis/core/models.py:1058 +#: aleksis/core/models.py:1060 msgid "Data check results" msgstr "" -#: aleksis/core/models.py:1060 +#: aleksis/core/models.py:1062 msgid "Can run data checks" msgstr "" -#: aleksis/core/models.py:1061 +#: aleksis/core/models.py:1063 msgid "Can solve data check problems" msgstr "" -#: aleksis/core/models.py:1076 +#: aleksis/core/models.py:1070 +msgid "E-Mail address" +msgstr "" + +#: aleksis/core/models.py:1094 msgid "Owner" msgstr "" -#: aleksis/core/models.py:1080 +#: aleksis/core/models.py:1098 msgid "File expires at" msgstr "" -#: aleksis/core/models.py:1082 +#: aleksis/core/models.py:1100 msgid "Generated HTML file" msgstr "" -#: aleksis/core/models.py:1084 +#: aleksis/core/models.py:1102 msgid "Generated PDF file" msgstr "" -#: aleksis/core/models.py:1091 +#: aleksis/core/models.py:1109 msgid "PDF file" msgstr "" -#: aleksis/core/models.py:1092 +#: aleksis/core/models.py:1110 msgid "PDF files" msgstr "" -#: aleksis/core/models.py:1097 +#: aleksis/core/models.py:1115 msgid "Task result" msgstr "" -#: aleksis/core/models.py:1100 +#: aleksis/core/models.py:1118 msgid "Task user" msgstr "" -#: aleksis/core/models.py:1112 +#: aleksis/core/models.py:1130 msgid "Task user assignment" msgstr "" -#: aleksis/core/models.py:1113 +#: aleksis/core/models.py:1131 msgid "Task user assignments" msgstr "" -#: aleksis/core/models.py:1127 +#: aleksis/core/models.py:1147 +msgid "Additional attributes" +msgstr "" + +#: aleksis/core/models.py:1185 msgid "Allowed scopes that clients can request" msgstr "" -#: aleksis/core/preferences.py:23 +#: aleksis/core/preferences.py:24 msgid "General" msgstr "" -#: aleksis/core/preferences.py:24 +#: aleksis/core/preferences.py:25 msgid "School" msgstr "" -#: aleksis/core/preferences.py:25 +#: aleksis/core/preferences.py:26 msgid "Theme" msgstr "" -#: aleksis/core/preferences.py:26 +#: aleksis/core/preferences.py:27 msgid "Mail" msgstr "" -#: aleksis/core/preferences.py:28 +#: aleksis/core/preferences.py:29 msgid "Footer" msgstr "" -#: aleksis/core/preferences.py:29 +#: aleksis/core/preferences.py:30 msgid "Accounts" msgstr "" -#: aleksis/core/preferences.py:30 +#: aleksis/core/preferences.py:31 msgid "Authentication" msgstr "" -#: aleksis/core/preferences.py:31 +#: aleksis/core/preferences.py:32 msgid "Internationalisation" msgstr "" -#: aleksis/core/preferences.py:42 +#: aleksis/core/preferences.py:43 msgid "Site title" msgstr "" -#: aleksis/core/preferences.py:53 +#: aleksis/core/preferences.py:54 msgid "Site description" msgstr "" -#: aleksis/core/preferences.py:64 +#: aleksis/core/preferences.py:65 msgid "Primary colour" msgstr "" -#: aleksis/core/preferences.py:76 +#: aleksis/core/preferences.py:77 msgid "Secondary colour" msgstr "" -#: aleksis/core/preferences.py:87 +#: aleksis/core/preferences.py:88 msgid "Logo" msgstr "" -#: aleksis/core/preferences.py:97 +#: aleksis/core/preferences.py:98 msgid "Favicon" msgstr "" -#: aleksis/core/preferences.py:107 +#: aleksis/core/preferences.py:108 msgid "PWA-Icon" msgstr "" -#: aleksis/core/preferences.py:118 +#: aleksis/core/preferences.py:119 msgid "Mail out name" msgstr "" -#: aleksis/core/preferences.py:129 +#: aleksis/core/preferences.py:130 msgid "Mail out address" msgstr "" -#: aleksis/core/preferences.py:141 +#: aleksis/core/preferences.py:142 msgid "Link to privacy policy" msgstr "" -#: aleksis/core/preferences.py:153 +#: aleksis/core/preferences.py:154 msgid "Link to imprint" msgstr "" -#: aleksis/core/preferences.py:165 +#: aleksis/core/preferences.py:166 msgid "Name format for addressing" msgstr "" -#: aleksis/core/preferences.py:181 +#: aleksis/core/preferences.py:182 msgid "Channels to use for notifications" msgstr "" -#: aleksis/core/preferences.py:193 +#: aleksis/core/preferences.py:194 msgid "Regular expression to match primary group, e.g. '^Class .*'" msgstr "" -#: aleksis/core/preferences.py:204 +#: aleksis/core/preferences.py:205 msgid "Field on person to match primary group against" msgstr "" -#: aleksis/core/preferences.py:216 +#: aleksis/core/preferences.py:217 msgid "Automatically create new persons for new users" msgstr "" -#: aleksis/core/preferences.py:225 +#: aleksis/core/preferences.py:226 msgid "Automatically link existing persons to new users by their e-mail address" msgstr "" -#: aleksis/core/preferences.py:236 +#: aleksis/core/preferences.py:237 msgid "Display name of the school" msgstr "" -#: aleksis/core/preferences.py:247 +#: aleksis/core/preferences.py:248 msgid "Official name of the school, e.g. as given by supervisory authority" msgstr "" -#: aleksis/core/preferences.py:255 +#: aleksis/core/preferences.py:256 msgid "Allow users to change their passwords" msgstr "" -#: aleksis/core/preferences.py:263 +#: aleksis/core/preferences.py:264 msgid "Enable signup" msgstr "" -#: aleksis/core/preferences.py:274 +#: aleksis/core/preferences.py:272 +msgid "Enable invitations" +msgstr "" + +#: aleksis/core/preferences.py:280 +msgid "Length of invite code. (Default 3: abcde-acbde-abcde)" +msgstr "" + +#: aleksis/core/preferences.py:288 +msgid "Size of packets. (Default 5: abcde)" +msgstr "" + +#: aleksis/core/preferences.py:298 msgid "Allowed Grant Flows for OAuth applications" msgstr "" -#: aleksis/core/preferences.py:287 +#: aleksis/core/preferences.py:311 msgid "Available languages" msgstr "" -#: aleksis/core/preferences.py:299 +#: aleksis/core/preferences.py:323 msgid "Send emails if data checks detect problems" msgstr "" -#: aleksis/core/preferences.py:310 +#: aleksis/core/preferences.py:334 msgid "Email recipients for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:321 +#: aleksis/core/preferences.py:345 msgid "Email recipient groups for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:330 +#: aleksis/core/preferences.py:354 msgid "Show dashboard to users without login" msgstr "" -#: aleksis/core/preferences.py:339 +#: aleksis/core/preferences.py:363 msgid "Allow users to edit their dashboard" msgstr "" -#: aleksis/core/preferences.py:350 +#: aleksis/core/preferences.py:374 msgid "Fields on person model which are editable by themselves." msgstr "" -#: aleksis/core/preferences.py:364 +#: aleksis/core/preferences.py:388 msgid "Editable fields on person model which should trigger a notification on change" msgstr "" -#: aleksis/core/preferences.py:377 +#: aleksis/core/preferences.py:401 msgid "Contact for notification if a person changes their data" msgstr "" -#: aleksis/core/preferences.py:387 +#: aleksis/core/preferences.py:411 msgid "PDF file expiration duration" msgstr "" -#: aleksis/core/preferences.py:388 +#: aleksis/core/preferences.py:412 msgid "in minutes" msgstr "" -#: aleksis/core/preferences.py:398 +#: aleksis/core/preferences.py:422 msgid "Automatically update the dashboard and its widgets" msgstr "" -#: aleksis/core/preferences.py:408 +#: aleksis/core/preferences.py:432 msgid "Automatically update the dashboard and its widgets sitewide" msgstr "" -#: aleksis/core/settings.py:474 +#: aleksis/core/settings.py:507 msgid "English" msgstr "" -#: aleksis/core/settings.py:475 +#: aleksis/core/settings.py:508 msgid "German" msgstr "" -#: aleksis/core/tables.py:19 +#: aleksis/core/tables.py:24 #: aleksis/core/templates/core/announcement/list.html:36 #: aleksis/core/templates/core/group/full.html:24 -#: aleksis/core/templates/core/person/full.html:23 +#: aleksis/core/templates/core/person/full.html:24 #: aleksis/core/templates/oauth2_provider/application/detail.html:17 msgid "Edit" msgstr "" -#: aleksis/core/tables.py:21 aleksis/core/tables.py:89 -#: aleksis/core/tables.py:105 +#: aleksis/core/tables.py:26 aleksis/core/tables.py:94 +#: aleksis/core/tables.py:137 #: aleksis/core/templates/core/announcement/list.html:22 msgid "Actions" msgstr "" -#: aleksis/core/tables.py:56 aleksis/core/tables.py:57 -#: aleksis/core/tables.py:71 aleksis/core/tables.py:87 -#: aleksis/core/tables.py:103 +#: aleksis/core/tables.py:61 aleksis/core/tables.py:62 +#: aleksis/core/tables.py:76 aleksis/core/tables.py:92 +#: aleksis/core/tables.py:135 #: aleksis/core/templates/core/announcement/list.html:42 #: aleksis/core/templates/core/group/full.html:31 #: aleksis/core/templates/core/pages/delete.html:22 -#: aleksis/core/templates/core/person/full.html:30 +#: aleksis/core/templates/core/person/full.html:31 #: aleksis/core/templates/oauth2_provider/application/detail.html:21 msgid "Delete" msgstr "" @@ -1208,11 +1227,11 @@ msgstr "" msgid "Account inactive" msgstr "" -#: aleksis/core/templates/account/account_inactive.html:13 +#: aleksis/core/templates/account/account_inactive.html:14 msgid "Account inactive." msgstr "" -#: aleksis/core/templates/account/account_inactive.html:15 +#: aleksis/core/templates/account/account_inactive.html:17 msgid "" "\n" " This account is currently inactive. If you think this is an\n" @@ -1364,11 +1383,11 @@ msgstr "" msgid "Signup closed" msgstr "" -#: aleksis/core/templates/account/signup_closed.html:13 +#: aleksis/core/templates/account/signup_closed.html:14 msgid "Signup closed." msgstr "" -#: aleksis/core/templates/account/signup_closed.html:15 +#: aleksis/core/templates/account/signup_closed.html:17 msgid "" "\n" " This sign up is currently closed. If you think this is an\n" @@ -1406,11 +1425,6 @@ msgid "" " " msgstr "" -#: aleksis/core/templates/account/verification_sent.html:30 -#, python-format -msgid "<strong>Note:</strong> you can still <a href=\"%(email_url)s\">change your e-mail address</a>" -msgstr "" - #: aleksis/core/templates/core/additional_field/edit.html:6 #: aleksis/core/templates/core/additional_field/edit.html:7 msgid "Edit additional field" @@ -1459,11 +1473,11 @@ msgid "Logged in as" msgstr "" #: aleksis/core/templates/core/base.html:175 -msgid "About AlekSIS — The Free School Information System" +msgid "About AlekSIS® — The Free School Information System" msgstr "" #: aleksis/core/templates/core/base.html:183 -msgid "Impress" +msgid "Imprint" msgstr "" #: aleksis/core/templates/core/base.html:191 @@ -1471,7 +1485,7 @@ msgid "Privacy Policy" msgstr "" #: aleksis/core/templates/core/base_print.html:72 -msgid "Powered by AlekSIS" +msgid "Powered by AlekSIS®" msgstr "" #: aleksis/core/templates/core/dashboard_widget/create.html:8 @@ -1686,7 +1700,7 @@ msgid "Edit group" msgstr "" #: aleksis/core/templates/core/group/full.html:38 -#: aleksis/core/templates/core/person/full.html:37 +#: aleksis/core/templates/core/person/full.html:38 msgid "Change preferences" msgstr "" @@ -1775,36 +1789,46 @@ msgid "No notifications available yet." msgstr "" #: aleksis/core/templates/core/pages/about.html:6 -#: aleksis/core/templates/core/pages/about.html:15 -msgid "About AlekSIS" +msgid "About AlekSIS®" msgstr "" #: aleksis/core/templates/core/pages/about.html:7 -msgid "AlekSIS – The Free School Information System" +msgid "AlekSIS® – The Free School Information System" +msgstr "" + +#: aleksis/core/templates/core/pages/about.html:15 +msgid "About AlekSIS" msgstr "" #: aleksis/core/templates/core/pages/about.html:17 msgid "" "\n" -" This platform is powered by AlekSIS, a web-based school information system (SIS) which can be used\n" +" This platform is powered by AlekSIS®, a web-based school information system (SIS) which can be used\n" " to manage and/or publish organisational artifacts of educational institutions. AlekSIS is free software and\n" " can be used by anyone.\n" " " msgstr "" -#: aleksis/core/templates/core/pages/about.html:25 +#: aleksis/core/templates/core/pages/about.html:24 +msgid "" +"\n" +" AlekSIS® is a registered trademark of the AlekSIS open source project, represented by Teckids e.V.\n" +" " +msgstr "" + +#: aleksis/core/templates/core/pages/about.html:30 msgid "Website of AlekSIS" msgstr "" -#: aleksis/core/templates/core/pages/about.html:26 +#: aleksis/core/templates/core/pages/about.html:31 msgid "Source code" msgstr "" -#: aleksis/core/templates/core/pages/about.html:35 +#: aleksis/core/templates/core/pages/about.html:40 msgid "Licence information" msgstr "" -#: aleksis/core/templates/core/pages/about.html:37 +#: aleksis/core/templates/core/pages/about.html:42 msgid "" "\n" " The core and the official apps of AlekSIS are licenced under the EUPL, version 1.2 or later. For licence\n" @@ -1813,23 +1837,23 @@ msgid "" " " msgstr "" -#: aleksis/core/templates/core/pages/about.html:45 +#: aleksis/core/templates/core/pages/about.html:50 msgid "Free/Open Source Licence" msgstr "" -#: aleksis/core/templates/core/pages/about.html:46 +#: aleksis/core/templates/core/pages/about.html:51 msgid "Other Licence" msgstr "" -#: aleksis/core/templates/core/pages/about.html:50 +#: aleksis/core/templates/core/pages/about.html:55 msgid "Full licence text" msgstr "" -#: aleksis/core/templates/core/pages/about.html:51 +#: aleksis/core/templates/core/pages/about.html:56 msgid "More information about the EUPL" msgstr "" -#: aleksis/core/templates/core/pages/about.html:90 +#: aleksis/core/templates/core/pages/about.html:95 #, python-format msgid "" "\n" @@ -2070,17 +2094,19 @@ msgstr "" msgid "Edit person" msgstr "" -#: aleksis/core/templates/core/person/full.html:44 -#: aleksis/core/templates/impersonate/list_users.html:7 -#: aleksis/core/templates/impersonate/list_users.html:8 +#: aleksis/core/templates/core/person/full.html:45 msgid "Impersonate" msgstr "" -#: aleksis/core/templates/core/person/full.html:50 +#: aleksis/core/templates/core/person/full.html:51 +msgid "Invite user" +msgstr "" + +#: aleksis/core/templates/core/person/full.html:57 msgid "Contact details" msgstr "" -#: aleksis/core/templates/core/person/full.html:131 +#: aleksis/core/templates/core/person/full.html:138 msgid "Children" msgstr "" @@ -2120,6 +2146,49 @@ msgstr "" msgid "Save preferences" msgstr "" +#: aleksis/core/templates/invitations/enter.html:21 +msgid "Accept your invitation" +msgstr "" + +#: aleksis/core/templates/invitations/enter.html:25 +msgid "" +"\n" +" Please enter your invitation code to register\n" +" your new user account:\n" +" " +msgstr "" + +#: aleksis/core/templates/invitations/enter.html:37 +msgid "Accept invite" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:9 +#: aleksis/core/templates/invitations/forms/_invite.html:10 +#: aleksis/core/templates/invitations/forms/_invite.html:21 +msgid "Invite" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:17 +msgid "Invite by email address" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:26 +msgid "Generate invitation code" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:29 +msgid "Generate code" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:33 +msgid "Invitations" +msgstr "" + +#: aleksis/core/templates/invitations/messages/invite_accepted.txt:3 +#, python-format +msgid "The invitation for %(email)s has been accepted." +msgstr "" + #: aleksis/core/templates/oauth2_provider/application/create.html:5 #: aleksis/core/templates/oauth2_provider/application/create.html:6 msgid "Register OAuth2 Application" @@ -2780,147 +2849,160 @@ msgstr "" msgid "SMS" msgstr "" -#: aleksis/core/util/pdf.py:105 +#: aleksis/core/util/pdf.py:113 msgid "Progress: Generate PDF file" msgstr "" -#: aleksis/core/util/pdf.py:106 +#: aleksis/core/util/pdf.py:114 msgid "Generating PDF file …" msgstr "" -#: aleksis/core/util/pdf.py:107 +#: aleksis/core/util/pdf.py:115 msgid "The PDF file has been generated successfully." msgstr "" -#: aleksis/core/util/pdf.py:108 +#: aleksis/core/util/pdf.py:116 msgid "There was a problem while generating the PDF file." msgstr "" -#: aleksis/core/util/pdf.py:111 +#: aleksis/core/util/pdf.py:119 msgid "Download PDF" msgstr "" -#: aleksis/core/views.py:270 +#: aleksis/core/views.py:280 msgid "The school term has been created." msgstr "" -#: aleksis/core/views.py:282 +#: aleksis/core/views.py:292 msgid "The school term has been saved." msgstr "" -#: aleksis/core/views.py:406 +#: aleksis/core/views.py:416 msgid "The child groups were successfully saved." msgstr "" -#: aleksis/core/views.py:425 aleksis/core/views.py:435 +#: aleksis/core/views.py:435 aleksis/core/views.py:445 msgid "The person has been saved." msgstr "" -#: aleksis/core/views.py:485 +#: aleksis/core/views.py:495 msgid "The group has been saved." msgstr "" -#: aleksis/core/views.py:582 +#: aleksis/core/views.py:592 msgid "The announcement has been saved." msgstr "" -#: aleksis/core/views.py:598 +#: aleksis/core/views.py:608 msgid "The announcement has been deleted." msgstr "" -#: aleksis/core/views.py:682 +#: aleksis/core/views.py:695 msgid "The preferences have been saved successfully." msgstr "" -#: aleksis/core/views.py:706 +#: aleksis/core/views.py:719 msgid "The person has been deleted." msgstr "" -#: aleksis/core/views.py:720 +#: aleksis/core/views.py:733 msgid "The group has been deleted." msgstr "" -#: aleksis/core/views.py:752 +#: aleksis/core/views.py:765 msgid "The additional_field has been saved." msgstr "" -#: aleksis/core/views.py:786 +#: aleksis/core/views.py:799 msgid "The additional field has been deleted." msgstr "" -#: aleksis/core/views.py:811 +#: aleksis/core/views.py:824 msgid "The group type has been saved." msgstr "" -#: aleksis/core/views.py:841 +#: aleksis/core/views.py:854 msgid "The group type has been deleted." msgstr "" -#: aleksis/core/views.py:874 +#: aleksis/core/views.py:887 msgid "Progress: Run data checks" msgstr "" -#: aleksis/core/views.py:875 +#: aleksis/core/views.py:888 msgid "Run data checks …" msgstr "" -#: aleksis/core/views.py:876 +#: aleksis/core/views.py:889 msgid "The data checks were run successfully." msgstr "" -#: aleksis/core/views.py:877 +#: aleksis/core/views.py:890 msgid "There was a problem while running data checks." msgstr "" -#: aleksis/core/views.py:893 +#: aleksis/core/views.py:906 #, python-brace-format msgid "The solve option '{solve_option_obj.verbose_name}' " msgstr "" -#: aleksis/core/views.py:935 +#: aleksis/core/views.py:948 msgid "The dashboard widget has been saved." msgstr "" -#: aleksis/core/views.py:965 +#: aleksis/core/views.py:978 msgid "The dashboard widget has been created." msgstr "" -#: aleksis/core/views.py:975 +#: aleksis/core/views.py:988 msgid "The dashboard widget has been deleted." msgstr "" -#: aleksis/core/views.py:1042 +#: aleksis/core/views.py:1055 msgid "Your dashboard configuration has been saved successfully." msgstr "" -#: aleksis/core/views.py:1044 +#: aleksis/core/views.py:1057 msgid "The configuration of the default dashboard has been saved successfully." msgstr "" -#: aleksis/core/views.py:1139 +#: aleksis/core/views.py:1127 +#, python-brace-format +msgid "The invitation was successfully created. The invitation code is {code}" +msgstr "" + +#: aleksis/core/views.py:1218 msgid "We have successfully assigned the permissions." msgstr "" -#: aleksis/core/views.py:1149 +#: aleksis/core/views.py:1228 msgid "The global user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1159 +#: aleksis/core/views.py:1238 msgid "The global group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1169 +#: aleksis/core/views.py:1248 msgid "The object user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1179 +#: aleksis/core/views.py:1258 msgid "The object group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1298 +#: aleksis/core/views.py:1377 msgid "The third-party account could not be disconnected because it is the only login method available." msgstr "" -#: aleksis/core/views.py:1305 +#: aleksis/core/views.py:1384 msgid "The third-party account has been successfully disconnected." msgstr "" + +#: aleksis/core/views.py:1441 +msgid "Person was invited successfully." +msgstr "" + +#: aleksis/core/views.py:1443 +msgid "Person was already invited." +msgstr "" diff --git a/aleksis/core/locale/ar/LC_MESSAGES/djangojs.po b/aleksis/core/locale/ar/LC_MESSAGES/djangojs.po index eacffd3e211761afbf5bb697e91ee630c6d3eabc..ac0e765ef8e4c2d7ac490397fcd99e22fd921846 100644 --- a/aleksis/core/locale/ar/LC_MESSAGES/djangojs.po +++ b/aleksis/core/locale/ar/LC_MESSAGES/djangojs.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-29 09:59+0100\n" +"POT-Creation-Date: 2021-12-28 12:14+0100\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" @@ -30,6 +30,6 @@ msgstr "" msgid "OK" msgstr "" -#: aleksis/core/static/js/main.js:127 +#: aleksis/core/static/js/main.js:128 msgid "This page may contain outdated information since there is no internet connection." msgstr "" diff --git a/aleksis/core/locale/de_DE/LC_MESSAGES/django.po b/aleksis/core/locale/de_DE/LC_MESSAGES/django.po index a4078edbe8ad41e7ed85dc18d522f063c7cce33c..6a7afee49da25f0111b97b04ca8f4f51eb7aeba8 100644 --- a/aleksis/core/locale/de_DE/LC_MESSAGES/django.po +++ b/aleksis/core/locale/de_DE/LC_MESSAGES/django.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: AlekSIS (School Information System) 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-29 09:59+0100\n" -"PO-Revision-Date: 2021-11-29 09:34+0000\n" +"POT-Creation-Date: 2021-12-28 12:13+0100\n" +"PO-Revision-Date: 2021-12-29 13:20+0000\n" "Last-Translator: Jonathan Weth <teckids@jonathanweth.de>\n" "Language-Team: German <https://translate.edugit.org/projects/aleksis/" "aleksis-core/de/>\n" @@ -19,26 +19,33 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.8\n" -#: aleksis/core/apps.py:151 +#: aleksis/core/apps.py:152 msgid "OpenID Connect scope" msgstr "OpenID-Connect-Scope" -#: aleksis/core/apps.py:152 +#: aleksis/core/apps.py:153 msgid "Given name, family name, link to profile and picture if existing." msgstr "Vorname, Nachname, Link zum Profil und Bild falls vorhanden" -#: aleksis/core/apps.py:153 +#: aleksis/core/apps.py:154 msgid "Full home postal address" msgstr "Vollständige Postanschrift" -#: aleksis/core/apps.py:154 +#: aleksis/core/apps.py:155 msgid "Email address" msgstr "E-Mail-Adresse" -#: aleksis/core/apps.py:155 +#: aleksis/core/apps.py:156 msgid "Home and mobile phone" msgstr "Festnetz- und Mobilfunknummer" +#: aleksis/core/apps.py:157 aleksis/core/forms.py:223 aleksis/core/menus.py:265 +#: aleksis/core/models.py:414 aleksis/core/templates/core/group/list.html:8 +#: aleksis/core/templates/core/group/list.html:9 +#: aleksis/core/templates/core/person/full.html:152 +msgid "Groups" +msgstr "Gruppen" + #: aleksis/core/data_checks.py:55 msgid "Ignore problem" msgstr "Problem ignorieren" @@ -85,161 +92,148 @@ msgstr "Berechtigung" msgid "Content type" msgstr "Inhaltstyp" -#: aleksis/core/filters.py:112 aleksis/core/models.py:579 +#: aleksis/core/filters.py:112 aleksis/core/models.py:581 msgid "User" msgstr "Benutzer" -#: aleksis/core/filters.py:134 aleksis/core/models.py:411 +#: aleksis/core/filters.py:134 aleksis/core/models.py:413 msgid "Group" msgstr "Gruppe" -#: aleksis/core/forms.py:46 aleksis/core/forms.py:514 +#: aleksis/core/forms.py:48 aleksis/core/forms.py:559 msgid "Base data" msgstr "Basisdaten" -#: aleksis/core/forms.py:52 +#: aleksis/core/forms.py:54 msgid "Address" msgstr "Adresse" -#: aleksis/core/forms.py:53 +#: aleksis/core/forms.py:55 aleksis/core/forms.py:568 msgid "Contact data" msgstr "Kontaktdaten" -#: aleksis/core/forms.py:55 +#: aleksis/core/forms.py:57 msgid "Advanced personal data" msgstr "Zusätzliche persönliche Daten" -#: aleksis/core/forms.py:103 +#: aleksis/core/forms.py:105 msgid "New user" msgstr "Neuer Benutzer" -#: aleksis/core/forms.py:103 +#: aleksis/core/forms.py:105 msgid "Create a new account" msgstr "Neues Benutzerkonto erstellen" -#: aleksis/core/forms.py:134 +#: aleksis/core/forms.py:136 msgid "You cannot set a new username when also selecting an existing user." msgstr "Sie können keine neuen Benutzer erstellen, wenn Sie gleichzeitig einen existierenden Benutzer auswählen." -#: aleksis/core/forms.py:138 +#: aleksis/core/forms.py:140 msgid "This username is already in use." msgstr "Dieser Benutzername wird bereits genutzt." -#: aleksis/core/forms.py:155 aleksis/core/models.py:125 +#: aleksis/core/forms.py:157 aleksis/core/models.py:129 msgid "School term" msgstr "Schuljahr" -#: aleksis/core/forms.py:156 +#: aleksis/core/forms.py:158 msgid "Common data" msgstr "Allgemeine Daten" -#: aleksis/core/forms.py:157 aleksis/core/forms.py:208 -#: aleksis/core/menus.py:256 aleksis/core/models.py:148 +#: aleksis/core/forms.py:159 aleksis/core/forms.py:210 +#: aleksis/core/menus.py:254 aleksis/core/models.py:152 #: aleksis/core/templates/core/person/list.html:8 #: aleksis/core/templates/core/person/list.html:9 msgid "Persons" msgstr "Personen" -#: aleksis/core/forms.py:158 +#: aleksis/core/forms.py:160 aleksis/core/forms.py:570 msgid "Additional data" msgstr "Zusätzliche Datne" -#: aleksis/core/forms.py:200 aleksis/core/forms.py:203 -#: aleksis/core/models.py:68 +#: aleksis/core/forms.py:202 aleksis/core/forms.py:205 +#: aleksis/core/models.py:72 msgid "Date" msgstr "Datum" -#: aleksis/core/forms.py:201 aleksis/core/forms.py:204 -#: aleksis/core/models.py:76 +#: aleksis/core/forms.py:203 aleksis/core/forms.py:206 +#: aleksis/core/models.py:80 msgid "Time" msgstr "Zeit" -#: aleksis/core/forms.py:221 aleksis/core/menus.py:267 -#: aleksis/core/models.py:412 aleksis/core/templates/core/group/list.html:8 -#: aleksis/core/templates/core/group/list.html:9 -#: aleksis/core/templates/core/person/full.html:145 -msgid "Groups" -msgstr "Gruppen" - -#: aleksis/core/forms.py:234 +#: aleksis/core/forms.py:236 msgid "From when until when should the announcement be displayed?" msgstr "Von wann bis wann soll die Ankündigung angezeigt werden?" -#: aleksis/core/forms.py:237 +#: aleksis/core/forms.py:239 msgid "Who should see the announcement?" msgstr "Wer soll die Ankündigung sehen?" -#: aleksis/core/forms.py:238 +#: aleksis/core/forms.py:240 msgid "Write your announcement:" msgstr "Schreiben Sie ihre Ankündigung:" -#: aleksis/core/forms.py:277 +#: aleksis/core/forms.py:279 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." -#: aleksis/core/forms.py:281 +#: aleksis/core/forms.py:283 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." -#: aleksis/core/forms.py:290 +#: aleksis/core/forms.py:292 msgid "You need at least one recipient." msgstr "Sie benötigen mindestens einen Empfänger." -#: aleksis/core/forms.py:411 +#: aleksis/core/forms.py:401 +msgid "Invitation code" +msgstr "Einladungscode" + +#: aleksis/core/forms.py:402 +msgid "Please enter your invitation code." +msgstr "Bitte geben Sie Ihren Einladungscode ein." + +#: aleksis/core/forms.py:434 msgid "Who should get the permission?" msgstr "Wer soll die Berechtigung erhalten?" -#: aleksis/core/forms.py:412 +#: aleksis/core/forms.py:435 msgid "On what?" msgstr "Auf was?" -#: aleksis/core/forms.py:438 +#: aleksis/core/forms.py:461 msgid "Select objects which the permission should be granted for:" -msgstr "" -"Wählen Sie die Objekte aus, für welche die Berechtigung vergeben werden soll:" +msgstr "Wählen Sie die Objekte aus, für welche die Berechtigung vergeben werden soll:" -#: aleksis/core/forms.py:441 +#: aleksis/core/forms.py:464 msgid "Grant the permission for all objects" msgstr "Vergebe die Berechtigung für alle Objekte" -#: aleksis/core/forms.py:449 +#: aleksis/core/forms.py:472 msgid "You must select at least one group or person which should get the permission." -msgstr "" -"Sie müssen mindestens eine Gruppe oder Person auswählen, welche die " -"Berechtigung erhalten soll." +msgstr "Sie müssen mindestens eine Gruppe oder Person auswählen, welche die Berechtigung erhalten soll." -#: aleksis/core/forms.py:454 +#: aleksis/core/forms.py:477 msgid "You must grant the permission to all objects and/or to some objects." -msgstr "" -"Sie müssen die Berechtigung auf alle Objekte und/oder für einige Objekte " -"vergeben." +msgstr "Sie müssen die Berechtigung auf alle Objekte und/oder für einige Objekte vergeben." -#: aleksis/core/forms.py:518 +#: aleksis/core/forms.py:564 +msgid "Adress data" +msgstr "Adressdaten" + +#: aleksis/core/forms.py:576 msgid "Account data" msgstr "Kontodaten" -#: aleksis/core/forms.py:524 -msgid "Consents" -msgstr "Zustimmungen" - -#: aleksis/core/forms.py:531 +#: aleksis/core/forms.py:583 msgid "Password" msgstr "Passwort" -#: aleksis/core/forms.py:537 +#: aleksis/core/forms.py:586 msgid "Password (again)" msgstr "Passwort wiederholen" -#: aleksis/core/forms.py:550 -#, python-brace-format -msgid "I have read the <a href='{privacy_policy}'>Privacy policy</a> and agree with them." -msgstr "Ich habe die <a href='{privacy_policy}'>Datenschutzerklärung</a> gelesen und stimme ihr zu." - -#: aleksis/core/forms.py:575 -msgid "You must type the same password each time." -msgstr "Sie müssen zweimal das gleiche Passwort eingeben." - -#: aleksis/core/forms.py:720 +#: aleksis/core/forms.py:752 msgid "No valid selection." msgstr "Keine gültige Auswahl." @@ -247,24 +241,20 @@ msgstr "Keine gültige Auswahl." msgid "There are unresolved data problems." msgstr "Es gibt ungelöste Datenprobleme." -#: aleksis/core/health_checks.py:38 -msgid "The backup folder doesn't exist." -msgstr "Der Backup-Ordner existiert nicht." - -#: aleksis/core/health_checks.py:47 +#: aleksis/core/health_checks.py:44 #, python-brace-format msgid "Last backup {time_gone_since_backup}!" msgstr "Letztes Backup: {time_gone_since_backup}!" -#: aleksis/core/health_checks.py:49 +#: aleksis/core/health_checks.py:46 msgid "No backup found!" msgstr "Kein Backup gefunden!" -#: aleksis/core/health_checks.py:76 +#: aleksis/core/health_checks.py:73 msgid "No backup result found!" msgstr "Kein Backupergebnis gefunden!" -#: aleksis/core/health_checks.py:78 +#: aleksis/core/health_checks.py:75 #, python-brace-format msgid "{task.status} - {task.result}" msgstr "{task.status} - {task.result}" @@ -280,34 +270,38 @@ msgstr "Anmelden" msgid "Sign up" msgstr "Registrieren" -#: aleksis/core/menus.py:24 +#: aleksis/core/menus.py:24 aleksis/core/templates/invitations/enter.html:7 +msgid "Accept invitation" +msgstr "Einladung akzeptieren" + +#: aleksis/core/menus.py:33 msgid "Dashboard" msgstr "Dashboard" -#: aleksis/core/menus.py:32 aleksis/core/models.py:625 -#: aleksis/core/preferences.py:27 +#: aleksis/core/menus.py:41 aleksis/core/models.py:627 +#: aleksis/core/preferences.py:28 #: aleksis/core/templates/core/notifications.html:4 #: aleksis/core/templates/core/notifications.html:5 msgid "Notifications" msgstr "Benachrichtigungen" -#: aleksis/core/menus.py:44 +#: aleksis/core/menus.py:53 msgid "Account" msgstr "Konto" -#: aleksis/core/menus.py:51 +#: aleksis/core/menus.py:60 msgid "Stop impersonation" msgstr "Verkleidung beenden" -#: aleksis/core/menus.py:60 aleksis/core/templates/core/base.html:80 +#: aleksis/core/menus.py:69 aleksis/core/templates/core/base.html:80 msgid "Logout" msgstr "Abmelden" -#: aleksis/core/menus.py:66 +#: aleksis/core/menus.py:75 msgid "2FA" msgstr "2FA" -#: aleksis/core/menus.py:74 +#: aleksis/core/menus.py:83 #: aleksis/core/templates/account/password_change.html:5 #: aleksis/core/templates/account/password_change.html:6 #: aleksis/core/templates/account/password_change.html:19 @@ -319,830 +313,850 @@ msgstr "2FA" msgid "Change password" msgstr "Passwort ändern" -#: aleksis/core/menus.py:86 +#: aleksis/core/menus.py:95 msgid "Me" msgstr "Ich" -#: aleksis/core/menus.py:95 +#: aleksis/core/menus.py:104 #: aleksis/core/templates/dynamic_preferences/form.html:5 msgid "Preferences" msgstr "Einstellungen" -#: aleksis/core/menus.py:104 +#: aleksis/core/menus.py:113 msgid "Third-party accounts" msgstr "Drittanbieter-Konten" -#: aleksis/core/menus.py:113 +#: aleksis/core/menus.py:122 #: aleksis/core/templates/oauth2_provider/authorized-tokens.html:5 #: aleksis/core/templates/oauth2_provider/authorized-tokens.html:6 msgid "Authorized applications" msgstr "Autorisierte Anwendungen" -#: aleksis/core/menus.py:124 +#: aleksis/core/menus.py:133 msgid "Admin" msgstr "Admin" -#: aleksis/core/menus.py:132 aleksis/core/models.py:725 +#: aleksis/core/menus.py:141 aleksis/core/models.py:727 #: aleksis/core/templates/core/announcement/list.html:7 #: aleksis/core/templates/core/announcement/list.html:8 msgid "Announcements" msgstr "Ankündigungen" -#: aleksis/core/menus.py:143 aleksis/core/models.py:126 +#: aleksis/core/menus.py:152 aleksis/core/models.py:130 #: aleksis/core/templates/core/school_term/list.html:8 #: aleksis/core/templates/core/school_term/list.html:9 msgid "School terms" msgstr "Schuljahre" -#: aleksis/core/menus.py:154 +#: aleksis/core/menus.py:163 #: aleksis/core/templates/core/dashboard_widget/list.html:8 #: aleksis/core/templates/core/dashboard_widget/list.html:9 msgid "Dashboard widgets" msgstr "Dashboard-Widgets" -#: aleksis/core/menus.py:165 +#: aleksis/core/menus.py:174 #: aleksis/core/templates/core/management/data_management.html:6 #: aleksis/core/templates/core/management/data_management.html:7 msgid "Data management" msgstr "Datenverwaltung" -#: aleksis/core/menus.py:176 +#: aleksis/core/menus.py:185 #: aleksis/core/templates/core/pages/system_status.html:5 #: aleksis/core/templates/core/pages/system_status.html:7 msgid "System status" msgstr "Systemstatus" -#: aleksis/core/menus.py:187 -msgid "Impersonation" -msgstr "Verkleidung" - -#: aleksis/core/menus.py:198 +#: aleksis/core/menus.py:196 msgid "Configuration" msgstr "Konfiguration" -#: aleksis/core/menus.py:209 aleksis/core/templates/core/data_check/list.html:9 +#: aleksis/core/menus.py:207 aleksis/core/templates/core/data_check/list.html:9 #: aleksis/core/templates/core/data_check/list.html:10 msgid "Data checks" msgstr "Datenprüfungen" -#: aleksis/core/menus.py:215 aleksis/core/templates/core/perms/list.html:13 +#: aleksis/core/menus.py:213 aleksis/core/templates/core/perms/list.html:13 #: aleksis/core/templates/core/perms/list.html:14 msgid "Manage permissions" msgstr "Berechtigungen verwalten" -#: aleksis/core/menus.py:226 +#: aleksis/core/menus.py:224 msgid "Backend Admin" msgstr "Backend-Administration" -#: aleksis/core/menus.py:234 +#: aleksis/core/menus.py:232 #: aleksis/core/templates/oauth2_provider/application/list.html:5 #: aleksis/core/templates/oauth2_provider/application/list.html:6 msgid "OAuth2 Applications" msgstr "OAuth2-Anwendungen" -#: aleksis/core/menus.py:247 +#: aleksis/core/menus.py:245 msgid "People" msgstr "Leute" -#: aleksis/core/menus.py:278 aleksis/core/models.py:979 +#: aleksis/core/menus.py:276 aleksis/core/models.py:981 #: aleksis/core/templates/core/group_type/list.html:8 #: aleksis/core/templates/core/group_type/list.html:9 msgid "Group types" msgstr "Gruppentypen" -#: aleksis/core/menus.py:289 +#: aleksis/core/menus.py:287 msgid "Groups and child groups" msgstr "Gruppen und Kindgruppen" -#: aleksis/core/menus.py:300 aleksis/core/models.py:460 +#: aleksis/core/menus.py:298 aleksis/core/models.py:462 #: aleksis/core/templates/core/additional_field/list.html:8 #: aleksis/core/templates/core/additional_field/list.html:9 msgid "Additional fields" msgstr "Zusätzliche Felder" -#: aleksis/core/menus.py:315 +#: aleksis/core/menus.py:309 +msgid "Invite person" +msgstr "Person einladen" + +#: aleksis/core/menus.py:322 #: aleksis/core/templates/core/group/child_groups.html:7 #: aleksis/core/templates/core/group/child_groups.html:9 msgid "Assign child groups to groups" msgstr "Kindgruppen zu Gruppen zuordnen" -#: aleksis/core/mixins.py:508 +#: aleksis/core/mixins.py:511 msgid "Linked school term" msgstr "Zugeordnetes Schuljahr" -#: aleksis/core/models.py:66 +#: aleksis/core/models.py:70 msgid "Boolean (Yes/No)" msgstr "Boolean (Ja/Nein)" -#: aleksis/core/models.py:67 +#: aleksis/core/models.py:71 msgid "Text (one line)" msgstr "Text (eine Zeile)" -#: aleksis/core/models.py:69 +#: aleksis/core/models.py:73 msgid "Date and time" msgstr "Datum und Uhrzeit" -#: aleksis/core/models.py:70 +#: aleksis/core/models.py:74 msgid "Decimal number" msgstr "Dezimalzahl" -#: aleksis/core/models.py:71 aleksis/core/models.py:194 +#: aleksis/core/models.py:75 aleksis/core/models.py:198 msgid "E-mail address" msgstr "E-Mail-Adresse" -#: aleksis/core/models.py:72 +#: aleksis/core/models.py:76 msgid "Integer" msgstr "Ganze Zahl" -#: aleksis/core/models.py:73 +#: aleksis/core/models.py:77 msgid "IP address" msgstr "IP-Adresse" -#: aleksis/core/models.py:74 +#: aleksis/core/models.py:78 msgid "Boolean or empty (Yes/No/Neither)" msgstr "Boolean oder leer (Ja/Nein/weder)" -#: aleksis/core/models.py:75 +#: aleksis/core/models.py:79 msgid "Text (multi-line)" msgstr "Text (mehrzeilig)" -#: aleksis/core/models.py:77 +#: aleksis/core/models.py:81 msgid "URL / Link" msgstr "URL / Link" -#: aleksis/core/models.py:89 aleksis/core/models.py:948 +#: aleksis/core/models.py:93 aleksis/core/models.py:950 msgid "Name" msgstr "Name" -#: aleksis/core/models.py:91 +#: aleksis/core/models.py:95 msgid "Start date" msgstr "Startdatum" -#: aleksis/core/models.py:92 +#: aleksis/core/models.py:96 msgid "End date" msgstr "Enddatum" -#: aleksis/core/models.py:111 +#: aleksis/core/models.py:115 msgid "The start date must be earlier than the end date." msgstr "Das Startdatum muss vor dem Enddatum liegen." -#: aleksis/core/models.py:118 +#: aleksis/core/models.py:122 msgid "There is already a school term for this time or a part of this time." msgstr "Es gibt bereits ein Schuljahr für diesen Zeitraum oder einen Teilzeitraum." -#: aleksis/core/models.py:147 aleksis/core/models.py:897 +#: aleksis/core/models.py:151 aleksis/core/models.py:899 msgid "Person" msgstr "Person" -#: aleksis/core/models.py:150 +#: aleksis/core/models.py:154 msgid "Can view address" msgstr "Kann Adresse sehen" -#: aleksis/core/models.py:151 +#: aleksis/core/models.py:155 msgid "Can view contact details" msgstr "Kann Kontaktdetails sehen" -#: aleksis/core/models.py:152 +#: aleksis/core/models.py:156 msgid "Can view photo" msgstr "Kann Foto sehen" -#: aleksis/core/models.py:153 +#: aleksis/core/models.py:157 msgid "Can view persons groups" msgstr "Kann Gruppen einer Person sehen" -#: aleksis/core/models.py:154 +#: aleksis/core/models.py:158 msgid "Can view personal details" msgstr "Kann persönliche Daten sehen" -#: aleksis/core/models.py:164 +#: aleksis/core/models.py:168 msgid "female" msgstr "weiblich" -#: aleksis/core/models.py:164 +#: aleksis/core/models.py:168 msgid "male" msgstr "männlich" -#: aleksis/core/models.py:172 +#: aleksis/core/models.py:176 aleksis/core/models.py:1144 msgid "Linked user" msgstr "Verknüpfter Benutzer" -#: aleksis/core/models.py:174 +#: aleksis/core/models.py:178 msgid "Is person active?" msgstr "Ist die Person aktiv?" -#: aleksis/core/models.py:176 +#: aleksis/core/models.py:180 msgid "First name" msgstr "Vorname" -#: aleksis/core/models.py:177 +#: aleksis/core/models.py:181 msgid "Last name" msgstr "Nachname" -#: aleksis/core/models.py:179 +#: aleksis/core/models.py:183 msgid "Additional name(s)" msgstr "Zusätzliche Namen" -#: aleksis/core/models.py:183 aleksis/core/models.py:429 +#: aleksis/core/models.py:187 aleksis/core/models.py:431 msgid "Short name" msgstr "Kurzname" -#: aleksis/core/models.py:186 +#: aleksis/core/models.py:190 msgid "Street" msgstr "Straße" -#: aleksis/core/models.py:187 +#: aleksis/core/models.py:191 msgid "Street number" msgstr "Hausnummer" -#: aleksis/core/models.py:188 +#: aleksis/core/models.py:192 msgid "Postal code" msgstr "Postleitzahl" -#: aleksis/core/models.py:189 +#: aleksis/core/models.py:193 msgid "Place" msgstr "Ort" -#: aleksis/core/models.py:191 +#: aleksis/core/models.py:195 msgid "Home phone" msgstr "Festnetz" -#: aleksis/core/models.py:192 +#: aleksis/core/models.py:196 msgid "Mobile phone" msgstr "Handy" -#: aleksis/core/models.py:196 +#: aleksis/core/models.py:200 msgid "Date of birth" msgstr "Geburtsdatum" -#: aleksis/core/models.py:198 +#: aleksis/core/models.py:201 msgid "Place of birth" msgstr "Geburtsort" -#: aleksis/core/models.py:200 +#: aleksis/core/models.py:202 msgid "Sex" msgstr "Geschlecht" -#: aleksis/core/models.py:202 +#: aleksis/core/models.py:204 msgid "Photo" msgstr "Foto" -#: aleksis/core/models.py:206 aleksis/core/templates/core/person/full.html:138 +#: aleksis/core/models.py:208 aleksis/core/templates/core/person/full.html:145 msgid "Guardians / Parents" msgstr "Erziehungsberechtigte / Eltern" -#: aleksis/core/models.py:213 +#: aleksis/core/models.py:215 msgid "Primary group" msgstr "Primärgruppe" -#: aleksis/core/models.py:216 aleksis/core/models.py:583 -#: aleksis/core/models.py:607 aleksis/core/models.py:692 -#: aleksis/core/models.py:972 aleksis/core/templates/core/person/full.html:121 +#: aleksis/core/models.py:218 aleksis/core/models.py:585 +#: aleksis/core/models.py:609 aleksis/core/models.py:694 +#: aleksis/core/models.py:974 aleksis/core/templates/core/person/full.html:128 msgid "Description" msgstr "Beschreibung" -#: aleksis/core/models.py:384 +#: aleksis/core/models.py:386 msgid "Title of field" msgstr "Feldtitel" -#: aleksis/core/models.py:386 +#: aleksis/core/models.py:388 msgid "Type of field" msgstr "Feldtyp" -#: aleksis/core/models.py:393 +#: aleksis/core/models.py:395 msgid "Addtitional field for groups" msgstr "Zusätzliche Felder für Gruppen" -#: aleksis/core/models.py:394 +#: aleksis/core/models.py:396 msgid "Addtitional fields for groups" msgstr "Zusätzliche Felder für Gruppen" -#: aleksis/core/models.py:414 +#: aleksis/core/models.py:416 msgid "Can assign child groups to groups" msgstr "Kann Kindgruppen zu Gruppen zuordnen" -#: aleksis/core/models.py:415 +#: aleksis/core/models.py:417 msgid "Can view statistics about group." msgstr "Kann Statistiken über Gruppen sehen." -#: aleksis/core/models.py:427 +#: aleksis/core/models.py:429 msgid "Long name" msgstr "Langname" -#: aleksis/core/models.py:437 aleksis/core/templates/core/group/full.html:85 +#: aleksis/core/models.py:439 aleksis/core/templates/core/group/full.html:85 msgid "Members" msgstr "Mitglieder" -#: aleksis/core/models.py:440 aleksis/core/templates/core/group/full.html:82 +#: aleksis/core/models.py:442 aleksis/core/templates/core/group/full.html:82 msgid "Owners" msgstr "Leiter/-innen" -#: aleksis/core/models.py:447 aleksis/core/templates/core/group/full.html:55 +#: aleksis/core/models.py:449 aleksis/core/templates/core/group/full.html:55 msgid "Parent groups" msgstr "Übergeordnete Gruppen" -#: aleksis/core/models.py:455 +#: aleksis/core/models.py:457 msgid "Type of group" msgstr "Gruppentyp" -#: aleksis/core/models.py:582 aleksis/core/models.py:606 -#: aleksis/core/models.py:691 +#: aleksis/core/models.py:584 aleksis/core/models.py:608 +#: aleksis/core/models.py:693 #: aleksis/core/templates/core/announcement/list.html:18 msgid "Title" msgstr "Titel" -#: aleksis/core/models.py:585 +#: aleksis/core/models.py:587 msgid "Application" msgstr "Anwendung" -#: aleksis/core/models.py:591 +#: aleksis/core/models.py:593 msgid "Activity" msgstr "Aktivität" -#: aleksis/core/models.py:592 +#: aleksis/core/models.py:594 msgid "Activities" msgstr "Aktivitäten" -#: aleksis/core/models.py:598 +#: aleksis/core/models.py:600 msgid "Sender" msgstr "Absender" -#: aleksis/core/models.py:603 +#: aleksis/core/models.py:605 msgid "Recipient" msgstr "Empfänger" -#: aleksis/core/models.py:608 aleksis/core/models.py:949 +#: aleksis/core/models.py:610 aleksis/core/models.py:951 msgid "Link" msgstr "Link" -#: aleksis/core/models.py:610 +#: aleksis/core/models.py:612 msgid "Read" msgstr "Gelesen" -#: aleksis/core/models.py:611 +#: aleksis/core/models.py:613 msgid "Sent" msgstr "Versandt" -#: aleksis/core/models.py:624 +#: aleksis/core/models.py:626 msgid "Notification" msgstr "Benachrichtigung" -#: aleksis/core/models.py:693 +#: aleksis/core/models.py:695 msgid "Link to detailed view" msgstr "Link zur detaillierten Ansicht" -#: aleksis/core/models.py:696 +#: aleksis/core/models.py:698 msgid "Date and time from when to show" msgstr "Datum und Uhrzeit des Anzeigestarts" -#: aleksis/core/models.py:699 +#: aleksis/core/models.py:701 msgid "Date and time until when to show" msgstr "Anzeigezeitraum" -#: aleksis/core/models.py:724 +#: aleksis/core/models.py:726 msgid "Announcement" msgstr "Ankündigung" -#: aleksis/core/models.py:762 +#: aleksis/core/models.py:764 msgid "Announcement recipient" msgstr "Empfänger der Ankündigung" -#: aleksis/core/models.py:763 +#: aleksis/core/models.py:765 msgid "Announcement recipients" msgstr "Empfänger der Ankündigung" -#: aleksis/core/models.py:818 +#: aleksis/core/models.py:820 msgid "Widget Title" msgstr "Widget-Titel" -#: aleksis/core/models.py:819 +#: aleksis/core/models.py:821 msgid "Activate Widget" msgstr "Widget aktivieren" -#: aleksis/core/models.py:820 +#: aleksis/core/models.py:822 msgid "Widget is broken" msgstr "Widget ist kaputt" -#: aleksis/core/models.py:823 +#: aleksis/core/models.py:825 msgid "Size on mobile devices" msgstr "Größe auf Mobilgeräten" -#: aleksis/core/models.py:824 +#: aleksis/core/models.py:826 msgid "<= 600 px, 12 columns" msgstr "<= 600 px, 12 Spalten" -#: aleksis/core/models.py:829 +#: aleksis/core/models.py:831 msgid "Size on tablet devices" msgstr "Größe auf Tablets" -#: aleksis/core/models.py:830 +#: aleksis/core/models.py:832 msgid "> 600 px, 12 columns" msgstr "> 600px, 12 Spalten" -#: aleksis/core/models.py:835 +#: aleksis/core/models.py:837 msgid "Size on desktop devices" msgstr "Größe auf Desktopgeräten" -#: aleksis/core/models.py:836 +#: aleksis/core/models.py:838 msgid "> 992 px, 12 columns" msgstr "> 992 px, 12 Spalten" -#: aleksis/core/models.py:841 +#: aleksis/core/models.py:843 msgid "Size on large desktop devices" msgstr "Größe auf großen Desktopgeräten" -#: aleksis/core/models.py:842 +#: aleksis/core/models.py:844 msgid "> 1200 px>, 12 columns" msgstr "> 1200 px, 12 Spalten" -#: aleksis/core/models.py:873 +#: aleksis/core/models.py:875 msgid "Can edit default dashboard" msgstr "Kann Standarddashboard bearbeiten" -#: aleksis/core/models.py:874 +#: aleksis/core/models.py:876 msgid "Dashboard Widget" msgstr "Dashboard-Widget" -#: aleksis/core/models.py:875 +#: aleksis/core/models.py:877 msgid "Dashboard Widgets" msgstr "Dashboard-Widgets" -#: aleksis/core/models.py:881 +#: aleksis/core/models.py:883 msgid "URL" msgstr "URL" -#: aleksis/core/models.py:882 +#: aleksis/core/models.py:884 msgid "Icon URL" msgstr "Symbol-URL" -#: aleksis/core/models.py:888 +#: aleksis/core/models.py:890 msgid "External link widget" msgstr "Externer-Link-Widget" -#: aleksis/core/models.py:889 +#: aleksis/core/models.py:891 msgid "External link widgets" msgstr "Externer-Link-Widgets" -#: aleksis/core/models.py:894 +#: aleksis/core/models.py:896 msgid "Dashboard widget" msgstr "Dashboard-Widget" -#: aleksis/core/models.py:899 +#: aleksis/core/models.py:901 msgid "Order" msgstr "Reihenfolge" -#: aleksis/core/models.py:900 +#: aleksis/core/models.py:902 msgid "Part of the default dashboard" msgstr "Teil des Standarddashboards" -#: aleksis/core/models.py:915 +#: aleksis/core/models.py:917 msgid "Dashboard widget order" msgstr "Reihenfolge der Dashboard-Widgets" -#: aleksis/core/models.py:916 +#: aleksis/core/models.py:918 msgid "Dashboard widget orders" msgstr "Reihenfolgen der Dashboard-Widgets" -#: aleksis/core/models.py:922 +#: aleksis/core/models.py:924 msgid "Menu ID" msgstr "Menü-ID" -#: aleksis/core/models.py:935 +#: aleksis/core/models.py:937 msgid "Custom menu" msgstr "Benutzerdefiniertes Menü" -#: aleksis/core/models.py:936 +#: aleksis/core/models.py:938 msgid "Custom menus" msgstr "Benutzerdefinierte Menüs" -#: aleksis/core/models.py:946 +#: aleksis/core/models.py:948 msgid "Menu" msgstr "Menü" -#: aleksis/core/models.py:950 +#: aleksis/core/models.py:952 msgid "Icon" msgstr "Symbol" -#: aleksis/core/models.py:956 +#: aleksis/core/models.py:958 msgid "Custom menu item" msgstr "Benutzerdefiniertes Menüelement" -#: aleksis/core/models.py:957 +#: aleksis/core/models.py:959 msgid "Custom menu items" msgstr "Benutzerdefinierte Menüelemente" -#: aleksis/core/models.py:971 +#: aleksis/core/models.py:973 msgid "Title of type" msgstr "Titel des Typs" -#: aleksis/core/models.py:978 aleksis/core/templates/core/group/full.html:47 +#: aleksis/core/models.py:980 aleksis/core/templates/core/group/full.html:47 msgid "Group type" msgstr "Gruppentyp" -#: aleksis/core/models.py:992 +#: aleksis/core/models.py:994 msgid "Can view system status" msgstr "Kann Systemstatus sehen" -#: aleksis/core/models.py:993 +#: aleksis/core/models.py:995 msgid "Can manage data" msgstr "Kann Daten verwalten" -#: aleksis/core/models.py:994 +#: aleksis/core/models.py:996 msgid "Can impersonate" msgstr "Kann sich verkleiden" -#: aleksis/core/models.py:995 +#: aleksis/core/models.py:997 msgid "Can use search" msgstr "Kann Suche benutzen" -#: aleksis/core/models.py:996 +#: aleksis/core/models.py:998 msgid "Can change site preferences" msgstr "Kann Konfiguration ändern" -#: aleksis/core/models.py:997 +#: aleksis/core/models.py:999 msgid "Can change person preferences" msgstr "Kann Einstellungen einer Person verändern" -#: aleksis/core/models.py:998 +#: aleksis/core/models.py:1000 msgid "Can change group preferences" msgstr "Kann Einstellungen einer Gruppe verändern" -#: aleksis/core/models.py:999 +#: aleksis/core/models.py:1001 msgid "Can test PDF generation" msgstr "Kann die PDF-Generierung testen" -#: aleksis/core/models.py:1035 +#: aleksis/core/models.py:1037 msgid "Related data check task" msgstr "Zugehörige Datenprüfungsaufgabe" -#: aleksis/core/models.py:1043 +#: aleksis/core/models.py:1045 msgid "Issue solved" msgstr "Problem gelöst" -#: aleksis/core/models.py:1044 +#: aleksis/core/models.py:1046 msgid "Notification sent" msgstr "Benachrichtigung gesendet" -#: aleksis/core/models.py:1057 +#: aleksis/core/models.py:1059 msgid "Data check result" msgstr "Datenprüfungsergebnis" -#: aleksis/core/models.py:1058 +#: aleksis/core/models.py:1060 msgid "Data check results" msgstr "Datenprüfungsergebnisse" -#: aleksis/core/models.py:1060 +#: aleksis/core/models.py:1062 msgid "Can run data checks" msgstr "Kann Datenprüfungen ausführen" -#: aleksis/core/models.py:1061 +#: aleksis/core/models.py:1063 msgid "Can solve data check problems" msgstr "Kann Datenprüfungsprobleme lösen" -#: aleksis/core/models.py:1076 +#: aleksis/core/models.py:1070 +msgid "E-Mail address" +msgstr "E-Mail-Adresse" + +#: aleksis/core/models.py:1094 msgid "Owner" msgstr "Leiter" -#: aleksis/core/models.py:1080 +#: aleksis/core/models.py:1098 msgid "File expires at" msgstr "Datei abgelaufen am" -#: aleksis/core/models.py:1082 +#: aleksis/core/models.py:1100 msgid "Generated HTML file" msgstr "Generierte HTML-Datei" -#: aleksis/core/models.py:1084 +#: aleksis/core/models.py:1102 msgid "Generated PDF file" msgstr "Generierte PDF-Datei" -#: aleksis/core/models.py:1091 +#: aleksis/core/models.py:1109 msgid "PDF file" msgstr "PDF-Datei" -#: aleksis/core/models.py:1092 +#: aleksis/core/models.py:1110 msgid "PDF files" msgstr "PDF-Dateien" -#: aleksis/core/models.py:1097 +#: aleksis/core/models.py:1115 msgid "Task result" msgstr "Task-Ergebnis" -#: aleksis/core/models.py:1100 +#: aleksis/core/models.py:1118 msgid "Task user" msgstr "Task-Benutzer" -#: aleksis/core/models.py:1112 +#: aleksis/core/models.py:1130 msgid "Task user assignment" msgstr "Task-Benutzer-Zuordnung" -#: aleksis/core/models.py:1113 +#: aleksis/core/models.py:1131 msgid "Task user assignments" msgstr "Task-Benutzer-Zuordnungen" -#: aleksis/core/models.py:1127 +#: aleksis/core/models.py:1147 +msgid "Additional attributes" +msgstr "Zusätzliche Attribute" + +#: aleksis/core/models.py:1185 msgid "Allowed scopes that clients can request" msgstr "Erlaubte Scopes, die ein Client anfordern kann" -#: aleksis/core/preferences.py:23 +#: aleksis/core/preferences.py:24 msgid "General" msgstr "Allgemein" -#: aleksis/core/preferences.py:24 +#: aleksis/core/preferences.py:25 msgid "School" msgstr "Schule" -#: aleksis/core/preferences.py:25 +#: aleksis/core/preferences.py:26 msgid "Theme" msgstr "Theme" -#: aleksis/core/preferences.py:26 +#: aleksis/core/preferences.py:27 msgid "Mail" msgstr "E-Mail" -#: aleksis/core/preferences.py:28 +#: aleksis/core/preferences.py:29 msgid "Footer" msgstr "Fußbereich" -#: aleksis/core/preferences.py:29 +#: aleksis/core/preferences.py:30 msgid "Accounts" msgstr "Konten" -#: aleksis/core/preferences.py:30 +#: aleksis/core/preferences.py:31 msgid "Authentication" msgstr "Authentifizierung" -#: aleksis/core/preferences.py:31 +#: aleksis/core/preferences.py:32 msgid "Internationalisation" msgstr "Internationalisierung" -#: aleksis/core/preferences.py:42 +#: aleksis/core/preferences.py:43 msgid "Site title" msgstr "Seitentitel" -#: aleksis/core/preferences.py:53 +#: aleksis/core/preferences.py:54 msgid "Site description" msgstr "Seitenbeschreibung" -#: aleksis/core/preferences.py:64 +#: aleksis/core/preferences.py:65 msgid "Primary colour" msgstr "Primärfarbe" -#: aleksis/core/preferences.py:76 +#: aleksis/core/preferences.py:77 msgid "Secondary colour" msgstr "Akzentfarbe" -#: aleksis/core/preferences.py:87 +#: aleksis/core/preferences.py:88 msgid "Logo" msgstr "Logo" -#: aleksis/core/preferences.py:97 +#: aleksis/core/preferences.py:98 msgid "Favicon" msgstr "Favicon" -#: aleksis/core/preferences.py:107 +#: aleksis/core/preferences.py:108 msgid "PWA-Icon" msgstr "PWA-Icon" -#: aleksis/core/preferences.py:118 +#: aleksis/core/preferences.py:119 msgid "Mail out name" msgstr "Ausgangsmailname" -#: aleksis/core/preferences.py:129 +#: aleksis/core/preferences.py:130 msgid "Mail out address" msgstr "E-Mail-Ausgangsadresse" -#: aleksis/core/preferences.py:141 +#: aleksis/core/preferences.py:142 msgid "Link to privacy policy" msgstr "Link zur Datenschutzerklärung" -#: aleksis/core/preferences.py:153 +#: aleksis/core/preferences.py:154 msgid "Link to imprint" msgstr "Link zum Impressum" -#: aleksis/core/preferences.py:165 +#: aleksis/core/preferences.py:166 msgid "Name format for addressing" msgstr "Namensformat für Anreden" -#: aleksis/core/preferences.py:181 +#: aleksis/core/preferences.py:182 msgid "Channels to use for notifications" msgstr "Aktivierte Benachrichtungskanäle" -#: aleksis/core/preferences.py:193 +#: aleksis/core/preferences.py:194 msgid "Regular expression to match primary group, e.g. '^Class .*'" msgstr "Regulärer Ausdruck um Primärgruppen zu finden, z. B. '^Class .*'" -#: aleksis/core/preferences.py:204 +#: aleksis/core/preferences.py:205 msgid "Field on person to match primary group against" msgstr "Feld um Primärgruppen zu finden" -#: aleksis/core/preferences.py:216 +#: aleksis/core/preferences.py:217 msgid "Automatically create new persons for new users" msgstr "Erstelle automatisch neue Personen für neue Benutzer" -#: aleksis/core/preferences.py:225 +#: aleksis/core/preferences.py:226 msgid "Automatically link existing persons to new users by their e-mail address" msgstr "Verknüpfe existierende Personen automatisch mit neuen Personen anhand ihrer E-Mail-Adresse" -#: aleksis/core/preferences.py:236 +#: aleksis/core/preferences.py:237 msgid "Display name of the school" msgstr "Sichtbarer Name der Schule" -#: aleksis/core/preferences.py:247 +#: aleksis/core/preferences.py:248 msgid "Official name of the school, e.g. as given by supervisory authority" msgstr "Offizieller Name der Schule, wie er z.B. von der Behörde vorgegeben ist" -#: aleksis/core/preferences.py:255 +#: aleksis/core/preferences.py:256 msgid "Allow users to change their passwords" msgstr "Erlaube Benutzern, ihr Passwort zu ändern" -#: aleksis/core/preferences.py:263 +#: aleksis/core/preferences.py:264 msgid "Enable signup" msgstr "Registrierung aktivieren" -#: aleksis/core/preferences.py:274 +#: aleksis/core/preferences.py:272 +msgid "Enable invitations" +msgstr "Einladungen aktivieren" + +#: aleksis/core/preferences.py:280 +msgid "Length of invite code. (Default 3: abcde-acbde-abcde)" +msgstr "Länge des Einladungscodes. (Standard: 3: abcde-acbde-abcde)" + +#: aleksis/core/preferences.py:288 +msgid "Size of packets. (Default 5: abcde)" +msgstr "Größe der Pakete. (Standard 5: abcde)" + +#: aleksis/core/preferences.py:298 msgid "Allowed Grant Flows for OAuth applications" msgstr "Erlaubte Grant Flows für OAuth-Anwendungen" -#: aleksis/core/preferences.py:287 +#: aleksis/core/preferences.py:311 msgid "Available languages" msgstr "Verfügbare Sprachen" -#: aleksis/core/preferences.py:299 +#: aleksis/core/preferences.py:323 msgid "Send emails if data checks detect problems" msgstr "E-Mails versenden, wenn Datenprüfungen Probleme finden" -#: aleksis/core/preferences.py:310 +#: aleksis/core/preferences.py:334 msgid "Email recipients for data checks problem emails" msgstr "E-Mailempfänger für Datenprüfungsproblem-E-Mails" -#: aleksis/core/preferences.py:321 +#: aleksis/core/preferences.py:345 msgid "Email recipient groups for data checks problem emails" msgstr "E-Mail-Empfängergruppen für Datenprüfungsproblem-E-Mails" -#: aleksis/core/preferences.py:330 +#: aleksis/core/preferences.py:354 msgid "Show dashboard to users without login" msgstr "Zeige Dashboard für Benutzer ohne Login" -#: aleksis/core/preferences.py:339 +#: aleksis/core/preferences.py:363 msgid "Allow users to edit their dashboard" msgstr "Erlaube Benutzern, ihr Dashboard zu bearbeiten" -#: aleksis/core/preferences.py:350 +#: aleksis/core/preferences.py:374 msgid "Fields on person model which are editable by themselves." msgstr "Felder des Personen-Models welche von ihnen selbst editierbar sind." -#: aleksis/core/preferences.py:364 +#: aleksis/core/preferences.py:388 msgid "Editable fields on person model which should trigger a notification on change" msgstr "Editierbare Felder des Personen-Models welche eine Benachrichtigung für Änderungen auslösen soll" -#: aleksis/core/preferences.py:377 +#: aleksis/core/preferences.py:401 msgid "Contact for notification if a person changes their data" msgstr "Kontakt für Benachrichtigung, wenn eine Person ihre Daten ändert" -#: aleksis/core/preferences.py:387 +#: aleksis/core/preferences.py:411 msgid "PDF file expiration duration" msgstr "PDF-Datei-Ablaufdauer" -#: aleksis/core/preferences.py:388 +#: aleksis/core/preferences.py:412 msgid "in minutes" msgstr "in Minuten" -#: aleksis/core/preferences.py:398 +#: aleksis/core/preferences.py:422 msgid "Automatically update the dashboard and its widgets" msgstr "Automatisch das Dashboard und seine Widgets aktualisieren" -#: aleksis/core/preferences.py:408 +#: aleksis/core/preferences.py:432 msgid "Automatically update the dashboard and its widgets sitewide" msgstr "Automatisch das Dashboard und seine Widgets aktualisieren (auf der ganzen Seite)" -#: aleksis/core/settings.py:474 +#: aleksis/core/settings.py:507 msgid "English" msgstr "Englisch" -#: aleksis/core/settings.py:475 +#: aleksis/core/settings.py:508 msgid "German" msgstr "Deutsch" -#: aleksis/core/tables.py:19 +#: aleksis/core/tables.py:24 #: aleksis/core/templates/core/announcement/list.html:36 #: aleksis/core/templates/core/group/full.html:24 -#: aleksis/core/templates/core/person/full.html:23 +#: aleksis/core/templates/core/person/full.html:24 #: aleksis/core/templates/oauth2_provider/application/detail.html:17 msgid "Edit" msgstr "Bearbeiten" -#: aleksis/core/tables.py:21 aleksis/core/tables.py:89 -#: aleksis/core/tables.py:105 +#: aleksis/core/tables.py:26 aleksis/core/tables.py:94 +#: aleksis/core/tables.py:137 #: aleksis/core/templates/core/announcement/list.html:22 msgid "Actions" msgstr "Aktionen" -#: aleksis/core/tables.py:56 aleksis/core/tables.py:57 -#: aleksis/core/tables.py:71 aleksis/core/tables.py:87 -#: aleksis/core/tables.py:103 +#: aleksis/core/tables.py:61 aleksis/core/tables.py:62 +#: aleksis/core/tables.py:76 aleksis/core/tables.py:92 +#: aleksis/core/tables.py:135 #: aleksis/core/templates/core/announcement/list.html:42 #: aleksis/core/templates/core/group/full.html:31 #: aleksis/core/templates/core/pages/delete.html:22 -#: aleksis/core/templates/core/person/full.html:30 +#: aleksis/core/templates/core/person/full.html:31 #: aleksis/core/templates/oauth2_provider/application/detail.html:21 msgid "Delete" msgstr "Löschen" @@ -1237,11 +1251,11 @@ msgstr "" msgid "Account inactive" msgstr "Konto inaktiv" -#: aleksis/core/templates/account/account_inactive.html:13 +#: aleksis/core/templates/account/account_inactive.html:14 msgid "Account inactive." msgstr "Konto inaktiv." -#: aleksis/core/templates/account/account_inactive.html:15 +#: aleksis/core/templates/account/account_inactive.html:17 msgid "" "\n" " This account is currently inactive. If you think this is an\n" @@ -1417,11 +1431,11 @@ msgstr "Haben Sie bereits ein Konto? Dann <a href=\"%(login_url)s\">melden Sie s msgid "Signup closed" msgstr "Registrierung geschlossen" -#: aleksis/core/templates/account/signup_closed.html:13 +#: aleksis/core/templates/account/signup_closed.html:14 msgid "Signup closed." msgstr "Registrierung geschlossen." -#: aleksis/core/templates/account/signup_closed.html:15 +#: aleksis/core/templates/account/signup_closed.html:17 msgid "" "\n" " This sign up is currently closed. If you think this is an\n" @@ -1472,11 +1486,6 @@ msgstr "" "Bitte kontaktieren Sie uns, wenn Sie diese nicht binnen weniger Minuten erhalten.\n" " " -#: aleksis/core/templates/account/verification_sent.html:30 -#, python-format -msgid "<strong>Note:</strong> you can still <a href=\"%(email_url)s\">change your e-mail address</a>" -msgstr "<strong>Hinweis:</strong> Sie können immer noch <a href=\"%(email_url)s\"> Ihre E-Mail-Adresse ändern</a>" - #: aleksis/core/templates/core/additional_field/edit.html:6 #: aleksis/core/templates/core/additional_field/edit.html:7 msgid "Edit additional field" @@ -1525,11 +1534,11 @@ msgid "Logged in as" msgstr "Angemeldet als" #: aleksis/core/templates/core/base.html:175 -msgid "About AlekSIS — The Free School Information System" -msgstr "Über AlekSIS — The Free School Information System" +msgid "About AlekSIS® — The Free School Information System" +msgstr "Über AlekSIS® — The Free School Information System" #: aleksis/core/templates/core/base.html:183 -msgid "Impress" +msgid "Imprint" msgstr "Impressum" #: aleksis/core/templates/core/base.html:191 @@ -1537,8 +1546,8 @@ msgid "Privacy Policy" msgstr "Datenschutzerklärung" #: aleksis/core/templates/core/base_print.html:72 -msgid "Powered by AlekSIS" -msgstr "Betrieben mit AlekSIS" +msgid "Powered by AlekSIS®" +msgstr "Betrieben mit AlekSIS®" #: aleksis/core/templates/core/dashboard_widget/create.html:8 #: aleksis/core/templates/core/dashboard_widget/create.html:12 @@ -1764,7 +1773,7 @@ msgstr "Zurück" #: aleksis/core/templates/core/group/child_groups.html:134 #: aleksis/core/templates/two_factor/_wizard_actions.html:26 msgid "Next" -msgstr "Weiter" +msgstr "Nächste" #: aleksis/core/templates/core/group/child_groups.html:106 #: aleksis/core/templates/core/group/child_groups.html:141 @@ -1783,7 +1792,7 @@ msgid "Edit group" msgstr "Gruppe editieren" #: aleksis/core/templates/core/group/full.html:38 -#: aleksis/core/templates/core/person/full.html:37 +#: aleksis/core/templates/core/person/full.html:38 msgid "Change preferences" msgstr "Einstellungen ändern" @@ -1876,41 +1885,54 @@ msgid "No notifications available yet." msgstr "Aktuell keine Benachrichtigungen verfügbar." #: aleksis/core/templates/core/pages/about.html:6 +msgid "About AlekSIS®" +msgstr "Über AlekSIS®" + +#: aleksis/core/templates/core/pages/about.html:7 +msgid "AlekSIS® – The Free School Information System" +msgstr "AlekSIS® – The Free School Information System" + #: aleksis/core/templates/core/pages/about.html:15 msgid "About AlekSIS" msgstr "Über AlekSIS" -#: aleksis/core/templates/core/pages/about.html:7 -msgid "AlekSIS – The Free School Information System" -msgstr "AlekSIS – The Free School Information System" - #: aleksis/core/templates/core/pages/about.html:17 msgid "" "\n" -" This platform is powered by AlekSIS, a web-based school information system (SIS) which can be used\n" +" This platform is powered by AlekSIS®, a web-based school information system (SIS) which can be used\n" " to manage and/or publish organisational artifacts of educational institutions. AlekSIS is free software and\n" " can be used by anyone.\n" " " msgstr "" "\n" -" Diese Plattform wird mit AlekSIS, einem webbasierten Schulinformationssystem (SIS), \n" +" Diese Plattform wird mit AlekSIS®, einem webbasierten Schulinformationssystem (SIS), \n" "welches für die Verwaltung und/oder Veröffentlichung von Bildungseinrichtungen verwendet werden kann.\n" "AlekSIS ist freie Software und kann von jedem benutzt werden.\n" " " -#: aleksis/core/templates/core/pages/about.html:25 +#: aleksis/core/templates/core/pages/about.html:24 +msgid "" +"\n" +" AlekSIS® is a registered trademark of the AlekSIS open source project, represented by Teckids e.V.\n" +" " +msgstr "" +"\n" +" AlekSIS® ist eine eingetragene Wortmarke des Open-Source-Projektes AlekSIS, vertreten durch den Teckids e.V.\n" +" " + +#: aleksis/core/templates/core/pages/about.html:30 msgid "Website of AlekSIS" msgstr "Website von AlekSIS" -#: aleksis/core/templates/core/pages/about.html:26 +#: aleksis/core/templates/core/pages/about.html:31 msgid "Source code" msgstr "Quellcode" -#: aleksis/core/templates/core/pages/about.html:35 +#: aleksis/core/templates/core/pages/about.html:40 msgid "Licence information" msgstr "Lizenzinformationen" -#: aleksis/core/templates/core/pages/about.html:37 +#: aleksis/core/templates/core/pages/about.html:42 msgid "" "\n" " The core and the official apps of AlekSIS are licenced under the EUPL, version 1.2 or later. For licence\n" @@ -1924,23 +1946,23 @@ msgstr "" "sind wie folgt markiert:\n" " " -#: aleksis/core/templates/core/pages/about.html:45 +#: aleksis/core/templates/core/pages/about.html:50 msgid "Free/Open Source Licence" msgstr "Freie/Open Source Lizenz" -#: aleksis/core/templates/core/pages/about.html:46 +#: aleksis/core/templates/core/pages/about.html:51 msgid "Other Licence" msgstr "Andere Lizenz" -#: aleksis/core/templates/core/pages/about.html:50 +#: aleksis/core/templates/core/pages/about.html:55 msgid "Full licence text" msgstr "Kompletter Lizenztext" -#: aleksis/core/templates/core/pages/about.html:51 +#: aleksis/core/templates/core/pages/about.html:56 msgid "More information about the EUPL" msgstr "Weitere Informationen über die EUPL" -#: aleksis/core/templates/core/pages/about.html:90 +#: aleksis/core/templates/core/pages/about.html:95 #, python-format msgid "" "\n" @@ -2220,17 +2242,19 @@ msgstr "Person erstellen" msgid "Edit person" msgstr "Person editieren" -#: aleksis/core/templates/core/person/full.html:44 -#: aleksis/core/templates/impersonate/list_users.html:7 -#: aleksis/core/templates/impersonate/list_users.html:8 +#: aleksis/core/templates/core/person/full.html:45 msgid "Impersonate" msgstr "Verkleiden" -#: aleksis/core/templates/core/person/full.html:50 +#: aleksis/core/templates/core/person/full.html:51 +msgid "Invite user" +msgstr "Benutzer einladen" + +#: aleksis/core/templates/core/person/full.html:57 msgid "Contact details" msgstr "Kontaktdetails" -#: aleksis/core/templates/core/person/full.html:131 +#: aleksis/core/templates/core/person/full.html:138 msgid "Children" msgstr "Kinder" @@ -2270,6 +2294,53 @@ msgstr "Einstellungen für %(instance)s" msgid "Save preferences" msgstr "Einstellungen speichern" +#: aleksis/core/templates/invitations/enter.html:21 +msgid "Accept your invitation" +msgstr "Ihre Einladung akzeptieren" + +#: aleksis/core/templates/invitations/enter.html:25 +msgid "" +"\n" +" Please enter your invitation code to register\n" +" your new user account:\n" +" " +msgstr "" +"\n" +" Bitte geben Sie Ihren Einladungscode ein, \n" +"um Ihr neues Benutzerkonto zu registrieren:\n" +" " + +#: aleksis/core/templates/invitations/enter.html:37 +msgid "Accept invite" +msgstr "Einladung akzeptieren" + +#: aleksis/core/templates/invitations/forms/_invite.html:9 +#: aleksis/core/templates/invitations/forms/_invite.html:10 +#: aleksis/core/templates/invitations/forms/_invite.html:21 +msgid "Invite" +msgstr "Einladen" + +#: aleksis/core/templates/invitations/forms/_invite.html:17 +msgid "Invite by email address" +msgstr "Mit E-Mail-Adresse einladen" + +#: aleksis/core/templates/invitations/forms/_invite.html:26 +msgid "Generate invitation code" +msgstr "Einladungscode generieren" + +#: aleksis/core/templates/invitations/forms/_invite.html:29 +msgid "Generate code" +msgstr "Code generieren" + +#: aleksis/core/templates/invitations/forms/_invite.html:33 +msgid "Invitations" +msgstr "Einladungen" + +#: aleksis/core/templates/invitations/messages/invite_accepted.txt:3 +#, python-format +msgid "The invitation for %(email)s has been accepted." +msgstr "Die Einladung für %(email)s wurde akzeptiert." + #: aleksis/core/templates/oauth2_provider/application/create.html:5 #: aleksis/core/templates/oauth2_provider/application/create.html:6 msgid "Register OAuth2 Application" @@ -3075,151 +3146,187 @@ msgstr "E-Mail" msgid "SMS" msgstr "SMS" -#: aleksis/core/util/pdf.py:105 +#: aleksis/core/util/pdf.py:113 msgid "Progress: Generate PDF file" msgstr "Fortschritt: PDF-Datei generieren" -#: aleksis/core/util/pdf.py:106 +#: aleksis/core/util/pdf.py:114 msgid "Generating PDF file …" msgstr "PDF-Datei wird generiert …" -#: aleksis/core/util/pdf.py:107 +#: aleksis/core/util/pdf.py:115 msgid "The PDF file has been generated successfully." msgstr "Die PDF-Datei wurde erfolgreich generiert." -#: aleksis/core/util/pdf.py:108 +#: aleksis/core/util/pdf.py:116 msgid "There was a problem while generating the PDF file." msgstr "Es ist ein Fehler beim Generieren der PDF-Datei aufgetreten." -#: aleksis/core/util/pdf.py:111 +#: aleksis/core/util/pdf.py:119 msgid "Download PDF" msgstr "PDF herunterladen" -#: aleksis/core/views.py:270 +#: aleksis/core/views.py:280 msgid "The school term has been created." msgstr "Das Schuljahr wurde erstellt." -#: aleksis/core/views.py:282 +#: aleksis/core/views.py:292 msgid "The school term has been saved." msgstr "Das Schuljahr wurde gespeichert." -#: aleksis/core/views.py:406 +#: aleksis/core/views.py:416 msgid "The child groups were successfully saved." msgstr "Die Untergruppen wurden gespeichert." -#: aleksis/core/views.py:425 aleksis/core/views.py:435 +#: aleksis/core/views.py:435 aleksis/core/views.py:445 msgid "The person has been saved." msgstr "Die Person wurde gespeichert." -#: aleksis/core/views.py:485 +#: aleksis/core/views.py:495 msgid "The group has been saved." msgstr "Die Gruppe wurde gespeichert." -#: aleksis/core/views.py:582 +#: aleksis/core/views.py:592 msgid "The announcement has been saved." msgstr "Die Ankündigung wurde gespeichert." -#: aleksis/core/views.py:598 +#: aleksis/core/views.py:608 msgid "The announcement has been deleted." msgstr "Ankündigung wurde gelöscht." -#: aleksis/core/views.py:682 +#: aleksis/core/views.py:695 msgid "The preferences have been saved successfully." msgstr "Die Einstellungen wurde gespeichert." -#: aleksis/core/views.py:706 +#: aleksis/core/views.py:719 msgid "The person has been deleted." msgstr "Die Person wurde gelöscht." -#: aleksis/core/views.py:720 +#: aleksis/core/views.py:733 msgid "The group has been deleted." msgstr "Die Gruppe wurde gelöscht." -#: aleksis/core/views.py:752 +#: aleksis/core/views.py:765 msgid "The additional_field has been saved." msgstr "Das zusätzliche Feld wurde gespeichert." -#: aleksis/core/views.py:786 +#: aleksis/core/views.py:799 msgid "The additional field has been deleted." msgstr "Das zusätzliche Feld wurde gelöscht." -#: aleksis/core/views.py:811 +#: aleksis/core/views.py:824 msgid "The group type has been saved." msgstr "Der Gruppentyp wurde gespeichert." -#: aleksis/core/views.py:841 +#: aleksis/core/views.py:854 msgid "The group type has been deleted." msgstr "Der Gruppentyp wurde gelöscht." -#: aleksis/core/views.py:874 +#: aleksis/core/views.py:887 msgid "Progress: Run data checks" msgstr "Fortschritt: Datenprüfungen ausführen" -#: aleksis/core/views.py:875 +#: aleksis/core/views.py:888 msgid "Run data checks …" msgstr "Datenprüfungen laufen …" -#: aleksis/core/views.py:876 +#: aleksis/core/views.py:889 msgid "The data checks were run successfully." msgstr "Die Datenprüfungen wurden erfolgreich ausgeführt." -#: aleksis/core/views.py:877 +#: aleksis/core/views.py:890 msgid "There was a problem while running data checks." msgstr "Es gab ein Problem beim Ausführen der Datenprüfungen." -#: aleksis/core/views.py:893 +#: aleksis/core/views.py:906 #, python-brace-format msgid "The solve option '{solve_option_obj.verbose_name}' " msgstr "Die Lösungsoption \"{solve_option_obj.verbose_name}\" " -#: aleksis/core/views.py:935 +#: aleksis/core/views.py:948 msgid "The dashboard widget has been saved." msgstr "Das Dashboard-Widget wurde gespeichert." -#: aleksis/core/views.py:965 +#: aleksis/core/views.py:978 msgid "The dashboard widget has been created." msgstr "Das Dashboard-Widget wurde erstellt." -#: aleksis/core/views.py:975 +#: aleksis/core/views.py:988 msgid "The dashboard widget has been deleted." msgstr "Das Dashboard-Widget wurde gelöscht." -#: aleksis/core/views.py:1042 +#: aleksis/core/views.py:1055 msgid "Your dashboard configuration has been saved successfully." msgstr "Ihre Dashboardkonfiguration wurde erfolgreich gespeichert." -#: aleksis/core/views.py:1044 +#: aleksis/core/views.py:1057 msgid "The configuration of the default dashboard has been saved successfully." msgstr "Die Konfiguration des Standard-Dashboardes wurde erfolgreich gespeichert." -#: aleksis/core/views.py:1139 +#: aleksis/core/views.py:1127 +#, python-brace-format +msgid "The invitation was successfully created. The invitation code is {code}" +msgstr "Die Einladung wurde erfolgreich erstellt. Der Einladungscode ist {code}" + +#: aleksis/core/views.py:1218 msgid "We have successfully assigned the permissions." msgstr "Wir haben die Berechtigungen erfolgreich zugewiesen." -#: aleksis/core/views.py:1149 +#: aleksis/core/views.py:1228 msgid "The global user permission has been deleted." msgstr "Die globale Benutzerberechtigung wurde gelöscht." -#: aleksis/core/views.py:1159 +#: aleksis/core/views.py:1238 msgid "The global group permission has been deleted." msgstr "Die globale Gruppenberechtigung wurde gelöscht." -#: aleksis/core/views.py:1169 +#: aleksis/core/views.py:1248 msgid "The object user permission has been deleted." msgstr "Die Objekt-Benutzerberechtigung wurde gelöscht." -#: aleksis/core/views.py:1179 +#: aleksis/core/views.py:1258 msgid "The object group permission has been deleted." msgstr "Die Objekt-Gruppenberechtigung wurde gelöscht." -#: aleksis/core/views.py:1298 +#: aleksis/core/views.py:1377 msgid "The third-party account could not be disconnected because it is the only login method available." msgstr "Das Drittanbieter-Konto konnte nicht deaktiviert werden, weil es die einzige verfügbare Anmeldeoption ist." -#: aleksis/core/views.py:1305 +#: aleksis/core/views.py:1384 msgid "The third-party account has been successfully disconnected." msgstr "Das Drittanbieter-Konto wurde erfolgreich getrennt." +#: aleksis/core/views.py:1441 +msgid "Person was invited successfully." +msgstr "Person wurde erfolgreich eingeladen." + +#: aleksis/core/views.py:1443 +msgid "Person was already invited." +msgstr "Person wurde bereits eingeladen." + +#~ msgid "Consents" +#~ msgstr "Zustimmungen" + +#, python-brace-format +#~ msgid "I have read the <a href='{privacy_policy}'>Privacy policy</a> and agree with them." +#~ msgstr "Ich habe die <a href='{privacy_policy}'>Datenschutzerklärung</a> gelesen und stimme ihr zu." + +#~ msgid "You must type the same password each time." +#~ msgstr "Sie müssen zweimal das gleiche Passwort eingeben." + +#~ msgid "Impersonation" +#~ msgstr "Verkleidung" + +#, python-format +#~ msgid "<strong>Note:</strong> you can still <a href=\"%(email_url)s\">change your e-mail address</a>" +#~ msgstr "<strong>Hinweis:</strong> Sie können immer noch <a href=\"%(email_url)s\"> Ihre E-Mail-Adresse ändern</a>" + +#~ msgid "Impress" +#~ msgstr "Impressum" + +#~ msgid "The backup folder doesn't exist." +#~ msgstr "Der Backup-Ordner existiert nicht." + #~ msgid "Can add oauth applications" #~ msgstr "Kann OAuth-Anwendungen hinzufügen" @@ -3281,9 +3388,6 @@ msgstr "Das Drittanbieter-Konto wurde erfolgreich getrennt." #~ msgid "New account" #~ msgstr "Neues Konto" -#~ msgid "Impersonate user" -#~ msgstr "Als Benutzer verkleiden" - #~ msgid "Authorized tokens" #~ msgstr "Autorisierte Tokens" @@ -3548,9 +3652,6 @@ msgstr "Das Drittanbieter-Konto wurde erfolgreich getrennt." #~ msgid "Assorted" #~ msgstr "Unsortiert" -#~ msgid "Administration" -#~ msgstr "Verwaltung" - #~ msgid "List of all groups" #~ msgstr "Liste aller Gruppen" diff --git a/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po b/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po index f104a1ea290e906c7f0e1d5d37aca398a16241e9..188d883c0746a8cb64414091b5e0fa2f8b247805 100644 --- a/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po +++ b/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-29 09:59+0100\n" +"POT-Creation-Date: 2021-12-28 12:14+0100\n" "PO-Revision-Date: 2021-10-28 14:37+0000\n" "Last-Translator: Jonathan Weth <teckids@jonathanweth.de>\n" "Language-Team: German <https://translate.edugit.org/projects/aleksis/aleksis-core-js/de/>\n" @@ -30,6 +30,6 @@ msgstr "Abbrechen" msgid "OK" msgstr "OK" -#: aleksis/core/static/js/main.js:127 +#: aleksis/core/static/js/main.js:128 msgid "This page may contain outdated information since there is no internet connection." msgstr "Diese Seite enthält vielleicht veraltete Informationen, da es keine Internetverbindung gibt." diff --git a/aleksis/core/locale/fr/LC_MESSAGES/django.po b/aleksis/core/locale/fr/LC_MESSAGES/django.po index 785f1ea6d42cdd2a00b6718d02a6ea578fe547fe..48ad0ea73dda60181ae19660fa021259b0f49ab0 100644 --- a/aleksis/core/locale/fr/LC_MESSAGES/django.po +++ b/aleksis/core/locale/fr/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: AlekSIS (School Information System) 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-29 09:59+0100\n" +"POT-Creation-Date: 2021-12-28 12:13+0100\n" "PO-Revision-Date: 2021-06-16 12:00+0000\n" "Last-Translator: Jonathan Weth <teckids@jonathanweth.de>\n" "Language-Team: French <https://translate.edugit.org/projects/aleksis/aleksis/fr/>\n" @@ -18,28 +18,37 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n > 1;\n" "X-Generator: Weblate 4.4\n" -#: aleksis/core/apps.py:151 +#: aleksis/core/apps.py:152 msgid "OpenID Connect scope" msgstr "" -#: aleksis/core/apps.py:152 +#: aleksis/core/apps.py:153 msgid "Given name, family name, link to profile and picture if existing." msgstr "" -#: aleksis/core/apps.py:153 +#: aleksis/core/apps.py:154 msgid "Full home postal address" msgstr "" -#: aleksis/core/apps.py:154 +#: aleksis/core/apps.py:155 #, fuzzy #| msgid "Contact details" msgid "Email address" msgstr "Détails de contact" -#: aleksis/core/apps.py:155 +#: aleksis/core/apps.py:156 msgid "Home and mobile phone" msgstr "" +#: aleksis/core/apps.py:157 aleksis/core/forms.py:223 aleksis/core/menus.py:265 +#: aleksis/core/models.py:414 aleksis/core/templates/core/group/list.html:8 +#: aleksis/core/templates/core/group/list.html:9 +#: aleksis/core/templates/core/person/full.html:152 +#, fuzzy +#| msgid "Group" +msgid "Groups" +msgstr "Groupe" + #: aleksis/core/data_checks.py:55 msgid "Ignore problem" msgstr "" @@ -88,62 +97,62 @@ msgstr "" msgid "Content type" msgstr "" -#: aleksis/core/filters.py:112 aleksis/core/models.py:579 +#: aleksis/core/filters.py:112 aleksis/core/models.py:581 msgid "User" msgstr "" -#: aleksis/core/filters.py:134 aleksis/core/models.py:411 +#: aleksis/core/filters.py:134 aleksis/core/models.py:413 msgid "Group" msgstr "groupe" -#: aleksis/core/forms.py:46 aleksis/core/forms.py:514 +#: aleksis/core/forms.py:48 aleksis/core/forms.py:559 msgid "Base data" msgstr "" -#: aleksis/core/forms.py:52 +#: aleksis/core/forms.py:54 msgid "Address" msgstr "" -#: aleksis/core/forms.py:53 +#: aleksis/core/forms.py:55 aleksis/core/forms.py:568 #, fuzzy #| msgid "Contact details" msgid "Contact data" msgstr "Détails de contact" -#: aleksis/core/forms.py:55 +#: aleksis/core/forms.py:57 #, fuzzy #| msgid "Contact details" msgid "Advanced personal data" msgstr "Détails de contact" -#: aleksis/core/forms.py:103 +#: aleksis/core/forms.py:105 msgid "New user" msgstr "" -#: aleksis/core/forms.py:103 +#: aleksis/core/forms.py:105 msgid "Create a new account" msgstr "" -#: aleksis/core/forms.py:134 +#: aleksis/core/forms.py:136 msgid "You cannot set a new username when also selecting an existing user." msgstr "" -#: aleksis/core/forms.py:138 +#: aleksis/core/forms.py:140 msgid "This username is already in use." msgstr "Cet nom est deja en utilisation." -#: aleksis/core/forms.py:155 aleksis/core/models.py:125 +#: aleksis/core/forms.py:157 aleksis/core/models.py:129 msgid "School term" msgstr "" -#: aleksis/core/forms.py:156 +#: aleksis/core/forms.py:158 #, fuzzy #| msgid "Contact details" msgid "Common data" msgstr "Détails de contact" -#: aleksis/core/forms.py:157 aleksis/core/forms.py:208 -#: aleksis/core/menus.py:256 aleksis/core/models.py:148 +#: aleksis/core/forms.py:159 aleksis/core/forms.py:210 +#: aleksis/core/menus.py:254 aleksis/core/models.py:152 #: aleksis/core/templates/core/person/list.html:8 #: aleksis/core/templates/core/person/list.html:9 #, fuzzy @@ -151,107 +160,97 @@ msgstr "Détails de contact" msgid "Persons" msgstr "Personne" -#: aleksis/core/forms.py:158 +#: aleksis/core/forms.py:160 aleksis/core/forms.py:570 #, fuzzy #| msgid "Contact details" msgid "Additional data" msgstr "Détails de contact" -#: aleksis/core/forms.py:200 aleksis/core/forms.py:203 -#: aleksis/core/models.py:68 +#: aleksis/core/forms.py:202 aleksis/core/forms.py:205 +#: aleksis/core/models.py:72 msgid "Date" msgstr "Date" -#: aleksis/core/forms.py:201 aleksis/core/forms.py:204 -#: aleksis/core/models.py:76 +#: aleksis/core/forms.py:203 aleksis/core/forms.py:206 +#: aleksis/core/models.py:80 msgid "Time" msgstr "" -#: aleksis/core/forms.py:221 aleksis/core/menus.py:267 -#: aleksis/core/models.py:412 aleksis/core/templates/core/group/list.html:8 -#: aleksis/core/templates/core/group/list.html:9 -#: aleksis/core/templates/core/person/full.html:145 -#, fuzzy -#| msgid "Group" -msgid "Groups" -msgstr "Groupe" - -#: aleksis/core/forms.py:234 +#: aleksis/core/forms.py:236 msgid "From when until when should the announcement be displayed?" msgstr "" -#: aleksis/core/forms.py:237 +#: aleksis/core/forms.py:239 msgid "Who should see the announcement?" msgstr "" -#: aleksis/core/forms.py:238 +#: aleksis/core/forms.py:240 msgid "Write your announcement:" msgstr "" -#: aleksis/core/forms.py:277 +#: aleksis/core/forms.py:279 msgid "You are not allowed to create announcements which are only valid in the past." msgstr "" -#: aleksis/core/forms.py:281 +#: aleksis/core/forms.py:283 msgid "The from date and time must be earlier then the until date and time." msgstr "" -#: aleksis/core/forms.py:290 +#: aleksis/core/forms.py:292 msgid "You need at least one recipient." msgstr "" -#: aleksis/core/forms.py:411 +#: aleksis/core/forms.py:401 +msgid "Invitation code" +msgstr "" + +#: aleksis/core/forms.py:402 +msgid "Please enter your invitation code." +msgstr "" + +#: aleksis/core/forms.py:434 msgid "Who should get the permission?" msgstr "" -#: aleksis/core/forms.py:412 +#: aleksis/core/forms.py:435 msgid "On what?" msgstr "" -#: aleksis/core/forms.py:438 +#: aleksis/core/forms.py:461 msgid "Select objects which the permission should be granted for:" msgstr "" -#: aleksis/core/forms.py:441 +#: aleksis/core/forms.py:464 msgid "Grant the permission for all objects" msgstr "" -#: aleksis/core/forms.py:449 +#: aleksis/core/forms.py:472 msgid "You must select at least one group or person which should get the permission." msgstr "" -#: aleksis/core/forms.py:454 +#: aleksis/core/forms.py:477 msgid "You must grant the permission to all objects and/or to some objects." msgstr "" -#: aleksis/core/forms.py:518 +#: aleksis/core/forms.py:564 +msgid "Adress data" +msgstr "" + +#: aleksis/core/forms.py:576 #, fuzzy #| msgid "Contact details" msgid "Account data" msgstr "Détails de contact" -#: aleksis/core/forms.py:524 -msgid "Consents" -msgstr "" - -#: aleksis/core/forms.py:531 +#: aleksis/core/forms.py:583 msgid "Password" msgstr "" -#: aleksis/core/forms.py:537 +#: aleksis/core/forms.py:586 msgid "Password (again)" msgstr "" -#: aleksis/core/forms.py:550 -#, python-brace-format -msgid "I have read the <a href='{privacy_policy}'>Privacy policy</a> and agree with them." -msgstr "" - -#: aleksis/core/forms.py:575 -msgid "You must type the same password each time." -msgstr "" - -#: aleksis/core/forms.py:720 +#: aleksis/core/forms.py:752 msgid "No valid selection." msgstr "" @@ -259,24 +258,20 @@ msgstr "" msgid "There are unresolved data problems." msgstr "" -#: aleksis/core/health_checks.py:38 -msgid "The backup folder doesn't exist." -msgstr "" - -#: aleksis/core/health_checks.py:47 +#: aleksis/core/health_checks.py:44 #, python-brace-format msgid "Last backup {time_gone_since_backup}!" msgstr "" -#: aleksis/core/health_checks.py:49 +#: aleksis/core/health_checks.py:46 msgid "No backup found!" msgstr "" -#: aleksis/core/health_checks.py:76 +#: aleksis/core/health_checks.py:73 msgid "No backup result found!" msgstr "" -#: aleksis/core/health_checks.py:78 +#: aleksis/core/health_checks.py:75 #, python-brace-format msgid "{task.status} - {task.result}" msgstr "" @@ -292,34 +287,38 @@ msgstr "" msgid "Sign up" msgstr "" -#: aleksis/core/menus.py:24 +#: aleksis/core/menus.py:24 aleksis/core/templates/invitations/enter.html:7 +msgid "Accept invitation" +msgstr "" + +#: aleksis/core/menus.py:33 msgid "Dashboard" msgstr "" -#: aleksis/core/menus.py:32 aleksis/core/models.py:625 -#: aleksis/core/preferences.py:27 +#: aleksis/core/menus.py:41 aleksis/core/models.py:627 +#: aleksis/core/preferences.py:28 #: aleksis/core/templates/core/notifications.html:4 #: aleksis/core/templates/core/notifications.html:5 msgid "Notifications" msgstr "" -#: aleksis/core/menus.py:44 +#: aleksis/core/menus.py:53 msgid "Account" msgstr "" -#: aleksis/core/menus.py:51 +#: aleksis/core/menus.py:60 msgid "Stop impersonation" msgstr "" -#: aleksis/core/menus.py:60 aleksis/core/templates/core/base.html:80 +#: aleksis/core/menus.py:69 aleksis/core/templates/core/base.html:80 msgid "Logout" msgstr "" -#: aleksis/core/menus.py:66 +#: aleksis/core/menus.py:75 msgid "2FA" msgstr "" -#: aleksis/core/menus.py:74 +#: aleksis/core/menus.py:83 #: aleksis/core/templates/account/password_change.html:5 #: aleksis/core/templates/account/password_change.html:6 #: aleksis/core/templates/account/password_change.html:19 @@ -331,92 +330,88 @@ msgstr "" msgid "Change password" msgstr "" -#: aleksis/core/menus.py:86 +#: aleksis/core/menus.py:95 msgid "Me" msgstr "" -#: aleksis/core/menus.py:95 +#: aleksis/core/menus.py:104 #: aleksis/core/templates/dynamic_preferences/form.html:5 msgid "Preferences" msgstr "" -#: aleksis/core/menus.py:104 +#: aleksis/core/menus.py:113 msgid "Third-party accounts" msgstr "" -#: aleksis/core/menus.py:113 +#: aleksis/core/menus.py:122 #: aleksis/core/templates/oauth2_provider/authorized-tokens.html:5 #: aleksis/core/templates/oauth2_provider/authorized-tokens.html:6 msgid "Authorized applications" msgstr "" -#: aleksis/core/menus.py:124 +#: aleksis/core/menus.py:133 msgid "Admin" msgstr "" -#: aleksis/core/menus.py:132 aleksis/core/models.py:725 +#: aleksis/core/menus.py:141 aleksis/core/models.py:727 #: aleksis/core/templates/core/announcement/list.html:7 #: aleksis/core/templates/core/announcement/list.html:8 msgid "Announcements" msgstr "" -#: aleksis/core/menus.py:143 aleksis/core/models.py:126 +#: aleksis/core/menus.py:152 aleksis/core/models.py:130 #: aleksis/core/templates/core/school_term/list.html:8 #: aleksis/core/templates/core/school_term/list.html:9 msgid "School terms" msgstr "" -#: aleksis/core/menus.py:154 +#: aleksis/core/menus.py:163 #: aleksis/core/templates/core/dashboard_widget/list.html:8 #: aleksis/core/templates/core/dashboard_widget/list.html:9 msgid "Dashboard widgets" msgstr "" -#: aleksis/core/menus.py:165 +#: aleksis/core/menus.py:174 #: aleksis/core/templates/core/management/data_management.html:6 #: aleksis/core/templates/core/management/data_management.html:7 msgid "Data management" msgstr "" -#: aleksis/core/menus.py:176 +#: aleksis/core/menus.py:185 #: aleksis/core/templates/core/pages/system_status.html:5 #: aleksis/core/templates/core/pages/system_status.html:7 msgid "System status" msgstr "" -#: aleksis/core/menus.py:187 -msgid "Impersonation" -msgstr "" - -#: aleksis/core/menus.py:198 +#: aleksis/core/menus.py:196 msgid "Configuration" msgstr "" -#: aleksis/core/menus.py:209 aleksis/core/templates/core/data_check/list.html:9 +#: aleksis/core/menus.py:207 aleksis/core/templates/core/data_check/list.html:9 #: aleksis/core/templates/core/data_check/list.html:10 msgid "Data checks" msgstr "" -#: aleksis/core/menus.py:215 aleksis/core/templates/core/perms/list.html:13 +#: aleksis/core/menus.py:213 aleksis/core/templates/core/perms/list.html:13 #: aleksis/core/templates/core/perms/list.html:14 msgid "Manage permissions" msgstr "" -#: aleksis/core/menus.py:226 +#: aleksis/core/menus.py:224 msgid "Backend Admin" msgstr "" -#: aleksis/core/menus.py:234 +#: aleksis/core/menus.py:232 #: aleksis/core/templates/oauth2_provider/application/list.html:5 #: aleksis/core/templates/oauth2_provider/application/list.html:6 msgid "OAuth2 Applications" msgstr "" -#: aleksis/core/menus.py:247 +#: aleksis/core/menus.py:245 msgid "People" msgstr "" -#: aleksis/core/menus.py:278 aleksis/core/models.py:979 +#: aleksis/core/menus.py:276 aleksis/core/models.py:981 #: aleksis/core/templates/core/group_type/list.html:8 #: aleksis/core/templates/core/group_type/list.html:9 #, fuzzy @@ -424,775 +419,805 @@ msgstr "" msgid "Group types" msgstr "Groupe" -#: aleksis/core/menus.py:289 +#: aleksis/core/menus.py:287 msgid "Groups and child groups" msgstr "" -#: aleksis/core/menus.py:300 aleksis/core/models.py:460 +#: aleksis/core/menus.py:298 aleksis/core/models.py:462 #: aleksis/core/templates/core/additional_field/list.html:8 #: aleksis/core/templates/core/additional_field/list.html:9 msgid "Additional fields" msgstr "" -#: aleksis/core/menus.py:315 +#: aleksis/core/menus.py:309 +#, fuzzy +#| msgid "Contact details" +msgid "Invite person" +msgstr "Détails de contact" + +#: aleksis/core/menus.py:322 #: aleksis/core/templates/core/group/child_groups.html:7 #: aleksis/core/templates/core/group/child_groups.html:9 msgid "Assign child groups to groups" msgstr "" -#: aleksis/core/mixins.py:508 +#: aleksis/core/mixins.py:511 msgid "Linked school term" msgstr "" -#: aleksis/core/models.py:66 +#: aleksis/core/models.py:70 msgid "Boolean (Yes/No)" msgstr "" -#: aleksis/core/models.py:67 +#: aleksis/core/models.py:71 msgid "Text (one line)" msgstr "" -#: aleksis/core/models.py:69 +#: aleksis/core/models.py:73 msgid "Date and time" msgstr "" -#: aleksis/core/models.py:70 +#: aleksis/core/models.py:74 msgid "Decimal number" msgstr "" -#: aleksis/core/models.py:71 aleksis/core/models.py:194 +#: aleksis/core/models.py:75 aleksis/core/models.py:198 msgid "E-mail address" msgstr "" -#: aleksis/core/models.py:72 +#: aleksis/core/models.py:76 msgid "Integer" msgstr "" -#: aleksis/core/models.py:73 +#: aleksis/core/models.py:77 msgid "IP address" msgstr "" -#: aleksis/core/models.py:74 +#: aleksis/core/models.py:78 msgid "Boolean or empty (Yes/No/Neither)" msgstr "" -#: aleksis/core/models.py:75 +#: aleksis/core/models.py:79 msgid "Text (multi-line)" msgstr "" -#: aleksis/core/models.py:77 +#: aleksis/core/models.py:81 msgid "URL / Link" msgstr "" -#: aleksis/core/models.py:89 aleksis/core/models.py:948 +#: aleksis/core/models.py:93 aleksis/core/models.py:950 msgid "Name" msgstr "" -#: aleksis/core/models.py:91 +#: aleksis/core/models.py:95 #, fuzzy #| msgid "Contact details" msgid "Start date" msgstr "Détails de contact" -#: aleksis/core/models.py:92 +#: aleksis/core/models.py:96 msgid "End date" msgstr "" -#: aleksis/core/models.py:111 +#: aleksis/core/models.py:115 msgid "The start date must be earlier than the end date." msgstr "" -#: aleksis/core/models.py:118 +#: aleksis/core/models.py:122 msgid "There is already a school term for this time or a part of this time." msgstr "" -#: aleksis/core/models.py:147 aleksis/core/models.py:897 +#: aleksis/core/models.py:151 aleksis/core/models.py:899 msgid "Person" msgstr "Personne" -#: aleksis/core/models.py:150 +#: aleksis/core/models.py:154 #, fuzzy #| msgid "Contact details" msgid "Can view address" msgstr "Détails de contact" -#: aleksis/core/models.py:151 +#: aleksis/core/models.py:155 #, fuzzy #| msgid "Contact details" msgid "Can view contact details" msgstr "Détails de contact" -#: aleksis/core/models.py:152 +#: aleksis/core/models.py:156 #, fuzzy #| msgid "Contact details" msgid "Can view photo" msgstr "Détails de contact" -#: aleksis/core/models.py:153 +#: aleksis/core/models.py:157 #, fuzzy #| msgid "Contact details" msgid "Can view persons groups" msgstr "Détails de contact" -#: aleksis/core/models.py:154 +#: aleksis/core/models.py:158 #, fuzzy #| msgid "Contact details" msgid "Can view personal details" msgstr "Détails de contact" -#: aleksis/core/models.py:164 +#: aleksis/core/models.py:168 msgid "female" msgstr "" -#: aleksis/core/models.py:164 +#: aleksis/core/models.py:168 msgid "male" msgstr "" -#: aleksis/core/models.py:172 +#: aleksis/core/models.py:176 aleksis/core/models.py:1144 msgid "Linked user" msgstr "" -#: aleksis/core/models.py:174 +#: aleksis/core/models.py:178 msgid "Is person active?" msgstr "" -#: aleksis/core/models.py:176 +#: aleksis/core/models.py:180 msgid "First name" msgstr "Prénom" -#: aleksis/core/models.py:177 +#: aleksis/core/models.py:181 msgid "Last name" msgstr "Nom de famille" -#: aleksis/core/models.py:179 +#: aleksis/core/models.py:183 msgid "Additional name(s)" msgstr "" -#: aleksis/core/models.py:183 aleksis/core/models.py:429 +#: aleksis/core/models.py:187 aleksis/core/models.py:431 #, fuzzy #| msgid "First name" msgid "Short name" msgstr "Prénom" -#: aleksis/core/models.py:186 +#: aleksis/core/models.py:190 msgid "Street" msgstr "" -#: aleksis/core/models.py:187 +#: aleksis/core/models.py:191 msgid "Street number" msgstr "" -#: aleksis/core/models.py:188 +#: aleksis/core/models.py:192 msgid "Postal code" msgstr "" -#: aleksis/core/models.py:189 +#: aleksis/core/models.py:193 msgid "Place" msgstr "" -#: aleksis/core/models.py:191 +#: aleksis/core/models.py:195 msgid "Home phone" msgstr "" -#: aleksis/core/models.py:192 +#: aleksis/core/models.py:196 msgid "Mobile phone" msgstr "" -#: aleksis/core/models.py:196 +#: aleksis/core/models.py:200 msgid "Date of birth" msgstr "Date d'anniversaire" -#: aleksis/core/models.py:198 +#: aleksis/core/models.py:201 #, fuzzy #| msgid "Date of birth" msgid "Place of birth" msgstr "Date d'anniversaire" -#: aleksis/core/models.py:200 +#: aleksis/core/models.py:202 msgid "Sex" msgstr "Sexe" -#: aleksis/core/models.py:202 +#: aleksis/core/models.py:204 msgid "Photo" msgstr "" -#: aleksis/core/models.py:206 aleksis/core/templates/core/person/full.html:138 +#: aleksis/core/models.py:208 aleksis/core/templates/core/person/full.html:145 msgid "Guardians / Parents" msgstr "" -#: aleksis/core/models.py:213 +#: aleksis/core/models.py:215 msgid "Primary group" msgstr "" -#: aleksis/core/models.py:216 aleksis/core/models.py:583 -#: aleksis/core/models.py:607 aleksis/core/models.py:692 -#: aleksis/core/models.py:972 aleksis/core/templates/core/person/full.html:121 +#: aleksis/core/models.py:218 aleksis/core/models.py:585 +#: aleksis/core/models.py:609 aleksis/core/models.py:694 +#: aleksis/core/models.py:974 aleksis/core/templates/core/person/full.html:128 msgid "Description" msgstr "Description" -#: aleksis/core/models.py:384 +#: aleksis/core/models.py:386 msgid "Title of field" msgstr "" -#: aleksis/core/models.py:386 +#: aleksis/core/models.py:388 msgid "Type of field" msgstr "" -#: aleksis/core/models.py:393 +#: aleksis/core/models.py:395 msgid "Addtitional field for groups" msgstr "" -#: aleksis/core/models.py:394 +#: aleksis/core/models.py:396 msgid "Addtitional fields for groups" msgstr "" -#: aleksis/core/models.py:414 +#: aleksis/core/models.py:416 msgid "Can assign child groups to groups" msgstr "" -#: aleksis/core/models.py:415 +#: aleksis/core/models.py:417 #, fuzzy #| msgid "Contact details" msgid "Can view statistics about group." msgstr "Détails de contact" -#: aleksis/core/models.py:427 +#: aleksis/core/models.py:429 #, fuzzy #| msgid "Last name" msgid "Long name" msgstr "Nom de famille" -#: aleksis/core/models.py:437 aleksis/core/templates/core/group/full.html:85 +#: aleksis/core/models.py:439 aleksis/core/templates/core/group/full.html:85 msgid "Members" msgstr "" -#: aleksis/core/models.py:440 aleksis/core/templates/core/group/full.html:82 +#: aleksis/core/models.py:442 aleksis/core/templates/core/group/full.html:82 msgid "Owners" msgstr "Propriétaires" -#: aleksis/core/models.py:447 aleksis/core/templates/core/group/full.html:55 +#: aleksis/core/models.py:449 aleksis/core/templates/core/group/full.html:55 msgid "Parent groups" msgstr "" -#: aleksis/core/models.py:455 +#: aleksis/core/models.py:457 msgid "Type of group" msgstr "" -#: aleksis/core/models.py:582 aleksis/core/models.py:606 -#: aleksis/core/models.py:691 +#: aleksis/core/models.py:584 aleksis/core/models.py:608 +#: aleksis/core/models.py:693 #: aleksis/core/templates/core/announcement/list.html:18 msgid "Title" msgstr "" -#: aleksis/core/models.py:585 +#: aleksis/core/models.py:587 msgid "Application" msgstr "" -#: aleksis/core/models.py:591 +#: aleksis/core/models.py:593 msgid "Activity" msgstr "" -#: aleksis/core/models.py:592 +#: aleksis/core/models.py:594 msgid "Activities" msgstr "" -#: aleksis/core/models.py:598 +#: aleksis/core/models.py:600 msgid "Sender" msgstr "" -#: aleksis/core/models.py:603 +#: aleksis/core/models.py:605 msgid "Recipient" msgstr "" -#: aleksis/core/models.py:608 aleksis/core/models.py:949 +#: aleksis/core/models.py:610 aleksis/core/models.py:951 msgid "Link" msgstr "" -#: aleksis/core/models.py:610 +#: aleksis/core/models.py:612 msgid "Read" msgstr "" -#: aleksis/core/models.py:611 +#: aleksis/core/models.py:613 msgid "Sent" msgstr "" -#: aleksis/core/models.py:624 +#: aleksis/core/models.py:626 msgid "Notification" msgstr "" -#: aleksis/core/models.py:693 +#: aleksis/core/models.py:695 msgid "Link to detailed view" msgstr "" -#: aleksis/core/models.py:696 +#: aleksis/core/models.py:698 msgid "Date and time from when to show" msgstr "" -#: aleksis/core/models.py:699 +#: aleksis/core/models.py:701 msgid "Date and time until when to show" msgstr "" -#: aleksis/core/models.py:724 +#: aleksis/core/models.py:726 msgid "Announcement" msgstr "" -#: aleksis/core/models.py:762 +#: aleksis/core/models.py:764 msgid "Announcement recipient" msgstr "" -#: aleksis/core/models.py:763 +#: aleksis/core/models.py:765 msgid "Announcement recipients" msgstr "" -#: aleksis/core/models.py:818 +#: aleksis/core/models.py:820 msgid "Widget Title" msgstr "" -#: aleksis/core/models.py:819 +#: aleksis/core/models.py:821 msgid "Activate Widget" msgstr "" -#: aleksis/core/models.py:820 +#: aleksis/core/models.py:822 msgid "Widget is broken" msgstr "" -#: aleksis/core/models.py:823 +#: aleksis/core/models.py:825 msgid "Size on mobile devices" msgstr "" -#: aleksis/core/models.py:824 +#: aleksis/core/models.py:826 msgid "<= 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:829 +#: aleksis/core/models.py:831 msgid "Size on tablet devices" msgstr "" -#: aleksis/core/models.py:830 +#: aleksis/core/models.py:832 msgid "> 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:835 +#: aleksis/core/models.py:837 msgid "Size on desktop devices" msgstr "" -#: aleksis/core/models.py:836 +#: aleksis/core/models.py:838 msgid "> 992 px, 12 columns" msgstr "" -#: aleksis/core/models.py:841 +#: aleksis/core/models.py:843 msgid "Size on large desktop devices" msgstr "" -#: aleksis/core/models.py:842 +#: aleksis/core/models.py:844 msgid "> 1200 px>, 12 columns" msgstr "" -#: aleksis/core/models.py:873 +#: aleksis/core/models.py:875 msgid "Can edit default dashboard" msgstr "" -#: aleksis/core/models.py:874 +#: aleksis/core/models.py:876 msgid "Dashboard Widget" msgstr "" -#: aleksis/core/models.py:875 +#: aleksis/core/models.py:877 msgid "Dashboard Widgets" msgstr "" -#: aleksis/core/models.py:881 +#: aleksis/core/models.py:883 msgid "URL" msgstr "" -#: aleksis/core/models.py:882 +#: aleksis/core/models.py:884 msgid "Icon URL" msgstr "" -#: aleksis/core/models.py:888 +#: aleksis/core/models.py:890 msgid "External link widget" msgstr "" -#: aleksis/core/models.py:889 +#: aleksis/core/models.py:891 msgid "External link widgets" msgstr "" -#: aleksis/core/models.py:894 +#: aleksis/core/models.py:896 msgid "Dashboard widget" msgstr "" -#: aleksis/core/models.py:899 +#: aleksis/core/models.py:901 msgid "Order" msgstr "" -#: aleksis/core/models.py:900 +#: aleksis/core/models.py:902 msgid "Part of the default dashboard" msgstr "" -#: aleksis/core/models.py:915 +#: aleksis/core/models.py:917 msgid "Dashboard widget order" msgstr "" -#: aleksis/core/models.py:916 +#: aleksis/core/models.py:918 msgid "Dashboard widget orders" msgstr "" -#: aleksis/core/models.py:922 +#: aleksis/core/models.py:924 msgid "Menu ID" msgstr "" -#: aleksis/core/models.py:935 +#: aleksis/core/models.py:937 msgid "Custom menu" msgstr "" -#: aleksis/core/models.py:936 +#: aleksis/core/models.py:938 msgid "Custom menus" msgstr "" -#: aleksis/core/models.py:946 +#: aleksis/core/models.py:948 msgid "Menu" msgstr "" -#: aleksis/core/models.py:950 +#: aleksis/core/models.py:952 msgid "Icon" msgstr "" -#: aleksis/core/models.py:956 +#: aleksis/core/models.py:958 msgid "Custom menu item" msgstr "" -#: aleksis/core/models.py:957 +#: aleksis/core/models.py:959 msgid "Custom menu items" msgstr "" -#: aleksis/core/models.py:971 +#: aleksis/core/models.py:973 msgid "Title of type" msgstr "" -#: aleksis/core/models.py:978 aleksis/core/templates/core/group/full.html:47 +#: aleksis/core/models.py:980 aleksis/core/templates/core/group/full.html:47 #, fuzzy #| msgid "Group" msgid "Group type" msgstr "Groupe" -#: aleksis/core/models.py:992 +#: aleksis/core/models.py:994 #, fuzzy #| msgid "Contact details" msgid "Can view system status" msgstr "Détails de contact" -#: aleksis/core/models.py:993 +#: aleksis/core/models.py:995 msgid "Can manage data" msgstr "" -#: aleksis/core/models.py:994 +#: aleksis/core/models.py:996 #, fuzzy #| msgid "Contact details" msgid "Can impersonate" msgstr "Détails de contact" -#: aleksis/core/models.py:995 +#: aleksis/core/models.py:997 msgid "Can use search" msgstr "" -#: aleksis/core/models.py:996 +#: aleksis/core/models.py:998 msgid "Can change site preferences" msgstr "" -#: aleksis/core/models.py:997 +#: aleksis/core/models.py:999 msgid "Can change person preferences" msgstr "" -#: aleksis/core/models.py:998 +#: aleksis/core/models.py:1000 msgid "Can change group preferences" msgstr "" -#: aleksis/core/models.py:999 +#: aleksis/core/models.py:1001 msgid "Can test PDF generation" msgstr "" -#: aleksis/core/models.py:1035 +#: aleksis/core/models.py:1037 msgid "Related data check task" msgstr "" -#: aleksis/core/models.py:1043 +#: aleksis/core/models.py:1045 msgid "Issue solved" msgstr "" -#: aleksis/core/models.py:1044 +#: aleksis/core/models.py:1046 msgid "Notification sent" msgstr "" -#: aleksis/core/models.py:1057 +#: aleksis/core/models.py:1059 msgid "Data check result" msgstr "" -#: aleksis/core/models.py:1058 +#: aleksis/core/models.py:1060 msgid "Data check results" msgstr "" -#: aleksis/core/models.py:1060 +#: aleksis/core/models.py:1062 msgid "Can run data checks" msgstr "" -#: aleksis/core/models.py:1061 +#: aleksis/core/models.py:1063 msgid "Can solve data check problems" msgstr "" -#: aleksis/core/models.py:1076 +#: aleksis/core/models.py:1070 +#, fuzzy +#| msgid "Contact details" +msgid "E-Mail address" +msgstr "Détails de contact" + +#: aleksis/core/models.py:1094 #, fuzzy #| msgid "Owners" msgid "Owner" msgstr "Propriétaires" -#: aleksis/core/models.py:1080 +#: aleksis/core/models.py:1098 msgid "File expires at" msgstr "" -#: aleksis/core/models.py:1082 +#: aleksis/core/models.py:1100 msgid "Generated HTML file" msgstr "" -#: aleksis/core/models.py:1084 +#: aleksis/core/models.py:1102 msgid "Generated PDF file" msgstr "" -#: aleksis/core/models.py:1091 +#: aleksis/core/models.py:1109 msgid "PDF file" msgstr "" -#: aleksis/core/models.py:1092 +#: aleksis/core/models.py:1110 msgid "PDF files" msgstr "" -#: aleksis/core/models.py:1097 +#: aleksis/core/models.py:1115 msgid "Task result" msgstr "" -#: aleksis/core/models.py:1100 +#: aleksis/core/models.py:1118 msgid "Task user" msgstr "" -#: aleksis/core/models.py:1112 +#: aleksis/core/models.py:1130 msgid "Task user assignment" msgstr "" -#: aleksis/core/models.py:1113 +#: aleksis/core/models.py:1131 msgid "Task user assignments" msgstr "" -#: aleksis/core/models.py:1127 +#: aleksis/core/models.py:1147 +#, fuzzy +#| msgid "Contact details" +msgid "Additional attributes" +msgstr "Détails de contact" + +#: aleksis/core/models.py:1185 msgid "Allowed scopes that clients can request" msgstr "" -#: aleksis/core/preferences.py:23 +#: aleksis/core/preferences.py:24 msgid "General" msgstr "" -#: aleksis/core/preferences.py:24 +#: aleksis/core/preferences.py:25 msgid "School" msgstr "" -#: aleksis/core/preferences.py:25 +#: aleksis/core/preferences.py:26 msgid "Theme" msgstr "" -#: aleksis/core/preferences.py:26 +#: aleksis/core/preferences.py:27 msgid "Mail" msgstr "" -#: aleksis/core/preferences.py:28 +#: aleksis/core/preferences.py:29 msgid "Footer" msgstr "" -#: aleksis/core/preferences.py:29 +#: aleksis/core/preferences.py:30 #, fuzzy #| msgid "Contact details" msgid "Accounts" msgstr "Détails de contact" -#: aleksis/core/preferences.py:30 +#: aleksis/core/preferences.py:31 msgid "Authentication" msgstr "" -#: aleksis/core/preferences.py:31 +#: aleksis/core/preferences.py:32 msgid "Internationalisation" msgstr "" -#: aleksis/core/preferences.py:42 +#: aleksis/core/preferences.py:43 msgid "Site title" msgstr "" -#: aleksis/core/preferences.py:53 +#: aleksis/core/preferences.py:54 #, fuzzy #| msgid "Description" msgid "Site description" msgstr "Description" -#: aleksis/core/preferences.py:64 +#: aleksis/core/preferences.py:65 msgid "Primary colour" msgstr "" -#: aleksis/core/preferences.py:76 +#: aleksis/core/preferences.py:77 msgid "Secondary colour" msgstr "" -#: aleksis/core/preferences.py:87 +#: aleksis/core/preferences.py:88 msgid "Logo" msgstr "" -#: aleksis/core/preferences.py:97 +#: aleksis/core/preferences.py:98 msgid "Favicon" msgstr "" -#: aleksis/core/preferences.py:107 +#: aleksis/core/preferences.py:108 msgid "PWA-Icon" msgstr "" -#: aleksis/core/preferences.py:118 +#: aleksis/core/preferences.py:119 #, fuzzy #| msgid "Last name" msgid "Mail out name" msgstr "Nom de famille" -#: aleksis/core/preferences.py:129 +#: aleksis/core/preferences.py:130 msgid "Mail out address" msgstr "" -#: aleksis/core/preferences.py:141 +#: aleksis/core/preferences.py:142 msgid "Link to privacy policy" msgstr "" -#: aleksis/core/preferences.py:153 +#: aleksis/core/preferences.py:154 msgid "Link to imprint" msgstr "" -#: aleksis/core/preferences.py:165 +#: aleksis/core/preferences.py:166 msgid "Name format for addressing" msgstr "" -#: aleksis/core/preferences.py:181 +#: aleksis/core/preferences.py:182 msgid "Channels to use for notifications" msgstr "" -#: aleksis/core/preferences.py:193 +#: aleksis/core/preferences.py:194 msgid "Regular expression to match primary group, e.g. '^Class .*'" msgstr "" -#: aleksis/core/preferences.py:204 +#: aleksis/core/preferences.py:205 msgid "Field on person to match primary group against" msgstr "" -#: aleksis/core/preferences.py:216 +#: aleksis/core/preferences.py:217 msgid "Automatically create new persons for new users" msgstr "" -#: aleksis/core/preferences.py:225 +#: aleksis/core/preferences.py:226 msgid "Automatically link existing persons to new users by their e-mail address" msgstr "" -#: aleksis/core/preferences.py:236 +#: aleksis/core/preferences.py:237 msgid "Display name of the school" msgstr "" -#: aleksis/core/preferences.py:247 +#: aleksis/core/preferences.py:248 msgid "Official name of the school, e.g. as given by supervisory authority" msgstr "" -#: aleksis/core/preferences.py:255 +#: aleksis/core/preferences.py:256 msgid "Allow users to change their passwords" msgstr "" -#: aleksis/core/preferences.py:263 +#: aleksis/core/preferences.py:264 msgid "Enable signup" msgstr "" -#: aleksis/core/preferences.py:274 +#: aleksis/core/preferences.py:272 +msgid "Enable invitations" +msgstr "" + +#: aleksis/core/preferences.py:280 +msgid "Length of invite code. (Default 3: abcde-acbde-abcde)" +msgstr "" + +#: aleksis/core/preferences.py:288 +msgid "Size of packets. (Default 5: abcde)" +msgstr "" + +#: aleksis/core/preferences.py:298 #, fuzzy #| msgid "Contact details" msgid "Allowed Grant Flows for OAuth applications" msgstr "Détails de contact" -#: aleksis/core/preferences.py:287 +#: aleksis/core/preferences.py:311 msgid "Available languages" msgstr "" -#: aleksis/core/preferences.py:299 +#: aleksis/core/preferences.py:323 msgid "Send emails if data checks detect problems" msgstr "" -#: aleksis/core/preferences.py:310 +#: aleksis/core/preferences.py:334 msgid "Email recipients for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:321 +#: aleksis/core/preferences.py:345 msgid "Email recipient groups for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:330 +#: aleksis/core/preferences.py:354 msgid "Show dashboard to users without login" msgstr "" -#: aleksis/core/preferences.py:339 +#: aleksis/core/preferences.py:363 msgid "Allow users to edit their dashboard" msgstr "" -#: aleksis/core/preferences.py:350 +#: aleksis/core/preferences.py:374 msgid "Fields on person model which are editable by themselves." msgstr "" -#: aleksis/core/preferences.py:364 +#: aleksis/core/preferences.py:388 msgid "Editable fields on person model which should trigger a notification on change" msgstr "" -#: aleksis/core/preferences.py:377 +#: aleksis/core/preferences.py:401 msgid "Contact for notification if a person changes their data" msgstr "" -#: aleksis/core/preferences.py:387 +#: aleksis/core/preferences.py:411 msgid "PDF file expiration duration" msgstr "" -#: aleksis/core/preferences.py:388 +#: aleksis/core/preferences.py:412 msgid "in minutes" msgstr "" -#: aleksis/core/preferences.py:398 +#: aleksis/core/preferences.py:422 msgid "Automatically update the dashboard and its widgets" msgstr "" -#: aleksis/core/preferences.py:408 +#: aleksis/core/preferences.py:432 msgid "Automatically update the dashboard and its widgets sitewide" msgstr "" -#: aleksis/core/settings.py:474 +#: aleksis/core/settings.py:507 msgid "English" msgstr "" -#: aleksis/core/settings.py:475 +#: aleksis/core/settings.py:508 msgid "German" msgstr "" -#: aleksis/core/tables.py:19 +#: aleksis/core/tables.py:24 #: aleksis/core/templates/core/announcement/list.html:36 #: aleksis/core/templates/core/group/full.html:24 -#: aleksis/core/templates/core/person/full.html:23 +#: aleksis/core/templates/core/person/full.html:24 #: aleksis/core/templates/oauth2_provider/application/detail.html:17 msgid "Edit" msgstr "" -#: aleksis/core/tables.py:21 aleksis/core/tables.py:89 -#: aleksis/core/tables.py:105 +#: aleksis/core/tables.py:26 aleksis/core/tables.py:94 +#: aleksis/core/tables.py:137 #: aleksis/core/templates/core/announcement/list.html:22 msgid "Actions" msgstr "" -#: aleksis/core/tables.py:56 aleksis/core/tables.py:57 -#: aleksis/core/tables.py:71 aleksis/core/tables.py:87 -#: aleksis/core/tables.py:103 +#: aleksis/core/tables.py:61 aleksis/core/tables.py:62 +#: aleksis/core/tables.py:76 aleksis/core/tables.py:92 +#: aleksis/core/tables.py:135 #: aleksis/core/templates/core/announcement/list.html:42 #: aleksis/core/templates/core/group/full.html:31 #: aleksis/core/templates/core/pages/delete.html:22 -#: aleksis/core/templates/core/person/full.html:30 +#: aleksis/core/templates/core/person/full.html:31 #: aleksis/core/templates/oauth2_provider/application/detail.html:21 msgid "Delete" msgstr "" @@ -1264,11 +1289,11 @@ msgstr "" msgid "Account inactive" msgstr "" -#: aleksis/core/templates/account/account_inactive.html:13 +#: aleksis/core/templates/account/account_inactive.html:14 msgid "Account inactive." msgstr "" -#: aleksis/core/templates/account/account_inactive.html:15 +#: aleksis/core/templates/account/account_inactive.html:17 msgid "" "\n" " This account is currently inactive. If you think this is an\n" @@ -1420,11 +1445,11 @@ msgstr "" msgid "Signup closed" msgstr "" -#: aleksis/core/templates/account/signup_closed.html:13 +#: aleksis/core/templates/account/signup_closed.html:14 msgid "Signup closed." msgstr "" -#: aleksis/core/templates/account/signup_closed.html:15 +#: aleksis/core/templates/account/signup_closed.html:17 msgid "" "\n" " This sign up is currently closed. If you think this is an\n" @@ -1462,11 +1487,6 @@ msgid "" " " msgstr "" -#: aleksis/core/templates/account/verification_sent.html:30 -#, python-format -msgid "<strong>Note:</strong> you can still <a href=\"%(email_url)s\">change your e-mail address</a>" -msgstr "" - #: aleksis/core/templates/core/additional_field/edit.html:6 #: aleksis/core/templates/core/additional_field/edit.html:7 msgid "Edit additional field" @@ -1515,11 +1535,11 @@ msgid "Logged in as" msgstr "" #: aleksis/core/templates/core/base.html:175 -msgid "About AlekSIS — The Free School Information System" +msgid "About AlekSIS® — The Free School Information System" msgstr "" #: aleksis/core/templates/core/base.html:183 -msgid "Impress" +msgid "Imprint" msgstr "" #: aleksis/core/templates/core/base.html:191 @@ -1527,7 +1547,7 @@ msgid "Privacy Policy" msgstr "" #: aleksis/core/templates/core/base_print.html:72 -msgid "Powered by AlekSIS" +msgid "Powered by AlekSIS®" msgstr "" #: aleksis/core/templates/core/dashboard_widget/create.html:8 @@ -1748,7 +1768,7 @@ msgid "Edit group" msgstr "" #: aleksis/core/templates/core/group/full.html:38 -#: aleksis/core/templates/core/person/full.html:37 +#: aleksis/core/templates/core/person/full.html:38 msgid "Change preferences" msgstr "" @@ -1841,36 +1861,46 @@ msgid "No notifications available yet." msgstr "" #: aleksis/core/templates/core/pages/about.html:6 -#: aleksis/core/templates/core/pages/about.html:15 -msgid "About AlekSIS" +msgid "About AlekSIS®" msgstr "" #: aleksis/core/templates/core/pages/about.html:7 -msgid "AlekSIS – The Free School Information System" +msgid "AlekSIS® – The Free School Information System" +msgstr "" + +#: aleksis/core/templates/core/pages/about.html:15 +msgid "About AlekSIS" msgstr "" #: aleksis/core/templates/core/pages/about.html:17 msgid "" "\n" -" This platform is powered by AlekSIS, a web-based school information system (SIS) which can be used\n" +" This platform is powered by AlekSIS®, a web-based school information system (SIS) which can be used\n" " to manage and/or publish organisational artifacts of educational institutions. AlekSIS is free software and\n" " can be used by anyone.\n" " " msgstr "" -#: aleksis/core/templates/core/pages/about.html:25 +#: aleksis/core/templates/core/pages/about.html:24 +msgid "" +"\n" +" AlekSIS® is a registered trademark of the AlekSIS open source project, represented by Teckids e.V.\n" +" " +msgstr "" + +#: aleksis/core/templates/core/pages/about.html:30 msgid "Website of AlekSIS" msgstr "" -#: aleksis/core/templates/core/pages/about.html:26 +#: aleksis/core/templates/core/pages/about.html:31 msgid "Source code" msgstr "" -#: aleksis/core/templates/core/pages/about.html:35 +#: aleksis/core/templates/core/pages/about.html:40 msgid "Licence information" msgstr "" -#: aleksis/core/templates/core/pages/about.html:37 +#: aleksis/core/templates/core/pages/about.html:42 msgid "" "\n" " The core and the official apps of AlekSIS are licenced under the EUPL, version 1.2 or later. For licence\n" @@ -1879,23 +1909,23 @@ msgid "" " " msgstr "" -#: aleksis/core/templates/core/pages/about.html:45 +#: aleksis/core/templates/core/pages/about.html:50 msgid "Free/Open Source Licence" msgstr "" -#: aleksis/core/templates/core/pages/about.html:46 +#: aleksis/core/templates/core/pages/about.html:51 msgid "Other Licence" msgstr "" -#: aleksis/core/templates/core/pages/about.html:50 +#: aleksis/core/templates/core/pages/about.html:55 msgid "Full licence text" msgstr "" -#: aleksis/core/templates/core/pages/about.html:51 +#: aleksis/core/templates/core/pages/about.html:56 msgid "More information about the EUPL" msgstr "" -#: aleksis/core/templates/core/pages/about.html:90 +#: aleksis/core/templates/core/pages/about.html:95 #, python-format msgid "" "\n" @@ -2142,19 +2172,21 @@ msgstr "Détails de contact" msgid "Edit person" msgstr "" -#: aleksis/core/templates/core/person/full.html:44 -#: aleksis/core/templates/impersonate/list_users.html:7 -#: aleksis/core/templates/impersonate/list_users.html:8 +#: aleksis/core/templates/core/person/full.html:45 #, fuzzy #| msgid "Contact details" msgid "Impersonate" msgstr "Détails de contact" -#: aleksis/core/templates/core/person/full.html:50 +#: aleksis/core/templates/core/person/full.html:51 +msgid "Invite user" +msgstr "" + +#: aleksis/core/templates/core/person/full.html:57 msgid "Contact details" msgstr "Détails de contact" -#: aleksis/core/templates/core/person/full.html:131 +#: aleksis/core/templates/core/person/full.html:138 msgid "Children" msgstr "" @@ -2194,6 +2226,51 @@ msgstr "" msgid "Save preferences" msgstr "" +#: aleksis/core/templates/invitations/enter.html:21 +msgid "Accept your invitation" +msgstr "" + +#: aleksis/core/templates/invitations/enter.html:25 +msgid "" +"\n" +" Please enter your invitation code to register\n" +" your new user account:\n" +" " +msgstr "" + +#: aleksis/core/templates/invitations/enter.html:37 +msgid "Accept invite" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:9 +#: aleksis/core/templates/invitations/forms/_invite.html:10 +#: aleksis/core/templates/invitations/forms/_invite.html:21 +msgid "Invite" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:17 +#, fuzzy +#| msgid "Contact details" +msgid "Invite by email address" +msgstr "Détails de contact" + +#: aleksis/core/templates/invitations/forms/_invite.html:26 +msgid "Generate invitation code" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:29 +msgid "Generate code" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:33 +msgid "Invitations" +msgstr "" + +#: aleksis/core/templates/invitations/messages/invite_accepted.txt:3 +#, python-format +msgid "The invitation for %(email)s has been accepted." +msgstr "" + #: aleksis/core/templates/oauth2_provider/application/create.html:5 #: aleksis/core/templates/oauth2_provider/application/create.html:6 #, fuzzy @@ -2860,151 +2937,166 @@ msgstr "" msgid "SMS" msgstr "" -#: aleksis/core/util/pdf.py:105 +#: aleksis/core/util/pdf.py:113 msgid "Progress: Generate PDF file" msgstr "" -#: aleksis/core/util/pdf.py:106 +#: aleksis/core/util/pdf.py:114 msgid "Generating PDF file …" msgstr "" -#: aleksis/core/util/pdf.py:107 +#: aleksis/core/util/pdf.py:115 msgid "The PDF file has been generated successfully." msgstr "" -#: aleksis/core/util/pdf.py:108 +#: aleksis/core/util/pdf.py:116 msgid "There was a problem while generating the PDF file." msgstr "" -#: aleksis/core/util/pdf.py:111 +#: aleksis/core/util/pdf.py:119 msgid "Download PDF" msgstr "" -#: aleksis/core/views.py:270 +#: aleksis/core/views.py:280 msgid "The school term has been created." msgstr "" -#: aleksis/core/views.py:282 +#: aleksis/core/views.py:292 msgid "The school term has been saved." msgstr "" -#: aleksis/core/views.py:406 +#: aleksis/core/views.py:416 msgid "The child groups were successfully saved." msgstr "" -#: aleksis/core/views.py:425 aleksis/core/views.py:435 +#: aleksis/core/views.py:435 aleksis/core/views.py:445 msgid "The person has been saved." msgstr "" -#: aleksis/core/views.py:485 +#: aleksis/core/views.py:495 msgid "The group has been saved." msgstr "" -#: aleksis/core/views.py:582 +#: aleksis/core/views.py:592 msgid "The announcement has been saved." msgstr "" -#: aleksis/core/views.py:598 +#: aleksis/core/views.py:608 msgid "The announcement has been deleted." msgstr "" -#: aleksis/core/views.py:682 +#: aleksis/core/views.py:695 msgid "The preferences have been saved successfully." msgstr "" -#: aleksis/core/views.py:706 +#: aleksis/core/views.py:719 msgid "The person has been deleted." msgstr "" -#: aleksis/core/views.py:720 +#: aleksis/core/views.py:733 msgid "The group has been deleted." msgstr "" -#: aleksis/core/views.py:752 +#: aleksis/core/views.py:765 msgid "The additional_field has been saved." msgstr "" -#: aleksis/core/views.py:786 +#: aleksis/core/views.py:799 msgid "The additional field has been deleted." msgstr "" -#: aleksis/core/views.py:811 +#: aleksis/core/views.py:824 msgid "The group type has been saved." msgstr "" -#: aleksis/core/views.py:841 +#: aleksis/core/views.py:854 msgid "The group type has been deleted." msgstr "" -#: aleksis/core/views.py:874 +#: aleksis/core/views.py:887 msgid "Progress: Run data checks" msgstr "" -#: aleksis/core/views.py:875 +#: aleksis/core/views.py:888 msgid "Run data checks …" msgstr "" -#: aleksis/core/views.py:876 +#: aleksis/core/views.py:889 msgid "The data checks were run successfully." msgstr "" -#: aleksis/core/views.py:877 +#: aleksis/core/views.py:890 msgid "There was a problem while running data checks." msgstr "" -#: aleksis/core/views.py:893 +#: aleksis/core/views.py:906 #, python-brace-format msgid "The solve option '{solve_option_obj.verbose_name}' " msgstr "" -#: aleksis/core/views.py:935 +#: aleksis/core/views.py:948 msgid "The dashboard widget has been saved." msgstr "" -#: aleksis/core/views.py:965 +#: aleksis/core/views.py:978 msgid "The dashboard widget has been created." msgstr "" -#: aleksis/core/views.py:975 +#: aleksis/core/views.py:988 msgid "The dashboard widget has been deleted." msgstr "" -#: aleksis/core/views.py:1042 +#: aleksis/core/views.py:1055 msgid "Your dashboard configuration has been saved successfully." msgstr "" -#: aleksis/core/views.py:1044 +#: aleksis/core/views.py:1057 msgid "The configuration of the default dashboard has been saved successfully." msgstr "" -#: aleksis/core/views.py:1139 +#: aleksis/core/views.py:1127 +#, python-brace-format +msgid "The invitation was successfully created. The invitation code is {code}" +msgstr "" + +#: aleksis/core/views.py:1218 msgid "We have successfully assigned the permissions." msgstr "" -#: aleksis/core/views.py:1149 +#: aleksis/core/views.py:1228 msgid "The global user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1159 +#: aleksis/core/views.py:1238 msgid "The global group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1169 +#: aleksis/core/views.py:1248 msgid "The object user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1179 +#: aleksis/core/views.py:1258 msgid "The object group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1298 +#: aleksis/core/views.py:1377 msgid "The third-party account could not be disconnected because it is the only login method available." msgstr "" -#: aleksis/core/views.py:1305 +#: aleksis/core/views.py:1384 msgid "The third-party account has been successfully disconnected." msgstr "" +#: aleksis/core/views.py:1441 +msgid "Person was invited successfully." +msgstr "" + +#: aleksis/core/views.py:1443 +#, fuzzy +#| msgid "This username is already in use." +msgid "Person was already invited." +msgstr "Cet nom est deja en utilisation." + #, fuzzy #~| msgid "Contact details" #~ msgid "Can link persons to accounts" diff --git a/aleksis/core/locale/fr/LC_MESSAGES/djangojs.po b/aleksis/core/locale/fr/LC_MESSAGES/djangojs.po index d92f36a6a9ed2888791de39ed7c9db3bdfe7f8dc..8dd920515ef4b23a59c72cb6ec2809d27d03292a 100644 --- a/aleksis/core/locale/fr/LC_MESSAGES/djangojs.po +++ b/aleksis/core/locale/fr/LC_MESSAGES/djangojs.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-29 09:59+0100\n" +"POT-Creation-Date: 2021-12-28 12:14+0100\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" @@ -30,6 +30,6 @@ msgstr "" msgid "OK" msgstr "" -#: aleksis/core/static/js/main.js:127 +#: aleksis/core/static/js/main.js:128 msgid "This page may contain outdated information since there is no internet connection." msgstr "" diff --git a/aleksis/core/locale/la/LC_MESSAGES/django.po b/aleksis/core/locale/la/LC_MESSAGES/django.po index 0f4d9b00d9560e0140e6242ec635d51b278c1271..b8f7f6b758f1520e97d0d96304f9205d2e356c9a 100644 --- a/aleksis/core/locale/la/LC_MESSAGES/django.po +++ b/aleksis/core/locale/la/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-29 09:59+0100\n" +"POT-Creation-Date: 2021-12-28 12:13+0100\n" "PO-Revision-Date: 2020-12-19 12:57+0000\n" "Last-Translator: Julian <leuckerj@gmail.com>\n" "Language-Team: Latin <https://translate.edugit.org/projects/aleksis/aleksis/la/>\n" @@ -18,32 +18,39 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.3.2\n" -#: aleksis/core/apps.py:151 +#: aleksis/core/apps.py:152 msgid "OpenID Connect scope" msgstr "" -#: aleksis/core/apps.py:152 +#: aleksis/core/apps.py:153 msgid "Given name, family name, link to profile and picture if existing." msgstr "" -#: aleksis/core/apps.py:153 +#: aleksis/core/apps.py:154 #, fuzzy #| msgid "E-mail address" msgid "Full home postal address" msgstr "Inscriptio electronica" -#: aleksis/core/apps.py:154 +#: aleksis/core/apps.py:155 #, fuzzy #| msgid "E-mail address" msgid "Email address" msgstr "Inscriptio electronica" -#: aleksis/core/apps.py:155 +#: aleksis/core/apps.py:156 #, fuzzy #| msgid "Mobile phone" msgid "Home and mobile phone" msgstr "Numerus telephoni mobilis" +#: aleksis/core/apps.py:157 aleksis/core/forms.py:223 aleksis/core/menus.py:265 +#: aleksis/core/models.py:414 aleksis/core/templates/core/group/list.html:8 +#: aleksis/core/templates/core/group/list.html:9 +#: aleksis/core/templates/core/person/full.html:152 +msgid "Groups" +msgstr "Greges" + #: aleksis/core/data_checks.py:55 msgid "Ignore problem" msgstr "" @@ -94,168 +101,162 @@ msgstr "" msgid "Content type" msgstr "" -#: aleksis/core/filters.py:112 aleksis/core/models.py:579 +#: aleksis/core/filters.py:112 aleksis/core/models.py:581 msgid "User" msgstr "" -#: aleksis/core/filters.py:134 aleksis/core/models.py:411 +#: aleksis/core/filters.py:134 aleksis/core/models.py:413 msgid "Group" msgstr "Grex" -#: aleksis/core/forms.py:46 aleksis/core/forms.py:514 +#: aleksis/core/forms.py:48 aleksis/core/forms.py:559 msgid "Base data" msgstr "" -#: aleksis/core/forms.py:52 +#: aleksis/core/forms.py:54 #, fuzzy #| msgid "E-mail address" msgid "Address" msgstr "Inscriptio electronica" -#: aleksis/core/forms.py:53 +#: aleksis/core/forms.py:55 aleksis/core/forms.py:568 msgid "Contact data" msgstr "" -#: aleksis/core/forms.py:55 +#: aleksis/core/forms.py:57 msgid "Advanced personal data" msgstr "" -#: aleksis/core/forms.py:103 +#: aleksis/core/forms.py:105 msgid "New user" msgstr "" -#: aleksis/core/forms.py:103 +#: aleksis/core/forms.py:105 #, fuzzy #| msgid "Persons and accounts" msgid "Create a new account" msgstr "Personae et computi" -#: aleksis/core/forms.py:134 +#: aleksis/core/forms.py:136 msgid "You cannot set a new username when also selecting an existing user." msgstr "" -#: aleksis/core/forms.py:138 +#: aleksis/core/forms.py:140 msgid "This username is already in use." msgstr "" -#: aleksis/core/forms.py:155 aleksis/core/models.py:125 +#: aleksis/core/forms.py:157 aleksis/core/models.py:129 msgid "School term" msgstr "Anus scolae" -#: aleksis/core/forms.py:156 +#: aleksis/core/forms.py:158 #, fuzzy #| msgid "Data management" msgid "Common data" msgstr "Adminstratio datarum" -#: aleksis/core/forms.py:157 aleksis/core/forms.py:208 -#: aleksis/core/menus.py:256 aleksis/core/models.py:148 +#: aleksis/core/forms.py:159 aleksis/core/forms.py:210 +#: aleksis/core/menus.py:254 aleksis/core/models.py:152 #: aleksis/core/templates/core/person/list.html:8 #: aleksis/core/templates/core/person/list.html:9 msgid "Persons" msgstr "personae" -#: aleksis/core/forms.py:158 +#: aleksis/core/forms.py:160 aleksis/core/forms.py:570 #, fuzzy #| msgid "Additional name(s)" msgid "Additional data" msgstr "addita nomines" -#: aleksis/core/forms.py:200 aleksis/core/forms.py:203 -#: aleksis/core/models.py:68 +#: aleksis/core/forms.py:202 aleksis/core/forms.py:205 +#: aleksis/core/models.py:72 msgid "Date" msgstr "dies" -#: aleksis/core/forms.py:201 aleksis/core/forms.py:204 -#: aleksis/core/models.py:76 +#: aleksis/core/forms.py:203 aleksis/core/forms.py:206 +#: aleksis/core/models.py:80 msgid "Time" msgstr "tempus" -#: aleksis/core/forms.py:221 aleksis/core/menus.py:267 -#: aleksis/core/models.py:412 aleksis/core/templates/core/group/list.html:8 -#: aleksis/core/templates/core/group/list.html:9 -#: aleksis/core/templates/core/person/full.html:145 -msgid "Groups" -msgstr "Greges" - -#: aleksis/core/forms.py:234 +#: aleksis/core/forms.py:236 msgid "From when until when should the announcement be displayed?" msgstr "" -#: aleksis/core/forms.py:237 +#: aleksis/core/forms.py:239 msgid "Who should see the announcement?" msgstr "Quis nuntium videatne?" -#: aleksis/core/forms.py:238 +#: aleksis/core/forms.py:240 msgid "Write your announcement:" msgstr "Scribe nuntium:" -#: aleksis/core/forms.py:277 +#: aleksis/core/forms.py:279 msgid "You are not allowed to create announcements which are only valid in the past." msgstr "" -#: aleksis/core/forms.py:281 +#: aleksis/core/forms.py:283 msgid "The from date and time must be earlier then the until date and time." msgstr "" -#: aleksis/core/forms.py:290 +#: aleksis/core/forms.py:292 msgid "You need at least one recipient." msgstr "" -#: aleksis/core/forms.py:411 +#: aleksis/core/forms.py:401 +msgid "Invitation code" +msgstr "" + +#: aleksis/core/forms.py:402 +msgid "Please enter your invitation code." +msgstr "" + +#: aleksis/core/forms.py:434 #, fuzzy #| msgid "Who should see the announcement?" msgid "Who should get the permission?" msgstr "Quis nuntium videatne?" -#: aleksis/core/forms.py:412 +#: aleksis/core/forms.py:435 msgid "On what?" msgstr "" -#: aleksis/core/forms.py:438 +#: aleksis/core/forms.py:461 msgid "Select objects which the permission should be granted for:" msgstr "" -#: aleksis/core/forms.py:441 +#: aleksis/core/forms.py:464 msgid "Grant the permission for all objects" msgstr "" -#: aleksis/core/forms.py:449 +#: aleksis/core/forms.py:472 msgid "You must select at least one group or person which should get the permission." msgstr "" -#: aleksis/core/forms.py:454 +#: aleksis/core/forms.py:477 msgid "You must grant the permission to all objects and/or to some objects." msgstr "" -#: aleksis/core/forms.py:518 +#: aleksis/core/forms.py:564 +#, fuzzy +#| msgid "E-mail address" +msgid "Adress data" +msgstr "Inscriptio electronica" + +#: aleksis/core/forms.py:576 #, fuzzy #| msgid "Data management" msgid "Account data" msgstr "Adminstratio datarum" -#: aleksis/core/forms.py:524 -msgid "Consents" -msgstr "" - -#: aleksis/core/forms.py:531 +#: aleksis/core/forms.py:583 msgid "Password" msgstr "" -#: aleksis/core/forms.py:537 +#: aleksis/core/forms.py:586 msgid "Password (again)" msgstr "" -#: aleksis/core/forms.py:550 -#, python-brace-format -msgid "I have read the <a href='{privacy_policy}'>Privacy policy</a> and agree with them." -msgstr "" - -#: aleksis/core/forms.py:575 -msgid "You must type the same password each time." -msgstr "" - -#: aleksis/core/forms.py:720 +#: aleksis/core/forms.py:752 msgid "No valid selection." msgstr "" @@ -265,24 +266,20 @@ msgstr "" msgid "There are unresolved data problems." msgstr "Scribe nuntium:" -#: aleksis/core/health_checks.py:38 -msgid "The backup folder doesn't exist." -msgstr "" - -#: aleksis/core/health_checks.py:47 +#: aleksis/core/health_checks.py:44 #, python-brace-format msgid "Last backup {time_gone_since_backup}!" msgstr "" -#: aleksis/core/health_checks.py:49 +#: aleksis/core/health_checks.py:46 msgid "No backup found!" msgstr "" -#: aleksis/core/health_checks.py:76 +#: aleksis/core/health_checks.py:73 msgid "No backup result found!" msgstr "" -#: aleksis/core/health_checks.py:78 +#: aleksis/core/health_checks.py:75 #, python-brace-format msgid "{task.status} - {task.result}" msgstr "" @@ -298,34 +295,40 @@ msgstr "nomen profiteri" msgid "Sign up" msgstr "" -#: aleksis/core/menus.py:24 +#: aleksis/core/menus.py:24 aleksis/core/templates/invitations/enter.html:7 +#, fuzzy +#| msgid "Edit school information" +msgid "Accept invitation" +msgstr "Muta informationes scolae" + +#: aleksis/core/menus.py:33 msgid "Dashboard" msgstr "Forum" -#: aleksis/core/menus.py:32 aleksis/core/models.py:625 -#: aleksis/core/preferences.py:27 +#: aleksis/core/menus.py:41 aleksis/core/models.py:627 +#: aleksis/core/preferences.py:28 #: aleksis/core/templates/core/notifications.html:4 #: aleksis/core/templates/core/notifications.html:5 msgid "Notifications" msgstr "Nuntii" -#: aleksis/core/menus.py:44 +#: aleksis/core/menus.py:53 msgid "Account" msgstr "" -#: aleksis/core/menus.py:51 +#: aleksis/core/menus.py:60 msgid "Stop impersonation" msgstr "Simulandum aliquem finire" -#: aleksis/core/menus.py:60 aleksis/core/templates/core/base.html:80 +#: aleksis/core/menus.py:69 aleksis/core/templates/core/base.html:80 msgid "Logout" msgstr "nomen retractare" -#: aleksis/core/menus.py:66 +#: aleksis/core/menus.py:75 msgid "2FA" msgstr "" -#: aleksis/core/menus.py:74 +#: aleksis/core/menus.py:83 #: aleksis/core/templates/account/password_change.html:5 #: aleksis/core/templates/account/password_change.html:6 #: aleksis/core/templates/account/password_change.html:19 @@ -337,22 +340,22 @@ msgstr "" msgid "Change password" msgstr "" -#: aleksis/core/menus.py:86 +#: aleksis/core/menus.py:95 msgid "Me" msgstr "" -#: aleksis/core/menus.py:95 +#: aleksis/core/menus.py:104 #: aleksis/core/templates/dynamic_preferences/form.html:5 msgid "Preferences" msgstr "" -#: aleksis/core/menus.py:104 +#: aleksis/core/menus.py:113 #, fuzzy #| msgid "Persons and accounts" msgid "Third-party accounts" msgstr "Personae et computi" -#: aleksis/core/menus.py:113 +#: aleksis/core/menus.py:122 #: aleksis/core/templates/oauth2_provider/authorized-tokens.html:5 #: aleksis/core/templates/oauth2_provider/authorized-tokens.html:6 #, fuzzy @@ -360,23 +363,23 @@ msgstr "Personae et computi" msgid "Authorized applications" msgstr "Nuntii" -#: aleksis/core/menus.py:124 +#: aleksis/core/menus.py:133 msgid "Admin" msgstr "Administratio" -#: aleksis/core/menus.py:132 aleksis/core/models.py:725 +#: aleksis/core/menus.py:141 aleksis/core/models.py:727 #: aleksis/core/templates/core/announcement/list.html:7 #: aleksis/core/templates/core/announcement/list.html:8 msgid "Announcements" msgstr "Nuntii" -#: aleksis/core/menus.py:143 aleksis/core/models.py:126 +#: aleksis/core/menus.py:152 aleksis/core/models.py:130 #: aleksis/core/templates/core/school_term/list.html:8 #: aleksis/core/templates/core/school_term/list.html:9 msgid "School terms" msgstr "ani scolae" -#: aleksis/core/menus.py:154 +#: aleksis/core/menus.py:163 #: aleksis/core/templates/core/dashboard_widget/list.html:8 #: aleksis/core/templates/core/dashboard_widget/list.html:9 #, fuzzy @@ -384,45 +387,41 @@ msgstr "ani scolae" msgid "Dashboard widgets" msgstr "Forum" -#: aleksis/core/menus.py:165 +#: aleksis/core/menus.py:174 #: aleksis/core/templates/core/management/data_management.html:6 #: aleksis/core/templates/core/management/data_management.html:7 msgid "Data management" msgstr "Adminstratio datarum" -#: aleksis/core/menus.py:176 +#: aleksis/core/menus.py:185 #: aleksis/core/templates/core/pages/system_status.html:5 #: aleksis/core/templates/core/pages/system_status.html:7 msgid "System status" msgstr "Status systemae" -#: aleksis/core/menus.py:187 -msgid "Impersonation" -msgstr "Simulare aliquem" - -#: aleksis/core/menus.py:198 +#: aleksis/core/menus.py:196 #, fuzzy #| msgid "Notification" msgid "Configuration" msgstr "Nuntius" -#: aleksis/core/menus.py:209 aleksis/core/templates/core/data_check/list.html:9 +#: aleksis/core/menus.py:207 aleksis/core/templates/core/data_check/list.html:9 #: aleksis/core/templates/core/data_check/list.html:10 #, fuzzy #| msgid "System status" msgid "Data checks" msgstr "Status systemae" -#: aleksis/core/menus.py:215 aleksis/core/templates/core/perms/list.html:13 +#: aleksis/core/menus.py:213 aleksis/core/templates/core/perms/list.html:13 #: aleksis/core/templates/core/perms/list.html:14 msgid "Manage permissions" msgstr "" -#: aleksis/core/menus.py:226 +#: aleksis/core/menus.py:224 msgid "Backend Admin" msgstr "" -#: aleksis/core/menus.py:234 +#: aleksis/core/menus.py:232 #: aleksis/core/templates/oauth2_provider/application/list.html:5 #: aleksis/core/templates/oauth2_provider/application/list.html:6 #, fuzzy @@ -430,11 +429,11 @@ msgstr "" msgid "OAuth2 Applications" msgstr "Nuntii" -#: aleksis/core/menus.py:247 +#: aleksis/core/menus.py:245 msgid "People" msgstr "Personae" -#: aleksis/core/menus.py:278 aleksis/core/models.py:979 +#: aleksis/core/menus.py:276 aleksis/core/models.py:981 #: aleksis/core/templates/core/group_type/list.html:8 #: aleksis/core/templates/core/group_type/list.html:9 #, fuzzy @@ -442,11 +441,11 @@ msgstr "Personae" msgid "Group types" msgstr "Greges" -#: aleksis/core/menus.py:289 +#: aleksis/core/menus.py:287 msgid "Groups and child groups" msgstr "" -#: aleksis/core/menus.py:300 aleksis/core/models.py:460 +#: aleksis/core/menus.py:298 aleksis/core/models.py:462 #: aleksis/core/templates/core/additional_field/list.html:8 #: aleksis/core/templates/core/additional_field/list.html:9 #, fuzzy @@ -454,809 +453,839 @@ msgstr "" msgid "Additional fields" msgstr "addita nomines" -#: aleksis/core/menus.py:315 +#: aleksis/core/menus.py:309 +#, fuzzy +#| msgid "Stop impersonation" +msgid "Invite person" +msgstr "Simulandum aliquem finire" + +#: aleksis/core/menus.py:322 #: aleksis/core/templates/core/group/child_groups.html:7 #: aleksis/core/templates/core/group/child_groups.html:9 msgid "Assign child groups to groups" msgstr "" -#: aleksis/core/mixins.py:508 +#: aleksis/core/mixins.py:511 #, fuzzy #| msgid "Edit school term" msgid "Linked school term" msgstr "Muta anum scolae" -#: aleksis/core/models.py:66 +#: aleksis/core/models.py:70 msgid "Boolean (Yes/No)" msgstr "" -#: aleksis/core/models.py:67 +#: aleksis/core/models.py:71 msgid "Text (one line)" msgstr "" -#: aleksis/core/models.py:69 +#: aleksis/core/models.py:73 msgid "Date and time" msgstr "Dies et hora" -#: aleksis/core/models.py:70 +#: aleksis/core/models.py:74 msgid "Decimal number" msgstr "" -#: aleksis/core/models.py:71 aleksis/core/models.py:194 +#: aleksis/core/models.py:75 aleksis/core/models.py:198 msgid "E-mail address" msgstr "Inscriptio electronica" -#: aleksis/core/models.py:72 +#: aleksis/core/models.py:76 msgid "Integer" msgstr "" -#: aleksis/core/models.py:73 +#: aleksis/core/models.py:77 #, fuzzy #| msgid "E-mail address" msgid "IP address" msgstr "Inscriptio electronica" -#: aleksis/core/models.py:74 +#: aleksis/core/models.py:78 msgid "Boolean or empty (Yes/No/Neither)" msgstr "" -#: aleksis/core/models.py:75 +#: aleksis/core/models.py:79 msgid "Text (multi-line)" msgstr "" -#: aleksis/core/models.py:77 +#: aleksis/core/models.py:81 msgid "URL / Link" msgstr "" -#: aleksis/core/models.py:89 aleksis/core/models.py:948 +#: aleksis/core/models.py:93 aleksis/core/models.py:950 msgid "Name" msgstr "Nomen" -#: aleksis/core/models.py:91 +#: aleksis/core/models.py:95 msgid "Start date" msgstr "" -#: aleksis/core/models.py:92 +#: aleksis/core/models.py:96 msgid "End date" msgstr "" -#: aleksis/core/models.py:111 +#: aleksis/core/models.py:115 msgid "The start date must be earlier than the end date." msgstr "" -#: aleksis/core/models.py:118 +#: aleksis/core/models.py:122 msgid "There is already a school term for this time or a part of this time." msgstr "" -#: aleksis/core/models.py:147 aleksis/core/models.py:897 +#: aleksis/core/models.py:151 aleksis/core/models.py:899 msgid "Person" msgstr "Persona" -#: aleksis/core/models.py:150 +#: aleksis/core/models.py:154 #, fuzzy #| msgid "E-mail address" msgid "Can view address" msgstr "Inscriptio electronica" -#: aleksis/core/models.py:151 +#: aleksis/core/models.py:155 #, fuzzy #| msgid "E-mail address" msgid "Can view contact details" msgstr "Inscriptio electronica" -#: aleksis/core/models.py:152 +#: aleksis/core/models.py:156 #, fuzzy #| msgid "E-mail address" msgid "Can view photo" msgstr "Inscriptio electronica" -#: aleksis/core/models.py:153 +#: aleksis/core/models.py:157 #, fuzzy #| msgid "Persons and accounts" msgid "Can view persons groups" msgstr "Personae et computi" -#: aleksis/core/models.py:154 +#: aleksis/core/models.py:158 #, fuzzy #| msgid "Stop impersonation" msgid "Can view personal details" msgstr "Simulandum aliquem finire" -#: aleksis/core/models.py:164 +#: aleksis/core/models.py:168 msgid "female" msgstr "femininum" -#: aleksis/core/models.py:164 +#: aleksis/core/models.py:168 msgid "male" msgstr "maskulinum" -#: aleksis/core/models.py:172 +#: aleksis/core/models.py:176 aleksis/core/models.py:1144 msgid "Linked user" msgstr "" -#: aleksis/core/models.py:174 +#: aleksis/core/models.py:178 #, fuzzy #| msgid "Impersonation" msgid "Is person active?" msgstr "Simulare aliquem" -#: aleksis/core/models.py:176 +#: aleksis/core/models.py:180 msgid "First name" msgstr "Primus nomen" -#: aleksis/core/models.py:177 +#: aleksis/core/models.py:181 msgid "Last name" msgstr "Secondus nomen" -#: aleksis/core/models.py:179 +#: aleksis/core/models.py:183 msgid "Additional name(s)" msgstr "addita nomines" -#: aleksis/core/models.py:183 aleksis/core/models.py:429 +#: aleksis/core/models.py:187 aleksis/core/models.py:431 msgid "Short name" msgstr "Breve nomen" -#: aleksis/core/models.py:186 +#: aleksis/core/models.py:190 msgid "Street" msgstr "Via" -#: aleksis/core/models.py:187 +#: aleksis/core/models.py:191 msgid "Street number" msgstr "Numerus domini" -#: aleksis/core/models.py:188 +#: aleksis/core/models.py:192 msgid "Postal code" msgstr "Numerus directorius" -#: aleksis/core/models.py:189 +#: aleksis/core/models.py:193 msgid "Place" msgstr "Urbs" -#: aleksis/core/models.py:191 +#: aleksis/core/models.py:195 msgid "Home phone" msgstr "Numerus telephoni domi" -#: aleksis/core/models.py:192 +#: aleksis/core/models.py:196 msgid "Mobile phone" msgstr "Numerus telephoni mobilis" -#: aleksis/core/models.py:196 +#: aleksis/core/models.py:200 msgid "Date of birth" msgstr "Dies natalis" -#: aleksis/core/models.py:198 +#: aleksis/core/models.py:201 #, fuzzy #| msgid "Date of birth" msgid "Place of birth" msgstr "Dies natalis" -#: aleksis/core/models.py:200 +#: aleksis/core/models.py:202 msgid "Sex" msgstr "Genus" -#: aleksis/core/models.py:202 +#: aleksis/core/models.py:204 msgid "Photo" msgstr "Photographia" -#: aleksis/core/models.py:206 aleksis/core/templates/core/person/full.html:138 +#: aleksis/core/models.py:208 aleksis/core/templates/core/person/full.html:145 msgid "Guardians / Parents" msgstr "Parentes" -#: aleksis/core/models.py:213 +#: aleksis/core/models.py:215 msgid "Primary group" msgstr "" -#: aleksis/core/models.py:216 aleksis/core/models.py:583 -#: aleksis/core/models.py:607 aleksis/core/models.py:692 -#: aleksis/core/models.py:972 aleksis/core/templates/core/person/full.html:121 +#: aleksis/core/models.py:218 aleksis/core/models.py:585 +#: aleksis/core/models.py:609 aleksis/core/models.py:694 +#: aleksis/core/models.py:974 aleksis/core/templates/core/person/full.html:128 msgid "Description" msgstr "Descriptio" -#: aleksis/core/models.py:384 +#: aleksis/core/models.py:386 msgid "Title of field" msgstr "" -#: aleksis/core/models.py:386 +#: aleksis/core/models.py:388 msgid "Type of field" msgstr "" -#: aleksis/core/models.py:393 +#: aleksis/core/models.py:395 #, fuzzy #| msgid "Additional name(s)" msgid "Addtitional field for groups" msgstr "addita nomines" -#: aleksis/core/models.py:394 +#: aleksis/core/models.py:396 #, fuzzy #| msgid "Additional name(s)" msgid "Addtitional fields for groups" msgstr "addita nomines" -#: aleksis/core/models.py:414 +#: aleksis/core/models.py:416 msgid "Can assign child groups to groups" msgstr "" -#: aleksis/core/models.py:415 +#: aleksis/core/models.py:417 #, fuzzy #| msgid "Persons and accounts" msgid "Can view statistics about group." msgstr "Personae et computi" -#: aleksis/core/models.py:427 +#: aleksis/core/models.py:429 #, fuzzy #| msgid "Last name" msgid "Long name" msgstr "Secondus nomen" -#: aleksis/core/models.py:437 aleksis/core/templates/core/group/full.html:85 +#: aleksis/core/models.py:439 aleksis/core/templates/core/group/full.html:85 msgid "Members" msgstr "" -#: aleksis/core/models.py:440 aleksis/core/templates/core/group/full.html:82 +#: aleksis/core/models.py:442 aleksis/core/templates/core/group/full.html:82 msgid "Owners" msgstr "" -#: aleksis/core/models.py:447 aleksis/core/templates/core/group/full.html:55 +#: aleksis/core/models.py:449 aleksis/core/templates/core/group/full.html:55 msgid "Parent groups" msgstr "" -#: aleksis/core/models.py:455 +#: aleksis/core/models.py:457 msgid "Type of group" msgstr "" -#: aleksis/core/models.py:582 aleksis/core/models.py:606 -#: aleksis/core/models.py:691 +#: aleksis/core/models.py:584 aleksis/core/models.py:608 +#: aleksis/core/models.py:693 #: aleksis/core/templates/core/announcement/list.html:18 msgid "Title" msgstr "Titulus" -#: aleksis/core/models.py:585 +#: aleksis/core/models.py:587 msgid "Application" msgstr "" -#: aleksis/core/models.py:591 +#: aleksis/core/models.py:593 msgid "Activity" msgstr "" -#: aleksis/core/models.py:592 +#: aleksis/core/models.py:594 msgid "Activities" msgstr "" -#: aleksis/core/models.py:598 +#: aleksis/core/models.py:600 msgid "Sender" msgstr "Mittens" -#: aleksis/core/models.py:603 +#: aleksis/core/models.py:605 msgid "Recipient" msgstr "" -#: aleksis/core/models.py:608 aleksis/core/models.py:949 +#: aleksis/core/models.py:610 aleksis/core/models.py:951 msgid "Link" msgstr "" -#: aleksis/core/models.py:610 +#: aleksis/core/models.py:612 msgid "Read" msgstr "" -#: aleksis/core/models.py:611 +#: aleksis/core/models.py:613 msgid "Sent" msgstr "" -#: aleksis/core/models.py:624 +#: aleksis/core/models.py:626 #, fuzzy #| msgid "Notifications" msgid "Notification" msgstr "Nuntii" -#: aleksis/core/models.py:693 +#: aleksis/core/models.py:695 msgid "Link to detailed view" msgstr "" -#: aleksis/core/models.py:696 +#: aleksis/core/models.py:698 msgid "Date and time from when to show" msgstr "" -#: aleksis/core/models.py:699 +#: aleksis/core/models.py:701 msgid "Date and time until when to show" msgstr "" -#: aleksis/core/models.py:724 +#: aleksis/core/models.py:726 #, fuzzy #| msgid "Announcements" msgid "Announcement" msgstr "Nuntii" -#: aleksis/core/models.py:762 +#: aleksis/core/models.py:764 #, fuzzy #| msgid "Announcements" msgid "Announcement recipient" msgstr "Nuntii" -#: aleksis/core/models.py:763 +#: aleksis/core/models.py:765 #, fuzzy #| msgid "Announcements" msgid "Announcement recipients" msgstr "Nuntii" -#: aleksis/core/models.py:818 +#: aleksis/core/models.py:820 #, fuzzy #| msgid "Site title" msgid "Widget Title" msgstr "Titulus paginae" -#: aleksis/core/models.py:819 +#: aleksis/core/models.py:821 msgid "Activate Widget" msgstr "" -#: aleksis/core/models.py:820 +#: aleksis/core/models.py:822 #, fuzzy #| msgid "Site title" msgid "Widget is broken" msgstr "Titulus paginae" -#: aleksis/core/models.py:823 +#: aleksis/core/models.py:825 msgid "Size on mobile devices" msgstr "" -#: aleksis/core/models.py:824 +#: aleksis/core/models.py:826 msgid "<= 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:829 +#: aleksis/core/models.py:831 msgid "Size on tablet devices" msgstr "" -#: aleksis/core/models.py:830 +#: aleksis/core/models.py:832 msgid "> 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:835 +#: aleksis/core/models.py:837 msgid "Size on desktop devices" msgstr "" -#: aleksis/core/models.py:836 +#: aleksis/core/models.py:838 msgid "> 992 px, 12 columns" msgstr "" -#: aleksis/core/models.py:841 +#: aleksis/core/models.py:843 msgid "Size on large desktop devices" msgstr "" -#: aleksis/core/models.py:842 +#: aleksis/core/models.py:844 msgid "> 1200 px>, 12 columns" msgstr "" -#: aleksis/core/models.py:873 +#: aleksis/core/models.py:875 #, fuzzy #| msgid "Dashboard" msgid "Can edit default dashboard" msgstr "Forum" -#: aleksis/core/models.py:874 +#: aleksis/core/models.py:876 #, fuzzy #| msgid "Dashboard" msgid "Dashboard Widget" msgstr "Forum" -#: aleksis/core/models.py:875 +#: aleksis/core/models.py:877 #, fuzzy #| msgid "Dashboard" msgid "Dashboard Widgets" msgstr "Forum" -#: aleksis/core/models.py:881 +#: aleksis/core/models.py:883 msgid "URL" msgstr "" -#: aleksis/core/models.py:882 +#: aleksis/core/models.py:884 #, fuzzy #| msgid "Icon" msgid "Icon URL" msgstr "Nota" -#: aleksis/core/models.py:888 +#: aleksis/core/models.py:890 msgid "External link widget" msgstr "" -#: aleksis/core/models.py:889 +#: aleksis/core/models.py:891 msgid "External link widgets" msgstr "" -#: aleksis/core/models.py:894 +#: aleksis/core/models.py:896 #, fuzzy #| msgid "Dashboard" msgid "Dashboard widget" msgstr "Forum" -#: aleksis/core/models.py:899 +#: aleksis/core/models.py:901 msgid "Order" msgstr "" -#: aleksis/core/models.py:900 +#: aleksis/core/models.py:902 msgid "Part of the default dashboard" msgstr "" -#: aleksis/core/models.py:915 +#: aleksis/core/models.py:917 #, fuzzy #| msgid "Dashboard" msgid "Dashboard widget order" msgstr "Forum" -#: aleksis/core/models.py:916 +#: aleksis/core/models.py:918 #, fuzzy #| msgid "Dashboard" msgid "Dashboard widget orders" msgstr "Forum" -#: aleksis/core/models.py:922 +#: aleksis/core/models.py:924 msgid "Menu ID" msgstr "" -#: aleksis/core/models.py:935 +#: aleksis/core/models.py:937 msgid "Custom menu" msgstr "" -#: aleksis/core/models.py:936 +#: aleksis/core/models.py:938 msgid "Custom menus" msgstr "" -#: aleksis/core/models.py:946 +#: aleksis/core/models.py:948 msgid "Menu" msgstr "" -#: aleksis/core/models.py:950 +#: aleksis/core/models.py:952 msgid "Icon" msgstr "Nota" -#: aleksis/core/models.py:956 +#: aleksis/core/models.py:958 msgid "Custom menu item" msgstr "" -#: aleksis/core/models.py:957 +#: aleksis/core/models.py:959 msgid "Custom menu items" msgstr "" -#: aleksis/core/models.py:971 +#: aleksis/core/models.py:973 msgid "Title of type" msgstr "" -#: aleksis/core/models.py:978 aleksis/core/templates/core/group/full.html:47 +#: aleksis/core/models.py:980 aleksis/core/templates/core/group/full.html:47 #, fuzzy #| msgid "Group" msgid "Group type" msgstr "Grex" -#: aleksis/core/models.py:992 +#: aleksis/core/models.py:994 #, fuzzy #| msgid "System status" msgid "Can view system status" msgstr "Status systemae" -#: aleksis/core/models.py:993 +#: aleksis/core/models.py:995 #, fuzzy #| msgid "Data management" msgid "Can manage data" msgstr "Adminstratio datarum" -#: aleksis/core/models.py:994 +#: aleksis/core/models.py:996 #, fuzzy #| msgid "Stop impersonation" msgid "Can impersonate" msgstr "Simulandum aliquem finire" -#: aleksis/core/models.py:995 +#: aleksis/core/models.py:997 msgid "Can use search" msgstr "" -#: aleksis/core/models.py:996 +#: aleksis/core/models.py:998 msgid "Can change site preferences" msgstr "" -#: aleksis/core/models.py:997 +#: aleksis/core/models.py:999 msgid "Can change person preferences" msgstr "" -#: aleksis/core/models.py:998 +#: aleksis/core/models.py:1000 msgid "Can change group preferences" msgstr "" -#: aleksis/core/models.py:999 +#: aleksis/core/models.py:1001 msgid "Can test PDF generation" msgstr "" -#: aleksis/core/models.py:1035 +#: aleksis/core/models.py:1037 msgid "Related data check task" msgstr "" -#: aleksis/core/models.py:1043 +#: aleksis/core/models.py:1045 msgid "Issue solved" msgstr "" -#: aleksis/core/models.py:1044 +#: aleksis/core/models.py:1046 #, fuzzy #| msgid "Notifications" msgid "Notification sent" msgstr "Nuntii" -#: aleksis/core/models.py:1057 +#: aleksis/core/models.py:1059 msgid "Data check result" msgstr "" -#: aleksis/core/models.py:1058 +#: aleksis/core/models.py:1060 msgid "Data check results" msgstr "" -#: aleksis/core/models.py:1060 +#: aleksis/core/models.py:1062 msgid "Can run data checks" msgstr "" -#: aleksis/core/models.py:1061 +#: aleksis/core/models.py:1063 msgid "Can solve data check problems" msgstr "" -#: aleksis/core/models.py:1076 +#: aleksis/core/models.py:1070 +#, fuzzy +#| msgid "E-mail address" +msgid "E-Mail address" +msgstr "Inscriptio electronica" + +#: aleksis/core/models.py:1094 msgid "Owner" msgstr "" -#: aleksis/core/models.py:1080 +#: aleksis/core/models.py:1098 msgid "File expires at" msgstr "" -#: aleksis/core/models.py:1082 +#: aleksis/core/models.py:1100 msgid "Generated HTML file" msgstr "" -#: aleksis/core/models.py:1084 +#: aleksis/core/models.py:1102 msgid "Generated PDF file" msgstr "" -#: aleksis/core/models.py:1091 +#: aleksis/core/models.py:1109 msgid "PDF file" msgstr "" -#: aleksis/core/models.py:1092 +#: aleksis/core/models.py:1110 msgid "PDF files" msgstr "" -#: aleksis/core/models.py:1097 +#: aleksis/core/models.py:1115 msgid "Task result" msgstr "" -#: aleksis/core/models.py:1100 +#: aleksis/core/models.py:1118 msgid "Task user" msgstr "" -#: aleksis/core/models.py:1112 +#: aleksis/core/models.py:1130 msgid "Task user assignment" msgstr "" -#: aleksis/core/models.py:1113 +#: aleksis/core/models.py:1131 msgid "Task user assignments" msgstr "" -#: aleksis/core/models.py:1127 +#: aleksis/core/models.py:1147 +#, fuzzy +#| msgid "Additional name(s)" +msgid "Additional attributes" +msgstr "addita nomines" + +#: aleksis/core/models.py:1185 msgid "Allowed scopes that clients can request" msgstr "" -#: aleksis/core/preferences.py:23 +#: aleksis/core/preferences.py:24 msgid "General" msgstr "" -#: aleksis/core/preferences.py:24 +#: aleksis/core/preferences.py:25 msgid "School" msgstr "Scola" -#: aleksis/core/preferences.py:25 +#: aleksis/core/preferences.py:26 msgid "Theme" msgstr "" -#: aleksis/core/preferences.py:26 +#: aleksis/core/preferences.py:27 msgid "Mail" msgstr "" -#: aleksis/core/preferences.py:28 +#: aleksis/core/preferences.py:29 msgid "Footer" msgstr "" -#: aleksis/core/preferences.py:29 +#: aleksis/core/preferences.py:30 #, fuzzy #| msgid "Data management" msgid "Accounts" msgstr "Adminstratio datarum" -#: aleksis/core/preferences.py:30 +#: aleksis/core/preferences.py:31 #, fuzzy #| msgid "Notifications" msgid "Authentication" msgstr "Nuntii" -#: aleksis/core/preferences.py:31 +#: aleksis/core/preferences.py:32 #, fuzzy #| msgid "Impersonation" msgid "Internationalisation" msgstr "Simulare aliquem" -#: aleksis/core/preferences.py:42 +#: aleksis/core/preferences.py:43 msgid "Site title" msgstr "Titulus paginae" -#: aleksis/core/preferences.py:53 +#: aleksis/core/preferences.py:54 msgid "Site description" msgstr "Descriptio paginae" -#: aleksis/core/preferences.py:64 +#: aleksis/core/preferences.py:65 msgid "Primary colour" msgstr "" -#: aleksis/core/preferences.py:76 +#: aleksis/core/preferences.py:77 msgid "Secondary colour" msgstr "" -#: aleksis/core/preferences.py:87 +#: aleksis/core/preferences.py:88 #, fuzzy #| msgid "Logout" msgid "Logo" msgstr "nomen retractare" -#: aleksis/core/preferences.py:97 +#: aleksis/core/preferences.py:98 msgid "Favicon" msgstr "" -#: aleksis/core/preferences.py:107 +#: aleksis/core/preferences.py:108 #, fuzzy #| msgid "Icon" msgid "PWA-Icon" msgstr "Nota" -#: aleksis/core/preferences.py:118 +#: aleksis/core/preferences.py:119 #, fuzzy #| msgid "Last name" msgid "Mail out name" msgstr "Secondus nomen" -#: aleksis/core/preferences.py:129 +#: aleksis/core/preferences.py:130 #, fuzzy #| msgid "E-mail address" msgid "Mail out address" msgstr "Inscriptio electronica" -#: aleksis/core/preferences.py:141 +#: aleksis/core/preferences.py:142 msgid "Link to privacy policy" msgstr "" -#: aleksis/core/preferences.py:153 +#: aleksis/core/preferences.py:154 msgid "Link to imprint" msgstr "" -#: aleksis/core/preferences.py:165 +#: aleksis/core/preferences.py:166 msgid "Name format for addressing" msgstr "" -#: aleksis/core/preferences.py:181 +#: aleksis/core/preferences.py:182 msgid "Channels to use for notifications" msgstr "" -#: aleksis/core/preferences.py:193 +#: aleksis/core/preferences.py:194 msgid "Regular expression to match primary group, e.g. '^Class .*'" msgstr "" -#: aleksis/core/preferences.py:204 +#: aleksis/core/preferences.py:205 msgid "Field on person to match primary group against" msgstr "" -#: aleksis/core/preferences.py:216 +#: aleksis/core/preferences.py:217 msgid "Automatically create new persons for new users" msgstr "" -#: aleksis/core/preferences.py:225 +#: aleksis/core/preferences.py:226 msgid "Automatically link existing persons to new users by their e-mail address" msgstr "" -#: aleksis/core/preferences.py:236 +#: aleksis/core/preferences.py:237 msgid "Display name of the school" msgstr "" -#: aleksis/core/preferences.py:247 +#: aleksis/core/preferences.py:248 msgid "Official name of the school, e.g. as given by supervisory authority" msgstr "Officialis nomen scolae, e. g." -#: aleksis/core/preferences.py:255 +#: aleksis/core/preferences.py:256 msgid "Allow users to change their passwords" msgstr "" -#: aleksis/core/preferences.py:263 +#: aleksis/core/preferences.py:264 msgid "Enable signup" msgstr "" -#: aleksis/core/preferences.py:274 +#: aleksis/core/preferences.py:272 +msgid "Enable invitations" +msgstr "" + +#: aleksis/core/preferences.py:280 +msgid "Length of invite code. (Default 3: abcde-acbde-abcde)" +msgstr "" + +#: aleksis/core/preferences.py:288 +msgid "Size of packets. (Default 5: abcde)" +msgstr "" + +#: aleksis/core/preferences.py:298 #, fuzzy #| msgid "E-mail address" msgid "Allowed Grant Flows for OAuth applications" msgstr "Inscriptio electronica" -#: aleksis/core/preferences.py:287 +#: aleksis/core/preferences.py:311 msgid "Available languages" msgstr "" -#: aleksis/core/preferences.py:299 +#: aleksis/core/preferences.py:323 msgid "Send emails if data checks detect problems" msgstr "" -#: aleksis/core/preferences.py:310 +#: aleksis/core/preferences.py:334 msgid "Email recipients for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:321 +#: aleksis/core/preferences.py:345 msgid "Email recipient groups for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:330 +#: aleksis/core/preferences.py:354 msgid "Show dashboard to users without login" msgstr "" -#: aleksis/core/preferences.py:339 +#: aleksis/core/preferences.py:363 msgid "Allow users to edit their dashboard" msgstr "" -#: aleksis/core/preferences.py:350 +#: aleksis/core/preferences.py:374 msgid "Fields on person model which are editable by themselves." msgstr "" -#: aleksis/core/preferences.py:364 +#: aleksis/core/preferences.py:388 msgid "Editable fields on person model which should trigger a notification on change" msgstr "" -#: aleksis/core/preferences.py:377 +#: aleksis/core/preferences.py:401 msgid "Contact for notification if a person changes their data" msgstr "" -#: aleksis/core/preferences.py:387 +#: aleksis/core/preferences.py:411 msgid "PDF file expiration duration" msgstr "" -#: aleksis/core/preferences.py:388 +#: aleksis/core/preferences.py:412 msgid "in minutes" msgstr "" -#: aleksis/core/preferences.py:398 +#: aleksis/core/preferences.py:422 msgid "Automatically update the dashboard and its widgets" msgstr "" -#: aleksis/core/preferences.py:408 +#: aleksis/core/preferences.py:432 msgid "Automatically update the dashboard and its widgets sitewide" msgstr "" -#: aleksis/core/settings.py:474 +#: aleksis/core/settings.py:507 msgid "English" msgstr "Britannicus" -#: aleksis/core/settings.py:475 +#: aleksis/core/settings.py:508 msgid "German" msgstr "Germanus" -#: aleksis/core/tables.py:19 +#: aleksis/core/tables.py:24 #: aleksis/core/templates/core/announcement/list.html:36 #: aleksis/core/templates/core/group/full.html:24 -#: aleksis/core/templates/core/person/full.html:23 +#: aleksis/core/templates/core/person/full.html:24 #: aleksis/core/templates/oauth2_provider/application/detail.html:17 msgid "Edit" msgstr "" -#: aleksis/core/tables.py:21 aleksis/core/tables.py:89 -#: aleksis/core/tables.py:105 +#: aleksis/core/tables.py:26 aleksis/core/tables.py:94 +#: aleksis/core/tables.py:137 #: aleksis/core/templates/core/announcement/list.html:22 #, fuzzy #| msgid "Notifications" msgid "Actions" msgstr "Nuntii" -#: aleksis/core/tables.py:56 aleksis/core/tables.py:57 -#: aleksis/core/tables.py:71 aleksis/core/tables.py:87 -#: aleksis/core/tables.py:103 +#: aleksis/core/tables.py:61 aleksis/core/tables.py:62 +#: aleksis/core/tables.py:76 aleksis/core/tables.py:92 +#: aleksis/core/tables.py:135 #: aleksis/core/templates/core/announcement/list.html:42 #: aleksis/core/templates/core/group/full.html:31 #: aleksis/core/templates/core/pages/delete.html:22 -#: aleksis/core/templates/core/person/full.html:30 +#: aleksis/core/templates/core/person/full.html:31 #: aleksis/core/templates/oauth2_provider/application/detail.html:21 msgid "Delete" msgstr "" @@ -1328,11 +1357,11 @@ msgstr "" msgid "Account inactive" msgstr "" -#: aleksis/core/templates/account/account_inactive.html:13 +#: aleksis/core/templates/account/account_inactive.html:14 msgid "Account inactive." msgstr "" -#: aleksis/core/templates/account/account_inactive.html:15 +#: aleksis/core/templates/account/account_inactive.html:17 msgid "" "\n" " This account is currently inactive. If you think this is an\n" @@ -1486,11 +1515,11 @@ msgstr "" msgid "Signup closed" msgstr "" -#: aleksis/core/templates/account/signup_closed.html:13 +#: aleksis/core/templates/account/signup_closed.html:14 msgid "Signup closed." msgstr "" -#: aleksis/core/templates/account/signup_closed.html:15 +#: aleksis/core/templates/account/signup_closed.html:17 msgid "" "\n" " This sign up is currently closed. If you think this is an\n" @@ -1530,11 +1559,6 @@ msgid "" " " msgstr "" -#: aleksis/core/templates/account/verification_sent.html:30 -#, python-format -msgid "<strong>Note:</strong> you can still <a href=\"%(email_url)s\">change your e-mail address</a>" -msgstr "" - #: aleksis/core/templates/core/additional_field/edit.html:6 #: aleksis/core/templates/core/additional_field/edit.html:7 #, fuzzy @@ -1597,11 +1621,11 @@ msgid "Logged in as" msgstr "" #: aleksis/core/templates/core/base.html:175 -msgid "About AlekSIS — The Free School Information System" +msgid "About AlekSIS® — The Free School Information System" msgstr "" #: aleksis/core/templates/core/base.html:183 -msgid "Impress" +msgid "Imprint" msgstr "" #: aleksis/core/templates/core/base.html:191 @@ -1609,7 +1633,7 @@ msgid "Privacy Policy" msgstr "" #: aleksis/core/templates/core/base_print.html:72 -msgid "Powered by AlekSIS" +msgid "Powered by AlekSIS®" msgstr "" #: aleksis/core/templates/core/dashboard_widget/create.html:8 @@ -1838,7 +1862,7 @@ msgid "Edit group" msgstr "" #: aleksis/core/templates/core/group/full.html:38 -#: aleksis/core/templates/core/person/full.html:37 +#: aleksis/core/templates/core/person/full.html:38 msgid "Change preferences" msgstr "" @@ -1937,38 +1961,48 @@ msgid "No notifications available yet." msgstr "" #: aleksis/core/templates/core/pages/about.html:6 -#: aleksis/core/templates/core/pages/about.html:15 -msgid "About AlekSIS" +msgid "About AlekSIS®" msgstr "" #: aleksis/core/templates/core/pages/about.html:7 -msgid "AlekSIS – The Free School Information System" +msgid "AlekSIS® – The Free School Information System" +msgstr "" + +#: aleksis/core/templates/core/pages/about.html:15 +msgid "About AlekSIS" msgstr "" #: aleksis/core/templates/core/pages/about.html:17 msgid "" "\n" -" This platform is powered by AlekSIS, a web-based school information system (SIS) which can be used\n" +" This platform is powered by AlekSIS®, a web-based school information system (SIS) which can be used\n" " to manage and/or publish organisational artifacts of educational institutions. AlekSIS is free software and\n" " can be used by anyone.\n" " " msgstr "" -#: aleksis/core/templates/core/pages/about.html:25 +#: aleksis/core/templates/core/pages/about.html:24 +msgid "" +"\n" +" AlekSIS® is a registered trademark of the AlekSIS open source project, represented by Teckids e.V.\n" +" " +msgstr "" + +#: aleksis/core/templates/core/pages/about.html:30 msgid "Website of AlekSIS" msgstr "" -#: aleksis/core/templates/core/pages/about.html:26 +#: aleksis/core/templates/core/pages/about.html:31 msgid "Source code" msgstr "" -#: aleksis/core/templates/core/pages/about.html:35 +#: aleksis/core/templates/core/pages/about.html:40 #, fuzzy #| msgid "Edit school information" msgid "Licence information" msgstr "Muta informationes scolae" -#: aleksis/core/templates/core/pages/about.html:37 +#: aleksis/core/templates/core/pages/about.html:42 msgid "" "\n" " The core and the official apps of AlekSIS are licenced under the EUPL, version 1.2 or later. For licence\n" @@ -1977,25 +2011,25 @@ msgid "" " " msgstr "" -#: aleksis/core/templates/core/pages/about.html:45 +#: aleksis/core/templates/core/pages/about.html:50 msgid "Free/Open Source Licence" msgstr "" -#: aleksis/core/templates/core/pages/about.html:46 +#: aleksis/core/templates/core/pages/about.html:51 msgid "Other Licence" msgstr "" -#: aleksis/core/templates/core/pages/about.html:50 +#: aleksis/core/templates/core/pages/about.html:55 msgid "Full licence text" msgstr "" -#: aleksis/core/templates/core/pages/about.html:51 +#: aleksis/core/templates/core/pages/about.html:56 #, fuzzy #| msgid "Edit school information" msgid "More information about the EUPL" msgstr "Muta informationes scolae" -#: aleksis/core/templates/core/pages/about.html:90 +#: aleksis/core/templates/core/pages/about.html:95 #, python-format msgid "" "\n" @@ -2248,19 +2282,23 @@ msgstr "Simulandum aliquem finire" msgid "Edit person" msgstr "" -#: aleksis/core/templates/core/person/full.html:44 -#: aleksis/core/templates/impersonate/list_users.html:7 -#: aleksis/core/templates/impersonate/list_users.html:8 +#: aleksis/core/templates/core/person/full.html:45 #, fuzzy #| msgid "Impersonation" msgid "Impersonate" msgstr "Simulare aliquem" -#: aleksis/core/templates/core/person/full.html:50 +#: aleksis/core/templates/core/person/full.html:51 +#, fuzzy +#| msgid "Impersonation" +msgid "Invite user" +msgstr "Simulare aliquem" + +#: aleksis/core/templates/core/person/full.html:57 msgid "Contact details" msgstr "" -#: aleksis/core/templates/core/person/full.html:131 +#: aleksis/core/templates/core/person/full.html:138 msgid "Children" msgstr "" @@ -2302,6 +2340,51 @@ msgstr "" msgid "Save preferences" msgstr "" +#: aleksis/core/templates/invitations/enter.html:21 +msgid "Accept your invitation" +msgstr "" + +#: aleksis/core/templates/invitations/enter.html:25 +msgid "" +"\n" +" Please enter your invitation code to register\n" +" your new user account:\n" +" " +msgstr "" + +#: aleksis/core/templates/invitations/enter.html:37 +msgid "Accept invite" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:9 +#: aleksis/core/templates/invitations/forms/_invite.html:10 +#: aleksis/core/templates/invitations/forms/_invite.html:21 +msgid "Invite" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:17 +#, fuzzy +#| msgid "E-mail address" +msgid "Invite by email address" +msgstr "Inscriptio electronica" + +#: aleksis/core/templates/invitations/forms/_invite.html:26 +msgid "Generate invitation code" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:29 +msgid "Generate code" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:33 +msgid "Invitations" +msgstr "" + +#: aleksis/core/templates/invitations/messages/invite_accepted.txt:3 +#, python-format +msgid "The invitation for %(email)s has been accepted." +msgstr "" + #: aleksis/core/templates/oauth2_provider/application/create.html:5 #: aleksis/core/templates/oauth2_provider/application/create.html:6 #, fuzzy @@ -2981,153 +3064,169 @@ msgstr "" msgid "SMS" msgstr "" -#: aleksis/core/util/pdf.py:105 +#: aleksis/core/util/pdf.py:113 msgid "Progress: Generate PDF file" msgstr "" -#: aleksis/core/util/pdf.py:106 +#: aleksis/core/util/pdf.py:114 msgid "Generating PDF file …" msgstr "" -#: aleksis/core/util/pdf.py:107 +#: aleksis/core/util/pdf.py:115 msgid "The PDF file has been generated successfully." msgstr "" -#: aleksis/core/util/pdf.py:108 +#: aleksis/core/util/pdf.py:116 msgid "There was a problem while generating the PDF file." msgstr "" -#: aleksis/core/util/pdf.py:111 +#: aleksis/core/util/pdf.py:119 msgid "Download PDF" msgstr "" -#: aleksis/core/views.py:270 +#: aleksis/core/views.py:280 msgid "The school term has been created." msgstr "" -#: aleksis/core/views.py:282 +#: aleksis/core/views.py:292 msgid "The school term has been saved." msgstr "" -#: aleksis/core/views.py:406 +#: aleksis/core/views.py:416 msgid "The child groups were successfully saved." msgstr "" -#: aleksis/core/views.py:425 aleksis/core/views.py:435 +#: aleksis/core/views.py:435 aleksis/core/views.py:445 msgid "The person has been saved." msgstr "" -#: aleksis/core/views.py:485 +#: aleksis/core/views.py:495 msgid "The group has been saved." msgstr "" -#: aleksis/core/views.py:582 +#: aleksis/core/views.py:592 msgid "The announcement has been saved." msgstr "" -#: aleksis/core/views.py:598 +#: aleksis/core/views.py:608 msgid "The announcement has been deleted." msgstr "" -#: aleksis/core/views.py:682 +#: aleksis/core/views.py:695 msgid "The preferences have been saved successfully." msgstr "" -#: aleksis/core/views.py:706 +#: aleksis/core/views.py:719 msgid "The person has been deleted." msgstr "" -#: aleksis/core/views.py:720 +#: aleksis/core/views.py:733 msgid "The group has been deleted." msgstr "" -#: aleksis/core/views.py:752 +#: aleksis/core/views.py:765 msgid "The additional_field has been saved." msgstr "" -#: aleksis/core/views.py:786 +#: aleksis/core/views.py:799 msgid "The additional field has been deleted." msgstr "" -#: aleksis/core/views.py:811 +#: aleksis/core/views.py:824 msgid "The group type has been saved." msgstr "" -#: aleksis/core/views.py:841 +#: aleksis/core/views.py:854 msgid "The group type has been deleted." msgstr "" -#: aleksis/core/views.py:874 +#: aleksis/core/views.py:887 msgid "Progress: Run data checks" msgstr "" -#: aleksis/core/views.py:875 +#: aleksis/core/views.py:888 #, fuzzy #| msgid "System status" msgid "Run data checks …" msgstr "Status systemae" -#: aleksis/core/views.py:876 +#: aleksis/core/views.py:889 msgid "The data checks were run successfully." msgstr "" -#: aleksis/core/views.py:877 +#: aleksis/core/views.py:890 msgid "There was a problem while running data checks." msgstr "" -#: aleksis/core/views.py:893 +#: aleksis/core/views.py:906 #, python-brace-format msgid "The solve option '{solve_option_obj.verbose_name}' " msgstr "" -#: aleksis/core/views.py:935 +#: aleksis/core/views.py:948 msgid "The dashboard widget has been saved." msgstr "" -#: aleksis/core/views.py:965 +#: aleksis/core/views.py:978 msgid "The dashboard widget has been created." msgstr "" -#: aleksis/core/views.py:975 +#: aleksis/core/views.py:988 msgid "The dashboard widget has been deleted." msgstr "" -#: aleksis/core/views.py:1042 +#: aleksis/core/views.py:1055 msgid "Your dashboard configuration has been saved successfully." msgstr "" -#: aleksis/core/views.py:1044 +#: aleksis/core/views.py:1057 msgid "The configuration of the default dashboard has been saved successfully." msgstr "" -#: aleksis/core/views.py:1139 +#: aleksis/core/views.py:1127 +#, python-brace-format +msgid "The invitation was successfully created. The invitation code is {code}" +msgstr "" + +#: aleksis/core/views.py:1218 msgid "We have successfully assigned the permissions." msgstr "" -#: aleksis/core/views.py:1149 +#: aleksis/core/views.py:1228 msgid "The global user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1159 +#: aleksis/core/views.py:1238 msgid "The global group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1169 +#: aleksis/core/views.py:1248 msgid "The object user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1179 +#: aleksis/core/views.py:1258 msgid "The object group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1298 +#: aleksis/core/views.py:1377 msgid "The third-party account could not be disconnected because it is the only login method available." msgstr "" -#: aleksis/core/views.py:1305 +#: aleksis/core/views.py:1384 msgid "The third-party account has been successfully disconnected." msgstr "" +#: aleksis/core/views.py:1441 +msgid "Person was invited successfully." +msgstr "" + +#: aleksis/core/views.py:1443 +msgid "Person was already invited." +msgstr "" + +#~ msgid "Impersonation" +#~ msgstr "Simulare aliquem" + #, fuzzy #~| msgid "Notifications" #~ msgid "OAuth2 applications" @@ -3146,11 +3245,6 @@ msgstr "" #~ msgid "Link persons to accounts" #~ msgstr "Personae et computi" -#, fuzzy -#~| msgid "Impersonation" -#~ msgid "Impersonate user" -#~ msgstr "Simulare aliquem" - #~ msgid "School logo" #~ msgstr "Imago scolae" diff --git a/aleksis/core/locale/la/LC_MESSAGES/djangojs.po b/aleksis/core/locale/la/LC_MESSAGES/djangojs.po index 2458849847f712fe1cf63743640716c5b3ef561a..d67bdb0055bf1ee96915909ce9e21023085c466b 100644 --- a/aleksis/core/locale/la/LC_MESSAGES/djangojs.po +++ b/aleksis/core/locale/la/LC_MESSAGES/djangojs.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-29 09:59+0100\n" +"POT-Creation-Date: 2021-12-28 12:14+0100\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" @@ -29,6 +29,6 @@ msgstr "" msgid "OK" msgstr "" -#: aleksis/core/static/js/main.js:127 +#: aleksis/core/static/js/main.js:128 msgid "This page may contain outdated information since there is no internet connection." msgstr "" diff --git a/aleksis/core/locale/nb_NO/LC_MESSAGES/django.po b/aleksis/core/locale/nb_NO/LC_MESSAGES/django.po index cf83adad715c4a2b0d4b804801f281e508de8367..e40c13ef84618ccb0eb3bd58c524f81e00fe8834 100644 --- a/aleksis/core/locale/nb_NO/LC_MESSAGES/django.po +++ b/aleksis/core/locale/nb_NO/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: AlekSIS (School Information System) 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-29 09:59+0100\n" +"POT-Creation-Date: 2021-12-28 12:13+0100\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" @@ -17,26 +17,33 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: aleksis/core/apps.py:151 +#: aleksis/core/apps.py:152 msgid "OpenID Connect scope" msgstr "" -#: aleksis/core/apps.py:152 +#: aleksis/core/apps.py:153 msgid "Given name, family name, link to profile and picture if existing." msgstr "" -#: aleksis/core/apps.py:153 +#: aleksis/core/apps.py:154 msgid "Full home postal address" msgstr "" -#: aleksis/core/apps.py:154 +#: aleksis/core/apps.py:155 msgid "Email address" msgstr "" -#: aleksis/core/apps.py:155 +#: aleksis/core/apps.py:156 msgid "Home and mobile phone" msgstr "" +#: aleksis/core/apps.py:157 aleksis/core/forms.py:223 aleksis/core/menus.py:265 +#: aleksis/core/models.py:414 aleksis/core/templates/core/group/list.html:8 +#: aleksis/core/templates/core/group/list.html:9 +#: aleksis/core/templates/core/person/full.html:152 +msgid "Groups" +msgstr "" + #: aleksis/core/data_checks.py:55 msgid "Ignore problem" msgstr "" @@ -83,156 +90,148 @@ msgstr "" msgid "Content type" msgstr "" -#: aleksis/core/filters.py:112 aleksis/core/models.py:579 +#: aleksis/core/filters.py:112 aleksis/core/models.py:581 msgid "User" msgstr "" -#: aleksis/core/filters.py:134 aleksis/core/models.py:411 +#: aleksis/core/filters.py:134 aleksis/core/models.py:413 msgid "Group" msgstr "" -#: aleksis/core/forms.py:46 aleksis/core/forms.py:514 +#: aleksis/core/forms.py:48 aleksis/core/forms.py:559 msgid "Base data" msgstr "" -#: aleksis/core/forms.py:52 +#: aleksis/core/forms.py:54 msgid "Address" msgstr "" -#: aleksis/core/forms.py:53 +#: aleksis/core/forms.py:55 aleksis/core/forms.py:568 msgid "Contact data" msgstr "" -#: aleksis/core/forms.py:55 +#: aleksis/core/forms.py:57 msgid "Advanced personal data" msgstr "" -#: aleksis/core/forms.py:103 +#: aleksis/core/forms.py:105 msgid "New user" msgstr "" -#: aleksis/core/forms.py:103 +#: aleksis/core/forms.py:105 msgid "Create a new account" msgstr "" -#: aleksis/core/forms.py:134 +#: aleksis/core/forms.py:136 msgid "You cannot set a new username when also selecting an existing user." msgstr "" -#: aleksis/core/forms.py:138 +#: aleksis/core/forms.py:140 msgid "This username is already in use." msgstr "" -#: aleksis/core/forms.py:155 aleksis/core/models.py:125 +#: aleksis/core/forms.py:157 aleksis/core/models.py:129 msgid "School term" msgstr "" -#: aleksis/core/forms.py:156 +#: aleksis/core/forms.py:158 msgid "Common data" msgstr "" -#: aleksis/core/forms.py:157 aleksis/core/forms.py:208 -#: aleksis/core/menus.py:256 aleksis/core/models.py:148 +#: aleksis/core/forms.py:159 aleksis/core/forms.py:210 +#: aleksis/core/menus.py:254 aleksis/core/models.py:152 #: aleksis/core/templates/core/person/list.html:8 #: aleksis/core/templates/core/person/list.html:9 msgid "Persons" msgstr "" -#: aleksis/core/forms.py:158 +#: aleksis/core/forms.py:160 aleksis/core/forms.py:570 msgid "Additional data" msgstr "" -#: aleksis/core/forms.py:200 aleksis/core/forms.py:203 -#: aleksis/core/models.py:68 +#: aleksis/core/forms.py:202 aleksis/core/forms.py:205 +#: aleksis/core/models.py:72 msgid "Date" msgstr "" -#: aleksis/core/forms.py:201 aleksis/core/forms.py:204 -#: aleksis/core/models.py:76 +#: aleksis/core/forms.py:203 aleksis/core/forms.py:206 +#: aleksis/core/models.py:80 msgid "Time" msgstr "" -#: aleksis/core/forms.py:221 aleksis/core/menus.py:267 -#: aleksis/core/models.py:412 aleksis/core/templates/core/group/list.html:8 -#: aleksis/core/templates/core/group/list.html:9 -#: aleksis/core/templates/core/person/full.html:145 -msgid "Groups" -msgstr "" - -#: aleksis/core/forms.py:234 +#: aleksis/core/forms.py:236 msgid "From when until when should the announcement be displayed?" msgstr "" -#: aleksis/core/forms.py:237 +#: aleksis/core/forms.py:239 msgid "Who should see the announcement?" msgstr "" -#: aleksis/core/forms.py:238 +#: aleksis/core/forms.py:240 msgid "Write your announcement:" msgstr "" -#: aleksis/core/forms.py:277 +#: aleksis/core/forms.py:279 msgid "You are not allowed to create announcements which are only valid in the past." msgstr "" -#: aleksis/core/forms.py:281 +#: aleksis/core/forms.py:283 msgid "The from date and time must be earlier then the until date and time." msgstr "" -#: aleksis/core/forms.py:290 +#: aleksis/core/forms.py:292 msgid "You need at least one recipient." msgstr "" -#: aleksis/core/forms.py:411 +#: aleksis/core/forms.py:401 +msgid "Invitation code" +msgstr "" + +#: aleksis/core/forms.py:402 +msgid "Please enter your invitation code." +msgstr "" + +#: aleksis/core/forms.py:434 msgid "Who should get the permission?" msgstr "" -#: aleksis/core/forms.py:412 +#: aleksis/core/forms.py:435 msgid "On what?" msgstr "" -#: aleksis/core/forms.py:438 +#: aleksis/core/forms.py:461 msgid "Select objects which the permission should be granted for:" msgstr "" -#: aleksis/core/forms.py:441 +#: aleksis/core/forms.py:464 msgid "Grant the permission for all objects" msgstr "" -#: aleksis/core/forms.py:449 +#: aleksis/core/forms.py:472 msgid "You must select at least one group or person which should get the permission." msgstr "" -#: aleksis/core/forms.py:454 +#: aleksis/core/forms.py:477 msgid "You must grant the permission to all objects and/or to some objects." msgstr "" -#: aleksis/core/forms.py:518 -msgid "Account data" +#: aleksis/core/forms.py:564 +msgid "Adress data" msgstr "" -#: aleksis/core/forms.py:524 -msgid "Consents" +#: aleksis/core/forms.py:576 +msgid "Account data" msgstr "" -#: aleksis/core/forms.py:531 +#: aleksis/core/forms.py:583 msgid "Password" msgstr "" -#: aleksis/core/forms.py:537 +#: aleksis/core/forms.py:586 msgid "Password (again)" msgstr "" -#: aleksis/core/forms.py:550 -#, python-brace-format -msgid "I have read the <a href='{privacy_policy}'>Privacy policy</a> and agree with them." -msgstr "" - -#: aleksis/core/forms.py:575 -msgid "You must type the same password each time." -msgstr "" - -#: aleksis/core/forms.py:720 +#: aleksis/core/forms.py:752 msgid "No valid selection." msgstr "" @@ -240,24 +239,20 @@ msgstr "" msgid "There are unresolved data problems." msgstr "" -#: aleksis/core/health_checks.py:38 -msgid "The backup folder doesn't exist." -msgstr "" - -#: aleksis/core/health_checks.py:47 +#: aleksis/core/health_checks.py:44 #, python-brace-format msgid "Last backup {time_gone_since_backup}!" msgstr "" -#: aleksis/core/health_checks.py:49 +#: aleksis/core/health_checks.py:46 msgid "No backup found!" msgstr "" -#: aleksis/core/health_checks.py:76 +#: aleksis/core/health_checks.py:73 msgid "No backup result found!" msgstr "" -#: aleksis/core/health_checks.py:78 +#: aleksis/core/health_checks.py:75 #, python-brace-format msgid "{task.status} - {task.result}" msgstr "" @@ -273,34 +268,38 @@ msgstr "" msgid "Sign up" msgstr "" -#: aleksis/core/menus.py:24 +#: aleksis/core/menus.py:24 aleksis/core/templates/invitations/enter.html:7 +msgid "Accept invitation" +msgstr "" + +#: aleksis/core/menus.py:33 msgid "Dashboard" msgstr "" -#: aleksis/core/menus.py:32 aleksis/core/models.py:625 -#: aleksis/core/preferences.py:27 +#: aleksis/core/menus.py:41 aleksis/core/models.py:627 +#: aleksis/core/preferences.py:28 #: aleksis/core/templates/core/notifications.html:4 #: aleksis/core/templates/core/notifications.html:5 msgid "Notifications" msgstr "" -#: aleksis/core/menus.py:44 +#: aleksis/core/menus.py:53 msgid "Account" msgstr "" -#: aleksis/core/menus.py:51 +#: aleksis/core/menus.py:60 msgid "Stop impersonation" msgstr "" -#: aleksis/core/menus.py:60 aleksis/core/templates/core/base.html:80 +#: aleksis/core/menus.py:69 aleksis/core/templates/core/base.html:80 msgid "Logout" msgstr "" -#: aleksis/core/menus.py:66 +#: aleksis/core/menus.py:75 msgid "2FA" msgstr "" -#: aleksis/core/menus.py:74 +#: aleksis/core/menus.py:83 #: aleksis/core/templates/account/password_change.html:5 #: aleksis/core/templates/account/password_change.html:6 #: aleksis/core/templates/account/password_change.html:19 @@ -312,830 +311,850 @@ msgstr "" msgid "Change password" msgstr "" -#: aleksis/core/menus.py:86 +#: aleksis/core/menus.py:95 msgid "Me" msgstr "" -#: aleksis/core/menus.py:95 +#: aleksis/core/menus.py:104 #: aleksis/core/templates/dynamic_preferences/form.html:5 msgid "Preferences" msgstr "" -#: aleksis/core/menus.py:104 +#: aleksis/core/menus.py:113 msgid "Third-party accounts" msgstr "" -#: aleksis/core/menus.py:113 +#: aleksis/core/menus.py:122 #: aleksis/core/templates/oauth2_provider/authorized-tokens.html:5 #: aleksis/core/templates/oauth2_provider/authorized-tokens.html:6 msgid "Authorized applications" msgstr "" -#: aleksis/core/menus.py:124 +#: aleksis/core/menus.py:133 msgid "Admin" msgstr "" -#: aleksis/core/menus.py:132 aleksis/core/models.py:725 +#: aleksis/core/menus.py:141 aleksis/core/models.py:727 #: aleksis/core/templates/core/announcement/list.html:7 #: aleksis/core/templates/core/announcement/list.html:8 msgid "Announcements" msgstr "" -#: aleksis/core/menus.py:143 aleksis/core/models.py:126 +#: aleksis/core/menus.py:152 aleksis/core/models.py:130 #: aleksis/core/templates/core/school_term/list.html:8 #: aleksis/core/templates/core/school_term/list.html:9 msgid "School terms" msgstr "" -#: aleksis/core/menus.py:154 +#: aleksis/core/menus.py:163 #: aleksis/core/templates/core/dashboard_widget/list.html:8 #: aleksis/core/templates/core/dashboard_widget/list.html:9 msgid "Dashboard widgets" msgstr "" -#: aleksis/core/menus.py:165 +#: aleksis/core/menus.py:174 #: aleksis/core/templates/core/management/data_management.html:6 #: aleksis/core/templates/core/management/data_management.html:7 msgid "Data management" msgstr "" -#: aleksis/core/menus.py:176 +#: aleksis/core/menus.py:185 #: aleksis/core/templates/core/pages/system_status.html:5 #: aleksis/core/templates/core/pages/system_status.html:7 msgid "System status" msgstr "" -#: aleksis/core/menus.py:187 -msgid "Impersonation" -msgstr "" - -#: aleksis/core/menus.py:198 +#: aleksis/core/menus.py:196 msgid "Configuration" msgstr "" -#: aleksis/core/menus.py:209 aleksis/core/templates/core/data_check/list.html:9 +#: aleksis/core/menus.py:207 aleksis/core/templates/core/data_check/list.html:9 #: aleksis/core/templates/core/data_check/list.html:10 msgid "Data checks" msgstr "" -#: aleksis/core/menus.py:215 aleksis/core/templates/core/perms/list.html:13 +#: aleksis/core/menus.py:213 aleksis/core/templates/core/perms/list.html:13 #: aleksis/core/templates/core/perms/list.html:14 msgid "Manage permissions" msgstr "" -#: aleksis/core/menus.py:226 +#: aleksis/core/menus.py:224 msgid "Backend Admin" msgstr "" -#: aleksis/core/menus.py:234 +#: aleksis/core/menus.py:232 #: aleksis/core/templates/oauth2_provider/application/list.html:5 #: aleksis/core/templates/oauth2_provider/application/list.html:6 msgid "OAuth2 Applications" msgstr "" -#: aleksis/core/menus.py:247 +#: aleksis/core/menus.py:245 msgid "People" msgstr "" -#: aleksis/core/menus.py:278 aleksis/core/models.py:979 +#: aleksis/core/menus.py:276 aleksis/core/models.py:981 #: aleksis/core/templates/core/group_type/list.html:8 #: aleksis/core/templates/core/group_type/list.html:9 msgid "Group types" msgstr "" -#: aleksis/core/menus.py:289 +#: aleksis/core/menus.py:287 msgid "Groups and child groups" msgstr "" -#: aleksis/core/menus.py:300 aleksis/core/models.py:460 +#: aleksis/core/menus.py:298 aleksis/core/models.py:462 #: aleksis/core/templates/core/additional_field/list.html:8 #: aleksis/core/templates/core/additional_field/list.html:9 msgid "Additional fields" msgstr "" -#: aleksis/core/menus.py:315 +#: aleksis/core/menus.py:309 +msgid "Invite person" +msgstr "" + +#: aleksis/core/menus.py:322 #: aleksis/core/templates/core/group/child_groups.html:7 #: aleksis/core/templates/core/group/child_groups.html:9 msgid "Assign child groups to groups" msgstr "" -#: aleksis/core/mixins.py:508 +#: aleksis/core/mixins.py:511 msgid "Linked school term" msgstr "" -#: aleksis/core/models.py:66 +#: aleksis/core/models.py:70 msgid "Boolean (Yes/No)" msgstr "" -#: aleksis/core/models.py:67 +#: aleksis/core/models.py:71 msgid "Text (one line)" msgstr "" -#: aleksis/core/models.py:69 +#: aleksis/core/models.py:73 msgid "Date and time" msgstr "" -#: aleksis/core/models.py:70 +#: aleksis/core/models.py:74 msgid "Decimal number" msgstr "" -#: aleksis/core/models.py:71 aleksis/core/models.py:194 +#: aleksis/core/models.py:75 aleksis/core/models.py:198 msgid "E-mail address" msgstr "" -#: aleksis/core/models.py:72 +#: aleksis/core/models.py:76 msgid "Integer" msgstr "" -#: aleksis/core/models.py:73 +#: aleksis/core/models.py:77 msgid "IP address" msgstr "" -#: aleksis/core/models.py:74 +#: aleksis/core/models.py:78 msgid "Boolean or empty (Yes/No/Neither)" msgstr "" -#: aleksis/core/models.py:75 +#: aleksis/core/models.py:79 msgid "Text (multi-line)" msgstr "" -#: aleksis/core/models.py:77 +#: aleksis/core/models.py:81 msgid "URL / Link" msgstr "" -#: aleksis/core/models.py:89 aleksis/core/models.py:948 +#: aleksis/core/models.py:93 aleksis/core/models.py:950 msgid "Name" msgstr "" -#: aleksis/core/models.py:91 +#: aleksis/core/models.py:95 msgid "Start date" msgstr "" -#: aleksis/core/models.py:92 +#: aleksis/core/models.py:96 msgid "End date" msgstr "" -#: aleksis/core/models.py:111 +#: aleksis/core/models.py:115 msgid "The start date must be earlier than the end date." msgstr "" -#: aleksis/core/models.py:118 +#: aleksis/core/models.py:122 msgid "There is already a school term for this time or a part of this time." msgstr "" -#: aleksis/core/models.py:147 aleksis/core/models.py:897 +#: aleksis/core/models.py:151 aleksis/core/models.py:899 msgid "Person" msgstr "" -#: aleksis/core/models.py:150 +#: aleksis/core/models.py:154 msgid "Can view address" msgstr "" -#: aleksis/core/models.py:151 +#: aleksis/core/models.py:155 msgid "Can view contact details" msgstr "" -#: aleksis/core/models.py:152 +#: aleksis/core/models.py:156 msgid "Can view photo" msgstr "" -#: aleksis/core/models.py:153 +#: aleksis/core/models.py:157 msgid "Can view persons groups" msgstr "" -#: aleksis/core/models.py:154 +#: aleksis/core/models.py:158 msgid "Can view personal details" msgstr "" -#: aleksis/core/models.py:164 +#: aleksis/core/models.py:168 msgid "female" msgstr "" -#: aleksis/core/models.py:164 +#: aleksis/core/models.py:168 msgid "male" msgstr "" -#: aleksis/core/models.py:172 +#: aleksis/core/models.py:176 aleksis/core/models.py:1144 msgid "Linked user" msgstr "" -#: aleksis/core/models.py:174 +#: aleksis/core/models.py:178 msgid "Is person active?" msgstr "" -#: aleksis/core/models.py:176 +#: aleksis/core/models.py:180 msgid "First name" msgstr "" -#: aleksis/core/models.py:177 +#: aleksis/core/models.py:181 msgid "Last name" msgstr "" -#: aleksis/core/models.py:179 +#: aleksis/core/models.py:183 msgid "Additional name(s)" msgstr "" -#: aleksis/core/models.py:183 aleksis/core/models.py:429 +#: aleksis/core/models.py:187 aleksis/core/models.py:431 msgid "Short name" msgstr "" -#: aleksis/core/models.py:186 +#: aleksis/core/models.py:190 msgid "Street" msgstr "" -#: aleksis/core/models.py:187 +#: aleksis/core/models.py:191 msgid "Street number" msgstr "" -#: aleksis/core/models.py:188 +#: aleksis/core/models.py:192 msgid "Postal code" msgstr "" -#: aleksis/core/models.py:189 +#: aleksis/core/models.py:193 msgid "Place" msgstr "" -#: aleksis/core/models.py:191 +#: aleksis/core/models.py:195 msgid "Home phone" msgstr "" -#: aleksis/core/models.py:192 +#: aleksis/core/models.py:196 msgid "Mobile phone" msgstr "" -#: aleksis/core/models.py:196 +#: aleksis/core/models.py:200 msgid "Date of birth" msgstr "" -#: aleksis/core/models.py:198 +#: aleksis/core/models.py:201 msgid "Place of birth" msgstr "" -#: aleksis/core/models.py:200 +#: aleksis/core/models.py:202 msgid "Sex" msgstr "" -#: aleksis/core/models.py:202 +#: aleksis/core/models.py:204 msgid "Photo" msgstr "" -#: aleksis/core/models.py:206 aleksis/core/templates/core/person/full.html:138 +#: aleksis/core/models.py:208 aleksis/core/templates/core/person/full.html:145 msgid "Guardians / Parents" msgstr "" -#: aleksis/core/models.py:213 +#: aleksis/core/models.py:215 msgid "Primary group" msgstr "" -#: aleksis/core/models.py:216 aleksis/core/models.py:583 -#: aleksis/core/models.py:607 aleksis/core/models.py:692 -#: aleksis/core/models.py:972 aleksis/core/templates/core/person/full.html:121 +#: aleksis/core/models.py:218 aleksis/core/models.py:585 +#: aleksis/core/models.py:609 aleksis/core/models.py:694 +#: aleksis/core/models.py:974 aleksis/core/templates/core/person/full.html:128 msgid "Description" msgstr "" -#: aleksis/core/models.py:384 +#: aleksis/core/models.py:386 msgid "Title of field" msgstr "" -#: aleksis/core/models.py:386 +#: aleksis/core/models.py:388 msgid "Type of field" msgstr "" -#: aleksis/core/models.py:393 +#: aleksis/core/models.py:395 msgid "Addtitional field for groups" msgstr "" -#: aleksis/core/models.py:394 +#: aleksis/core/models.py:396 msgid "Addtitional fields for groups" msgstr "" -#: aleksis/core/models.py:414 +#: aleksis/core/models.py:416 msgid "Can assign child groups to groups" msgstr "" -#: aleksis/core/models.py:415 +#: aleksis/core/models.py:417 msgid "Can view statistics about group." msgstr "" -#: aleksis/core/models.py:427 +#: aleksis/core/models.py:429 msgid "Long name" msgstr "" -#: aleksis/core/models.py:437 aleksis/core/templates/core/group/full.html:85 +#: aleksis/core/models.py:439 aleksis/core/templates/core/group/full.html:85 msgid "Members" msgstr "" -#: aleksis/core/models.py:440 aleksis/core/templates/core/group/full.html:82 +#: aleksis/core/models.py:442 aleksis/core/templates/core/group/full.html:82 msgid "Owners" msgstr "" -#: aleksis/core/models.py:447 aleksis/core/templates/core/group/full.html:55 +#: aleksis/core/models.py:449 aleksis/core/templates/core/group/full.html:55 msgid "Parent groups" msgstr "" -#: aleksis/core/models.py:455 +#: aleksis/core/models.py:457 msgid "Type of group" msgstr "" -#: aleksis/core/models.py:582 aleksis/core/models.py:606 -#: aleksis/core/models.py:691 +#: aleksis/core/models.py:584 aleksis/core/models.py:608 +#: aleksis/core/models.py:693 #: aleksis/core/templates/core/announcement/list.html:18 msgid "Title" msgstr "" -#: aleksis/core/models.py:585 +#: aleksis/core/models.py:587 msgid "Application" msgstr "" -#: aleksis/core/models.py:591 +#: aleksis/core/models.py:593 msgid "Activity" msgstr "" -#: aleksis/core/models.py:592 +#: aleksis/core/models.py:594 msgid "Activities" msgstr "" -#: aleksis/core/models.py:598 +#: aleksis/core/models.py:600 msgid "Sender" msgstr "" -#: aleksis/core/models.py:603 +#: aleksis/core/models.py:605 msgid "Recipient" msgstr "" -#: aleksis/core/models.py:608 aleksis/core/models.py:949 +#: aleksis/core/models.py:610 aleksis/core/models.py:951 msgid "Link" msgstr "" -#: aleksis/core/models.py:610 +#: aleksis/core/models.py:612 msgid "Read" msgstr "" -#: aleksis/core/models.py:611 +#: aleksis/core/models.py:613 msgid "Sent" msgstr "" -#: aleksis/core/models.py:624 +#: aleksis/core/models.py:626 msgid "Notification" msgstr "" -#: aleksis/core/models.py:693 +#: aleksis/core/models.py:695 msgid "Link to detailed view" msgstr "" -#: aleksis/core/models.py:696 +#: aleksis/core/models.py:698 msgid "Date and time from when to show" msgstr "" -#: aleksis/core/models.py:699 +#: aleksis/core/models.py:701 msgid "Date and time until when to show" msgstr "" -#: aleksis/core/models.py:724 +#: aleksis/core/models.py:726 msgid "Announcement" msgstr "" -#: aleksis/core/models.py:762 +#: aleksis/core/models.py:764 msgid "Announcement recipient" msgstr "" -#: aleksis/core/models.py:763 +#: aleksis/core/models.py:765 msgid "Announcement recipients" msgstr "" -#: aleksis/core/models.py:818 +#: aleksis/core/models.py:820 msgid "Widget Title" msgstr "" -#: aleksis/core/models.py:819 +#: aleksis/core/models.py:821 msgid "Activate Widget" msgstr "" -#: aleksis/core/models.py:820 +#: aleksis/core/models.py:822 msgid "Widget is broken" msgstr "" -#: aleksis/core/models.py:823 +#: aleksis/core/models.py:825 msgid "Size on mobile devices" msgstr "" -#: aleksis/core/models.py:824 +#: aleksis/core/models.py:826 msgid "<= 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:829 +#: aleksis/core/models.py:831 msgid "Size on tablet devices" msgstr "" -#: aleksis/core/models.py:830 +#: aleksis/core/models.py:832 msgid "> 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:835 +#: aleksis/core/models.py:837 msgid "Size on desktop devices" msgstr "" -#: aleksis/core/models.py:836 +#: aleksis/core/models.py:838 msgid "> 992 px, 12 columns" msgstr "" -#: aleksis/core/models.py:841 +#: aleksis/core/models.py:843 msgid "Size on large desktop devices" msgstr "" -#: aleksis/core/models.py:842 +#: aleksis/core/models.py:844 msgid "> 1200 px>, 12 columns" msgstr "" -#: aleksis/core/models.py:873 +#: aleksis/core/models.py:875 msgid "Can edit default dashboard" msgstr "" -#: aleksis/core/models.py:874 +#: aleksis/core/models.py:876 msgid "Dashboard Widget" msgstr "" -#: aleksis/core/models.py:875 +#: aleksis/core/models.py:877 msgid "Dashboard Widgets" msgstr "" -#: aleksis/core/models.py:881 +#: aleksis/core/models.py:883 msgid "URL" msgstr "" -#: aleksis/core/models.py:882 +#: aleksis/core/models.py:884 msgid "Icon URL" msgstr "" -#: aleksis/core/models.py:888 +#: aleksis/core/models.py:890 msgid "External link widget" msgstr "" -#: aleksis/core/models.py:889 +#: aleksis/core/models.py:891 msgid "External link widgets" msgstr "" -#: aleksis/core/models.py:894 +#: aleksis/core/models.py:896 msgid "Dashboard widget" msgstr "" -#: aleksis/core/models.py:899 +#: aleksis/core/models.py:901 msgid "Order" msgstr "" -#: aleksis/core/models.py:900 +#: aleksis/core/models.py:902 msgid "Part of the default dashboard" msgstr "" -#: aleksis/core/models.py:915 +#: aleksis/core/models.py:917 msgid "Dashboard widget order" msgstr "" -#: aleksis/core/models.py:916 +#: aleksis/core/models.py:918 msgid "Dashboard widget orders" msgstr "" -#: aleksis/core/models.py:922 +#: aleksis/core/models.py:924 msgid "Menu ID" msgstr "" -#: aleksis/core/models.py:935 +#: aleksis/core/models.py:937 msgid "Custom menu" msgstr "" -#: aleksis/core/models.py:936 +#: aleksis/core/models.py:938 msgid "Custom menus" msgstr "" -#: aleksis/core/models.py:946 +#: aleksis/core/models.py:948 msgid "Menu" msgstr "" -#: aleksis/core/models.py:950 +#: aleksis/core/models.py:952 msgid "Icon" msgstr "" -#: aleksis/core/models.py:956 +#: aleksis/core/models.py:958 msgid "Custom menu item" msgstr "" -#: aleksis/core/models.py:957 +#: aleksis/core/models.py:959 msgid "Custom menu items" msgstr "" -#: aleksis/core/models.py:971 +#: aleksis/core/models.py:973 msgid "Title of type" msgstr "" -#: aleksis/core/models.py:978 aleksis/core/templates/core/group/full.html:47 +#: aleksis/core/models.py:980 aleksis/core/templates/core/group/full.html:47 msgid "Group type" msgstr "" -#: aleksis/core/models.py:992 +#: aleksis/core/models.py:994 msgid "Can view system status" msgstr "" -#: aleksis/core/models.py:993 +#: aleksis/core/models.py:995 msgid "Can manage data" msgstr "" -#: aleksis/core/models.py:994 +#: aleksis/core/models.py:996 msgid "Can impersonate" msgstr "" -#: aleksis/core/models.py:995 +#: aleksis/core/models.py:997 msgid "Can use search" msgstr "" -#: aleksis/core/models.py:996 +#: aleksis/core/models.py:998 msgid "Can change site preferences" msgstr "" -#: aleksis/core/models.py:997 +#: aleksis/core/models.py:999 msgid "Can change person preferences" msgstr "" -#: aleksis/core/models.py:998 +#: aleksis/core/models.py:1000 msgid "Can change group preferences" msgstr "" -#: aleksis/core/models.py:999 +#: aleksis/core/models.py:1001 msgid "Can test PDF generation" msgstr "" -#: aleksis/core/models.py:1035 +#: aleksis/core/models.py:1037 msgid "Related data check task" msgstr "" -#: aleksis/core/models.py:1043 +#: aleksis/core/models.py:1045 msgid "Issue solved" msgstr "" -#: aleksis/core/models.py:1044 +#: aleksis/core/models.py:1046 msgid "Notification sent" msgstr "" -#: aleksis/core/models.py:1057 +#: aleksis/core/models.py:1059 msgid "Data check result" msgstr "" -#: aleksis/core/models.py:1058 +#: aleksis/core/models.py:1060 msgid "Data check results" msgstr "" -#: aleksis/core/models.py:1060 +#: aleksis/core/models.py:1062 msgid "Can run data checks" msgstr "" -#: aleksis/core/models.py:1061 +#: aleksis/core/models.py:1063 msgid "Can solve data check problems" msgstr "" -#: aleksis/core/models.py:1076 +#: aleksis/core/models.py:1070 +msgid "E-Mail address" +msgstr "" + +#: aleksis/core/models.py:1094 msgid "Owner" msgstr "" -#: aleksis/core/models.py:1080 +#: aleksis/core/models.py:1098 msgid "File expires at" msgstr "" -#: aleksis/core/models.py:1082 +#: aleksis/core/models.py:1100 msgid "Generated HTML file" msgstr "" -#: aleksis/core/models.py:1084 +#: aleksis/core/models.py:1102 msgid "Generated PDF file" msgstr "" -#: aleksis/core/models.py:1091 +#: aleksis/core/models.py:1109 msgid "PDF file" msgstr "" -#: aleksis/core/models.py:1092 +#: aleksis/core/models.py:1110 msgid "PDF files" msgstr "" -#: aleksis/core/models.py:1097 +#: aleksis/core/models.py:1115 msgid "Task result" msgstr "" -#: aleksis/core/models.py:1100 +#: aleksis/core/models.py:1118 msgid "Task user" msgstr "" -#: aleksis/core/models.py:1112 +#: aleksis/core/models.py:1130 msgid "Task user assignment" msgstr "" -#: aleksis/core/models.py:1113 +#: aleksis/core/models.py:1131 msgid "Task user assignments" msgstr "" -#: aleksis/core/models.py:1127 +#: aleksis/core/models.py:1147 +msgid "Additional attributes" +msgstr "" + +#: aleksis/core/models.py:1185 msgid "Allowed scopes that clients can request" msgstr "" -#: aleksis/core/preferences.py:23 +#: aleksis/core/preferences.py:24 msgid "General" msgstr "" -#: aleksis/core/preferences.py:24 +#: aleksis/core/preferences.py:25 msgid "School" msgstr "" -#: aleksis/core/preferences.py:25 +#: aleksis/core/preferences.py:26 msgid "Theme" msgstr "" -#: aleksis/core/preferences.py:26 +#: aleksis/core/preferences.py:27 msgid "Mail" msgstr "" -#: aleksis/core/preferences.py:28 +#: aleksis/core/preferences.py:29 msgid "Footer" msgstr "" -#: aleksis/core/preferences.py:29 +#: aleksis/core/preferences.py:30 msgid "Accounts" msgstr "" -#: aleksis/core/preferences.py:30 +#: aleksis/core/preferences.py:31 msgid "Authentication" msgstr "" -#: aleksis/core/preferences.py:31 +#: aleksis/core/preferences.py:32 msgid "Internationalisation" msgstr "" -#: aleksis/core/preferences.py:42 +#: aleksis/core/preferences.py:43 msgid "Site title" msgstr "" -#: aleksis/core/preferences.py:53 +#: aleksis/core/preferences.py:54 msgid "Site description" msgstr "" -#: aleksis/core/preferences.py:64 +#: aleksis/core/preferences.py:65 msgid "Primary colour" msgstr "" -#: aleksis/core/preferences.py:76 +#: aleksis/core/preferences.py:77 msgid "Secondary colour" msgstr "" -#: aleksis/core/preferences.py:87 +#: aleksis/core/preferences.py:88 msgid "Logo" msgstr "" -#: aleksis/core/preferences.py:97 +#: aleksis/core/preferences.py:98 msgid "Favicon" msgstr "" -#: aleksis/core/preferences.py:107 +#: aleksis/core/preferences.py:108 msgid "PWA-Icon" msgstr "" -#: aleksis/core/preferences.py:118 +#: aleksis/core/preferences.py:119 msgid "Mail out name" msgstr "" -#: aleksis/core/preferences.py:129 +#: aleksis/core/preferences.py:130 msgid "Mail out address" msgstr "" -#: aleksis/core/preferences.py:141 +#: aleksis/core/preferences.py:142 msgid "Link to privacy policy" msgstr "" -#: aleksis/core/preferences.py:153 +#: aleksis/core/preferences.py:154 msgid "Link to imprint" msgstr "" -#: aleksis/core/preferences.py:165 +#: aleksis/core/preferences.py:166 msgid "Name format for addressing" msgstr "" -#: aleksis/core/preferences.py:181 +#: aleksis/core/preferences.py:182 msgid "Channels to use for notifications" msgstr "" -#: aleksis/core/preferences.py:193 +#: aleksis/core/preferences.py:194 msgid "Regular expression to match primary group, e.g. '^Class .*'" msgstr "" -#: aleksis/core/preferences.py:204 +#: aleksis/core/preferences.py:205 msgid "Field on person to match primary group against" msgstr "" -#: aleksis/core/preferences.py:216 +#: aleksis/core/preferences.py:217 msgid "Automatically create new persons for new users" msgstr "" -#: aleksis/core/preferences.py:225 +#: aleksis/core/preferences.py:226 msgid "Automatically link existing persons to new users by their e-mail address" msgstr "" -#: aleksis/core/preferences.py:236 +#: aleksis/core/preferences.py:237 msgid "Display name of the school" msgstr "" -#: aleksis/core/preferences.py:247 +#: aleksis/core/preferences.py:248 msgid "Official name of the school, e.g. as given by supervisory authority" msgstr "" -#: aleksis/core/preferences.py:255 +#: aleksis/core/preferences.py:256 msgid "Allow users to change their passwords" msgstr "" -#: aleksis/core/preferences.py:263 +#: aleksis/core/preferences.py:264 msgid "Enable signup" msgstr "" -#: aleksis/core/preferences.py:274 +#: aleksis/core/preferences.py:272 +msgid "Enable invitations" +msgstr "" + +#: aleksis/core/preferences.py:280 +msgid "Length of invite code. (Default 3: abcde-acbde-abcde)" +msgstr "" + +#: aleksis/core/preferences.py:288 +msgid "Size of packets. (Default 5: abcde)" +msgstr "" + +#: aleksis/core/preferences.py:298 msgid "Allowed Grant Flows for OAuth applications" msgstr "" -#: aleksis/core/preferences.py:287 +#: aleksis/core/preferences.py:311 msgid "Available languages" msgstr "" -#: aleksis/core/preferences.py:299 +#: aleksis/core/preferences.py:323 msgid "Send emails if data checks detect problems" msgstr "" -#: aleksis/core/preferences.py:310 +#: aleksis/core/preferences.py:334 msgid "Email recipients for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:321 +#: aleksis/core/preferences.py:345 msgid "Email recipient groups for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:330 +#: aleksis/core/preferences.py:354 msgid "Show dashboard to users without login" msgstr "" -#: aleksis/core/preferences.py:339 +#: aleksis/core/preferences.py:363 msgid "Allow users to edit their dashboard" msgstr "" -#: aleksis/core/preferences.py:350 +#: aleksis/core/preferences.py:374 msgid "Fields on person model which are editable by themselves." msgstr "" -#: aleksis/core/preferences.py:364 +#: aleksis/core/preferences.py:388 msgid "Editable fields on person model which should trigger a notification on change" msgstr "" -#: aleksis/core/preferences.py:377 +#: aleksis/core/preferences.py:401 msgid "Contact for notification if a person changes their data" msgstr "" -#: aleksis/core/preferences.py:387 +#: aleksis/core/preferences.py:411 msgid "PDF file expiration duration" msgstr "" -#: aleksis/core/preferences.py:388 +#: aleksis/core/preferences.py:412 msgid "in minutes" msgstr "" -#: aleksis/core/preferences.py:398 +#: aleksis/core/preferences.py:422 msgid "Automatically update the dashboard and its widgets" msgstr "" -#: aleksis/core/preferences.py:408 +#: aleksis/core/preferences.py:432 msgid "Automatically update the dashboard and its widgets sitewide" msgstr "" -#: aleksis/core/settings.py:474 +#: aleksis/core/settings.py:507 msgid "English" msgstr "" -#: aleksis/core/settings.py:475 +#: aleksis/core/settings.py:508 msgid "German" msgstr "" -#: aleksis/core/tables.py:19 +#: aleksis/core/tables.py:24 #: aleksis/core/templates/core/announcement/list.html:36 #: aleksis/core/templates/core/group/full.html:24 -#: aleksis/core/templates/core/person/full.html:23 +#: aleksis/core/templates/core/person/full.html:24 #: aleksis/core/templates/oauth2_provider/application/detail.html:17 msgid "Edit" msgstr "" -#: aleksis/core/tables.py:21 aleksis/core/tables.py:89 -#: aleksis/core/tables.py:105 +#: aleksis/core/tables.py:26 aleksis/core/tables.py:94 +#: aleksis/core/tables.py:137 #: aleksis/core/templates/core/announcement/list.html:22 msgid "Actions" msgstr "" -#: aleksis/core/tables.py:56 aleksis/core/tables.py:57 -#: aleksis/core/tables.py:71 aleksis/core/tables.py:87 -#: aleksis/core/tables.py:103 +#: aleksis/core/tables.py:61 aleksis/core/tables.py:62 +#: aleksis/core/tables.py:76 aleksis/core/tables.py:92 +#: aleksis/core/tables.py:135 #: aleksis/core/templates/core/announcement/list.html:42 #: aleksis/core/templates/core/group/full.html:31 #: aleksis/core/templates/core/pages/delete.html:22 -#: aleksis/core/templates/core/person/full.html:30 +#: aleksis/core/templates/core/person/full.html:31 #: aleksis/core/templates/oauth2_provider/application/detail.html:21 msgid "Delete" msgstr "" @@ -1207,11 +1226,11 @@ msgstr "" msgid "Account inactive" msgstr "" -#: aleksis/core/templates/account/account_inactive.html:13 +#: aleksis/core/templates/account/account_inactive.html:14 msgid "Account inactive." msgstr "" -#: aleksis/core/templates/account/account_inactive.html:15 +#: aleksis/core/templates/account/account_inactive.html:17 msgid "" "\n" " This account is currently inactive. If you think this is an\n" @@ -1363,11 +1382,11 @@ msgstr "" msgid "Signup closed" msgstr "" -#: aleksis/core/templates/account/signup_closed.html:13 +#: aleksis/core/templates/account/signup_closed.html:14 msgid "Signup closed." msgstr "" -#: aleksis/core/templates/account/signup_closed.html:15 +#: aleksis/core/templates/account/signup_closed.html:17 msgid "" "\n" " This sign up is currently closed. If you think this is an\n" @@ -1405,11 +1424,6 @@ msgid "" " " msgstr "" -#: aleksis/core/templates/account/verification_sent.html:30 -#, python-format -msgid "<strong>Note:</strong> you can still <a href=\"%(email_url)s\">change your e-mail address</a>" -msgstr "" - #: aleksis/core/templates/core/additional_field/edit.html:6 #: aleksis/core/templates/core/additional_field/edit.html:7 msgid "Edit additional field" @@ -1458,11 +1472,11 @@ msgid "Logged in as" msgstr "" #: aleksis/core/templates/core/base.html:175 -msgid "About AlekSIS — The Free School Information System" +msgid "About AlekSIS® — The Free School Information System" msgstr "" #: aleksis/core/templates/core/base.html:183 -msgid "Impress" +msgid "Imprint" msgstr "" #: aleksis/core/templates/core/base.html:191 @@ -1470,7 +1484,7 @@ msgid "Privacy Policy" msgstr "" #: aleksis/core/templates/core/base_print.html:72 -msgid "Powered by AlekSIS" +msgid "Powered by AlekSIS®" msgstr "" #: aleksis/core/templates/core/dashboard_widget/create.html:8 @@ -1685,7 +1699,7 @@ msgid "Edit group" msgstr "" #: aleksis/core/templates/core/group/full.html:38 -#: aleksis/core/templates/core/person/full.html:37 +#: aleksis/core/templates/core/person/full.html:38 msgid "Change preferences" msgstr "" @@ -1774,36 +1788,46 @@ msgid "No notifications available yet." msgstr "" #: aleksis/core/templates/core/pages/about.html:6 -#: aleksis/core/templates/core/pages/about.html:15 -msgid "About AlekSIS" +msgid "About AlekSIS®" msgstr "" #: aleksis/core/templates/core/pages/about.html:7 -msgid "AlekSIS – The Free School Information System" +msgid "AlekSIS® – The Free School Information System" +msgstr "" + +#: aleksis/core/templates/core/pages/about.html:15 +msgid "About AlekSIS" msgstr "" #: aleksis/core/templates/core/pages/about.html:17 msgid "" "\n" -" This platform is powered by AlekSIS, a web-based school information system (SIS) which can be used\n" +" This platform is powered by AlekSIS®, a web-based school information system (SIS) which can be used\n" " to manage and/or publish organisational artifacts of educational institutions. AlekSIS is free software and\n" " can be used by anyone.\n" " " msgstr "" -#: aleksis/core/templates/core/pages/about.html:25 +#: aleksis/core/templates/core/pages/about.html:24 +msgid "" +"\n" +" AlekSIS® is a registered trademark of the AlekSIS open source project, represented by Teckids e.V.\n" +" " +msgstr "" + +#: aleksis/core/templates/core/pages/about.html:30 msgid "Website of AlekSIS" msgstr "" -#: aleksis/core/templates/core/pages/about.html:26 +#: aleksis/core/templates/core/pages/about.html:31 msgid "Source code" msgstr "" -#: aleksis/core/templates/core/pages/about.html:35 +#: aleksis/core/templates/core/pages/about.html:40 msgid "Licence information" msgstr "" -#: aleksis/core/templates/core/pages/about.html:37 +#: aleksis/core/templates/core/pages/about.html:42 msgid "" "\n" " The core and the official apps of AlekSIS are licenced under the EUPL, version 1.2 or later. For licence\n" @@ -1812,23 +1836,23 @@ msgid "" " " msgstr "" -#: aleksis/core/templates/core/pages/about.html:45 +#: aleksis/core/templates/core/pages/about.html:50 msgid "Free/Open Source Licence" msgstr "" -#: aleksis/core/templates/core/pages/about.html:46 +#: aleksis/core/templates/core/pages/about.html:51 msgid "Other Licence" msgstr "" -#: aleksis/core/templates/core/pages/about.html:50 +#: aleksis/core/templates/core/pages/about.html:55 msgid "Full licence text" msgstr "" -#: aleksis/core/templates/core/pages/about.html:51 +#: aleksis/core/templates/core/pages/about.html:56 msgid "More information about the EUPL" msgstr "" -#: aleksis/core/templates/core/pages/about.html:90 +#: aleksis/core/templates/core/pages/about.html:95 #, python-format msgid "" "\n" @@ -2069,17 +2093,19 @@ msgstr "" msgid "Edit person" msgstr "" -#: aleksis/core/templates/core/person/full.html:44 -#: aleksis/core/templates/impersonate/list_users.html:7 -#: aleksis/core/templates/impersonate/list_users.html:8 +#: aleksis/core/templates/core/person/full.html:45 msgid "Impersonate" msgstr "" -#: aleksis/core/templates/core/person/full.html:50 +#: aleksis/core/templates/core/person/full.html:51 +msgid "Invite user" +msgstr "" + +#: aleksis/core/templates/core/person/full.html:57 msgid "Contact details" msgstr "" -#: aleksis/core/templates/core/person/full.html:131 +#: aleksis/core/templates/core/person/full.html:138 msgid "Children" msgstr "" @@ -2119,6 +2145,49 @@ msgstr "" msgid "Save preferences" msgstr "" +#: aleksis/core/templates/invitations/enter.html:21 +msgid "Accept your invitation" +msgstr "" + +#: aleksis/core/templates/invitations/enter.html:25 +msgid "" +"\n" +" Please enter your invitation code to register\n" +" your new user account:\n" +" " +msgstr "" + +#: aleksis/core/templates/invitations/enter.html:37 +msgid "Accept invite" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:9 +#: aleksis/core/templates/invitations/forms/_invite.html:10 +#: aleksis/core/templates/invitations/forms/_invite.html:21 +msgid "Invite" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:17 +msgid "Invite by email address" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:26 +msgid "Generate invitation code" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:29 +msgid "Generate code" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:33 +msgid "Invitations" +msgstr "" + +#: aleksis/core/templates/invitations/messages/invite_accepted.txt:3 +#, python-format +msgid "The invitation for %(email)s has been accepted." +msgstr "" + #: aleksis/core/templates/oauth2_provider/application/create.html:5 #: aleksis/core/templates/oauth2_provider/application/create.html:6 msgid "Register OAuth2 Application" @@ -2775,150 +2844,163 @@ msgstr "" msgid "SMS" msgstr "" -#: aleksis/core/util/pdf.py:105 +#: aleksis/core/util/pdf.py:113 msgid "Progress: Generate PDF file" msgstr "" -#: aleksis/core/util/pdf.py:106 +#: aleksis/core/util/pdf.py:114 msgid "Generating PDF file …" msgstr "" -#: aleksis/core/util/pdf.py:107 +#: aleksis/core/util/pdf.py:115 msgid "The PDF file has been generated successfully." msgstr "" -#: aleksis/core/util/pdf.py:108 +#: aleksis/core/util/pdf.py:116 msgid "There was a problem while generating the PDF file." msgstr "" -#: aleksis/core/util/pdf.py:111 +#: aleksis/core/util/pdf.py:119 msgid "Download PDF" msgstr "" -#: aleksis/core/views.py:270 +#: aleksis/core/views.py:280 msgid "The school term has been created." msgstr "" -#: aleksis/core/views.py:282 +#: aleksis/core/views.py:292 msgid "The school term has been saved." msgstr "" -#: aleksis/core/views.py:406 +#: aleksis/core/views.py:416 msgid "The child groups were successfully saved." msgstr "" -#: aleksis/core/views.py:425 aleksis/core/views.py:435 +#: aleksis/core/views.py:435 aleksis/core/views.py:445 msgid "The person has been saved." msgstr "" -#: aleksis/core/views.py:485 +#: aleksis/core/views.py:495 msgid "The group has been saved." msgstr "" -#: aleksis/core/views.py:582 +#: aleksis/core/views.py:592 msgid "The announcement has been saved." msgstr "" -#: aleksis/core/views.py:598 +#: aleksis/core/views.py:608 msgid "The announcement has been deleted." msgstr "" -#: aleksis/core/views.py:682 +#: aleksis/core/views.py:695 msgid "The preferences have been saved successfully." msgstr "" -#: aleksis/core/views.py:706 +#: aleksis/core/views.py:719 msgid "The person has been deleted." msgstr "" -#: aleksis/core/views.py:720 +#: aleksis/core/views.py:733 msgid "The group has been deleted." msgstr "" -#: aleksis/core/views.py:752 +#: aleksis/core/views.py:765 msgid "The additional_field has been saved." msgstr "" -#: aleksis/core/views.py:786 +#: aleksis/core/views.py:799 msgid "The additional field has been deleted." msgstr "" -#: aleksis/core/views.py:811 +#: aleksis/core/views.py:824 msgid "The group type has been saved." msgstr "" -#: aleksis/core/views.py:841 +#: aleksis/core/views.py:854 msgid "The group type has been deleted." msgstr "" -#: aleksis/core/views.py:874 +#: aleksis/core/views.py:887 msgid "Progress: Run data checks" msgstr "" -#: aleksis/core/views.py:875 +#: aleksis/core/views.py:888 msgid "Run data checks …" msgstr "" -#: aleksis/core/views.py:876 +#: aleksis/core/views.py:889 msgid "The data checks were run successfully." msgstr "" -#: aleksis/core/views.py:877 +#: aleksis/core/views.py:890 msgid "There was a problem while running data checks." msgstr "" -#: aleksis/core/views.py:893 +#: aleksis/core/views.py:906 #, python-brace-format msgid "The solve option '{solve_option_obj.verbose_name}' " msgstr "" -#: aleksis/core/views.py:935 +#: aleksis/core/views.py:948 msgid "The dashboard widget has been saved." msgstr "" -#: aleksis/core/views.py:965 +#: aleksis/core/views.py:978 msgid "The dashboard widget has been created." msgstr "" -#: aleksis/core/views.py:975 +#: aleksis/core/views.py:988 msgid "The dashboard widget has been deleted." msgstr "" -#: aleksis/core/views.py:1042 +#: aleksis/core/views.py:1055 msgid "Your dashboard configuration has been saved successfully." msgstr "" -#: aleksis/core/views.py:1044 +#: aleksis/core/views.py:1057 msgid "The configuration of the default dashboard has been saved successfully." msgstr "" -#: aleksis/core/views.py:1139 +#: aleksis/core/views.py:1127 +#, python-brace-format +msgid "The invitation was successfully created. The invitation code is {code}" +msgstr "" + +#: aleksis/core/views.py:1218 msgid "We have successfully assigned the permissions." msgstr "" -#: aleksis/core/views.py:1149 +#: aleksis/core/views.py:1228 msgid "The global user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1159 +#: aleksis/core/views.py:1238 msgid "The global group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1169 +#: aleksis/core/views.py:1248 msgid "The object user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1179 +#: aleksis/core/views.py:1258 msgid "The object group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1298 +#: aleksis/core/views.py:1377 msgid "The third-party account could not be disconnected because it is the only login method available." msgstr "" -#: aleksis/core/views.py:1305 +#: aleksis/core/views.py:1384 msgid "The third-party account has been successfully disconnected." msgstr "" +#: aleksis/core/views.py:1441 +msgid "Person was invited successfully." +msgstr "" + +#: aleksis/core/views.py:1443 +msgid "Person was already invited." +msgstr "" + #~ msgid "Norwegian (bokmål)" #~ msgstr "Norsk (bokmål)" diff --git a/aleksis/core/locale/nb_NO/LC_MESSAGES/djangojs.po b/aleksis/core/locale/nb_NO/LC_MESSAGES/djangojs.po index 2458849847f712fe1cf63743640716c5b3ef561a..d67bdb0055bf1ee96915909ce9e21023085c466b 100644 --- a/aleksis/core/locale/nb_NO/LC_MESSAGES/djangojs.po +++ b/aleksis/core/locale/nb_NO/LC_MESSAGES/djangojs.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-29 09:59+0100\n" +"POT-Creation-Date: 2021-12-28 12:14+0100\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" @@ -29,6 +29,6 @@ msgstr "" msgid "OK" msgstr "" -#: aleksis/core/static/js/main.js:127 +#: aleksis/core/static/js/main.js:128 msgid "This page may contain outdated information since there is no internet connection." msgstr "" diff --git a/aleksis/core/locale/tr_TR/LC_MESSAGES/django.po b/aleksis/core/locale/tr_TR/LC_MESSAGES/django.po index 018414f7c82920ea684c99d5574e52bc2a923d5a..1738a0918a91e64c2eb5421ef10b70dac77a6b90 100644 --- a/aleksis/core/locale/tr_TR/LC_MESSAGES/django.po +++ b/aleksis/core/locale/tr_TR/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: AlekSIS (School Information System) 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-29 09:59+0100\n" +"POT-Creation-Date: 2021-12-28 12:13+0100\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" @@ -17,26 +17,33 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: aleksis/core/apps.py:151 +#: aleksis/core/apps.py:152 msgid "OpenID Connect scope" msgstr "" -#: aleksis/core/apps.py:152 +#: aleksis/core/apps.py:153 msgid "Given name, family name, link to profile and picture if existing." msgstr "" -#: aleksis/core/apps.py:153 +#: aleksis/core/apps.py:154 msgid "Full home postal address" msgstr "" -#: aleksis/core/apps.py:154 +#: aleksis/core/apps.py:155 msgid "Email address" msgstr "" -#: aleksis/core/apps.py:155 +#: aleksis/core/apps.py:156 msgid "Home and mobile phone" msgstr "" +#: aleksis/core/apps.py:157 aleksis/core/forms.py:223 aleksis/core/menus.py:265 +#: aleksis/core/models.py:414 aleksis/core/templates/core/group/list.html:8 +#: aleksis/core/templates/core/group/list.html:9 +#: aleksis/core/templates/core/person/full.html:152 +msgid "Groups" +msgstr "" + #: aleksis/core/data_checks.py:55 msgid "Ignore problem" msgstr "" @@ -83,156 +90,148 @@ msgstr "" msgid "Content type" msgstr "" -#: aleksis/core/filters.py:112 aleksis/core/models.py:579 +#: aleksis/core/filters.py:112 aleksis/core/models.py:581 msgid "User" msgstr "" -#: aleksis/core/filters.py:134 aleksis/core/models.py:411 +#: aleksis/core/filters.py:134 aleksis/core/models.py:413 msgid "Group" msgstr "" -#: aleksis/core/forms.py:46 aleksis/core/forms.py:514 +#: aleksis/core/forms.py:48 aleksis/core/forms.py:559 msgid "Base data" msgstr "" -#: aleksis/core/forms.py:52 +#: aleksis/core/forms.py:54 msgid "Address" msgstr "" -#: aleksis/core/forms.py:53 +#: aleksis/core/forms.py:55 aleksis/core/forms.py:568 msgid "Contact data" msgstr "" -#: aleksis/core/forms.py:55 +#: aleksis/core/forms.py:57 msgid "Advanced personal data" msgstr "" -#: aleksis/core/forms.py:103 +#: aleksis/core/forms.py:105 msgid "New user" msgstr "" -#: aleksis/core/forms.py:103 +#: aleksis/core/forms.py:105 msgid "Create a new account" msgstr "" -#: aleksis/core/forms.py:134 +#: aleksis/core/forms.py:136 msgid "You cannot set a new username when also selecting an existing user." msgstr "" -#: aleksis/core/forms.py:138 +#: aleksis/core/forms.py:140 msgid "This username is already in use." msgstr "" -#: aleksis/core/forms.py:155 aleksis/core/models.py:125 +#: aleksis/core/forms.py:157 aleksis/core/models.py:129 msgid "School term" msgstr "" -#: aleksis/core/forms.py:156 +#: aleksis/core/forms.py:158 msgid "Common data" msgstr "" -#: aleksis/core/forms.py:157 aleksis/core/forms.py:208 -#: aleksis/core/menus.py:256 aleksis/core/models.py:148 +#: aleksis/core/forms.py:159 aleksis/core/forms.py:210 +#: aleksis/core/menus.py:254 aleksis/core/models.py:152 #: aleksis/core/templates/core/person/list.html:8 #: aleksis/core/templates/core/person/list.html:9 msgid "Persons" msgstr "" -#: aleksis/core/forms.py:158 +#: aleksis/core/forms.py:160 aleksis/core/forms.py:570 msgid "Additional data" msgstr "" -#: aleksis/core/forms.py:200 aleksis/core/forms.py:203 -#: aleksis/core/models.py:68 +#: aleksis/core/forms.py:202 aleksis/core/forms.py:205 +#: aleksis/core/models.py:72 msgid "Date" msgstr "" -#: aleksis/core/forms.py:201 aleksis/core/forms.py:204 -#: aleksis/core/models.py:76 +#: aleksis/core/forms.py:203 aleksis/core/forms.py:206 +#: aleksis/core/models.py:80 msgid "Time" msgstr "" -#: aleksis/core/forms.py:221 aleksis/core/menus.py:267 -#: aleksis/core/models.py:412 aleksis/core/templates/core/group/list.html:8 -#: aleksis/core/templates/core/group/list.html:9 -#: aleksis/core/templates/core/person/full.html:145 -msgid "Groups" -msgstr "" - -#: aleksis/core/forms.py:234 +#: aleksis/core/forms.py:236 msgid "From when until when should the announcement be displayed?" msgstr "" -#: aleksis/core/forms.py:237 +#: aleksis/core/forms.py:239 msgid "Who should see the announcement?" msgstr "" -#: aleksis/core/forms.py:238 +#: aleksis/core/forms.py:240 msgid "Write your announcement:" msgstr "" -#: aleksis/core/forms.py:277 +#: aleksis/core/forms.py:279 msgid "You are not allowed to create announcements which are only valid in the past." msgstr "" -#: aleksis/core/forms.py:281 +#: aleksis/core/forms.py:283 msgid "The from date and time must be earlier then the until date and time." msgstr "" -#: aleksis/core/forms.py:290 +#: aleksis/core/forms.py:292 msgid "You need at least one recipient." msgstr "" -#: aleksis/core/forms.py:411 +#: aleksis/core/forms.py:401 +msgid "Invitation code" +msgstr "" + +#: aleksis/core/forms.py:402 +msgid "Please enter your invitation code." +msgstr "" + +#: aleksis/core/forms.py:434 msgid "Who should get the permission?" msgstr "" -#: aleksis/core/forms.py:412 +#: aleksis/core/forms.py:435 msgid "On what?" msgstr "" -#: aleksis/core/forms.py:438 +#: aleksis/core/forms.py:461 msgid "Select objects which the permission should be granted for:" msgstr "" -#: aleksis/core/forms.py:441 +#: aleksis/core/forms.py:464 msgid "Grant the permission for all objects" msgstr "" -#: aleksis/core/forms.py:449 +#: aleksis/core/forms.py:472 msgid "You must select at least one group or person which should get the permission." msgstr "" -#: aleksis/core/forms.py:454 +#: aleksis/core/forms.py:477 msgid "You must grant the permission to all objects and/or to some objects." msgstr "" -#: aleksis/core/forms.py:518 -msgid "Account data" +#: aleksis/core/forms.py:564 +msgid "Adress data" msgstr "" -#: aleksis/core/forms.py:524 -msgid "Consents" +#: aleksis/core/forms.py:576 +msgid "Account data" msgstr "" -#: aleksis/core/forms.py:531 +#: aleksis/core/forms.py:583 msgid "Password" msgstr "" -#: aleksis/core/forms.py:537 +#: aleksis/core/forms.py:586 msgid "Password (again)" msgstr "" -#: aleksis/core/forms.py:550 -#, python-brace-format -msgid "I have read the <a href='{privacy_policy}'>Privacy policy</a> and agree with them." -msgstr "" - -#: aleksis/core/forms.py:575 -msgid "You must type the same password each time." -msgstr "" - -#: aleksis/core/forms.py:720 +#: aleksis/core/forms.py:752 msgid "No valid selection." msgstr "" @@ -240,24 +239,20 @@ msgstr "" msgid "There are unresolved data problems." msgstr "" -#: aleksis/core/health_checks.py:38 -msgid "The backup folder doesn't exist." -msgstr "" - -#: aleksis/core/health_checks.py:47 +#: aleksis/core/health_checks.py:44 #, python-brace-format msgid "Last backup {time_gone_since_backup}!" msgstr "" -#: aleksis/core/health_checks.py:49 +#: aleksis/core/health_checks.py:46 msgid "No backup found!" msgstr "" -#: aleksis/core/health_checks.py:76 +#: aleksis/core/health_checks.py:73 msgid "No backup result found!" msgstr "" -#: aleksis/core/health_checks.py:78 +#: aleksis/core/health_checks.py:75 #, python-brace-format msgid "{task.status} - {task.result}" msgstr "" @@ -273,34 +268,38 @@ msgstr "" msgid "Sign up" msgstr "" -#: aleksis/core/menus.py:24 +#: aleksis/core/menus.py:24 aleksis/core/templates/invitations/enter.html:7 +msgid "Accept invitation" +msgstr "" + +#: aleksis/core/menus.py:33 msgid "Dashboard" msgstr "" -#: aleksis/core/menus.py:32 aleksis/core/models.py:625 -#: aleksis/core/preferences.py:27 +#: aleksis/core/menus.py:41 aleksis/core/models.py:627 +#: aleksis/core/preferences.py:28 #: aleksis/core/templates/core/notifications.html:4 #: aleksis/core/templates/core/notifications.html:5 msgid "Notifications" msgstr "" -#: aleksis/core/menus.py:44 +#: aleksis/core/menus.py:53 msgid "Account" msgstr "" -#: aleksis/core/menus.py:51 +#: aleksis/core/menus.py:60 msgid "Stop impersonation" msgstr "" -#: aleksis/core/menus.py:60 aleksis/core/templates/core/base.html:80 +#: aleksis/core/menus.py:69 aleksis/core/templates/core/base.html:80 msgid "Logout" msgstr "" -#: aleksis/core/menus.py:66 +#: aleksis/core/menus.py:75 msgid "2FA" msgstr "" -#: aleksis/core/menus.py:74 +#: aleksis/core/menus.py:83 #: aleksis/core/templates/account/password_change.html:5 #: aleksis/core/templates/account/password_change.html:6 #: aleksis/core/templates/account/password_change.html:19 @@ -312,830 +311,850 @@ msgstr "" msgid "Change password" msgstr "" -#: aleksis/core/menus.py:86 +#: aleksis/core/menus.py:95 msgid "Me" msgstr "" -#: aleksis/core/menus.py:95 +#: aleksis/core/menus.py:104 #: aleksis/core/templates/dynamic_preferences/form.html:5 msgid "Preferences" msgstr "" -#: aleksis/core/menus.py:104 +#: aleksis/core/menus.py:113 msgid "Third-party accounts" msgstr "" -#: aleksis/core/menus.py:113 +#: aleksis/core/menus.py:122 #: aleksis/core/templates/oauth2_provider/authorized-tokens.html:5 #: aleksis/core/templates/oauth2_provider/authorized-tokens.html:6 msgid "Authorized applications" msgstr "" -#: aleksis/core/menus.py:124 +#: aleksis/core/menus.py:133 msgid "Admin" msgstr "" -#: aleksis/core/menus.py:132 aleksis/core/models.py:725 +#: aleksis/core/menus.py:141 aleksis/core/models.py:727 #: aleksis/core/templates/core/announcement/list.html:7 #: aleksis/core/templates/core/announcement/list.html:8 msgid "Announcements" msgstr "" -#: aleksis/core/menus.py:143 aleksis/core/models.py:126 +#: aleksis/core/menus.py:152 aleksis/core/models.py:130 #: aleksis/core/templates/core/school_term/list.html:8 #: aleksis/core/templates/core/school_term/list.html:9 msgid "School terms" msgstr "" -#: aleksis/core/menus.py:154 +#: aleksis/core/menus.py:163 #: aleksis/core/templates/core/dashboard_widget/list.html:8 #: aleksis/core/templates/core/dashboard_widget/list.html:9 msgid "Dashboard widgets" msgstr "" -#: aleksis/core/menus.py:165 +#: aleksis/core/menus.py:174 #: aleksis/core/templates/core/management/data_management.html:6 #: aleksis/core/templates/core/management/data_management.html:7 msgid "Data management" msgstr "" -#: aleksis/core/menus.py:176 +#: aleksis/core/menus.py:185 #: aleksis/core/templates/core/pages/system_status.html:5 #: aleksis/core/templates/core/pages/system_status.html:7 msgid "System status" msgstr "" -#: aleksis/core/menus.py:187 -msgid "Impersonation" -msgstr "" - -#: aleksis/core/menus.py:198 +#: aleksis/core/menus.py:196 msgid "Configuration" msgstr "" -#: aleksis/core/menus.py:209 aleksis/core/templates/core/data_check/list.html:9 +#: aleksis/core/menus.py:207 aleksis/core/templates/core/data_check/list.html:9 #: aleksis/core/templates/core/data_check/list.html:10 msgid "Data checks" msgstr "" -#: aleksis/core/menus.py:215 aleksis/core/templates/core/perms/list.html:13 +#: aleksis/core/menus.py:213 aleksis/core/templates/core/perms/list.html:13 #: aleksis/core/templates/core/perms/list.html:14 msgid "Manage permissions" msgstr "" -#: aleksis/core/menus.py:226 +#: aleksis/core/menus.py:224 msgid "Backend Admin" msgstr "" -#: aleksis/core/menus.py:234 +#: aleksis/core/menus.py:232 #: aleksis/core/templates/oauth2_provider/application/list.html:5 #: aleksis/core/templates/oauth2_provider/application/list.html:6 msgid "OAuth2 Applications" msgstr "" -#: aleksis/core/menus.py:247 +#: aleksis/core/menus.py:245 msgid "People" msgstr "" -#: aleksis/core/menus.py:278 aleksis/core/models.py:979 +#: aleksis/core/menus.py:276 aleksis/core/models.py:981 #: aleksis/core/templates/core/group_type/list.html:8 #: aleksis/core/templates/core/group_type/list.html:9 msgid "Group types" msgstr "" -#: aleksis/core/menus.py:289 +#: aleksis/core/menus.py:287 msgid "Groups and child groups" msgstr "" -#: aleksis/core/menus.py:300 aleksis/core/models.py:460 +#: aleksis/core/menus.py:298 aleksis/core/models.py:462 #: aleksis/core/templates/core/additional_field/list.html:8 #: aleksis/core/templates/core/additional_field/list.html:9 msgid "Additional fields" msgstr "" -#: aleksis/core/menus.py:315 +#: aleksis/core/menus.py:309 +msgid "Invite person" +msgstr "" + +#: aleksis/core/menus.py:322 #: aleksis/core/templates/core/group/child_groups.html:7 #: aleksis/core/templates/core/group/child_groups.html:9 msgid "Assign child groups to groups" msgstr "" -#: aleksis/core/mixins.py:508 +#: aleksis/core/mixins.py:511 msgid "Linked school term" msgstr "" -#: aleksis/core/models.py:66 +#: aleksis/core/models.py:70 msgid "Boolean (Yes/No)" msgstr "" -#: aleksis/core/models.py:67 +#: aleksis/core/models.py:71 msgid "Text (one line)" msgstr "" -#: aleksis/core/models.py:69 +#: aleksis/core/models.py:73 msgid "Date and time" msgstr "" -#: aleksis/core/models.py:70 +#: aleksis/core/models.py:74 msgid "Decimal number" msgstr "" -#: aleksis/core/models.py:71 aleksis/core/models.py:194 +#: aleksis/core/models.py:75 aleksis/core/models.py:198 msgid "E-mail address" msgstr "" -#: aleksis/core/models.py:72 +#: aleksis/core/models.py:76 msgid "Integer" msgstr "" -#: aleksis/core/models.py:73 +#: aleksis/core/models.py:77 msgid "IP address" msgstr "" -#: aleksis/core/models.py:74 +#: aleksis/core/models.py:78 msgid "Boolean or empty (Yes/No/Neither)" msgstr "" -#: aleksis/core/models.py:75 +#: aleksis/core/models.py:79 msgid "Text (multi-line)" msgstr "" -#: aleksis/core/models.py:77 +#: aleksis/core/models.py:81 msgid "URL / Link" msgstr "" -#: aleksis/core/models.py:89 aleksis/core/models.py:948 +#: aleksis/core/models.py:93 aleksis/core/models.py:950 msgid "Name" msgstr "" -#: aleksis/core/models.py:91 +#: aleksis/core/models.py:95 msgid "Start date" msgstr "" -#: aleksis/core/models.py:92 +#: aleksis/core/models.py:96 msgid "End date" msgstr "" -#: aleksis/core/models.py:111 +#: aleksis/core/models.py:115 msgid "The start date must be earlier than the end date." msgstr "" -#: aleksis/core/models.py:118 +#: aleksis/core/models.py:122 msgid "There is already a school term for this time or a part of this time." msgstr "" -#: aleksis/core/models.py:147 aleksis/core/models.py:897 +#: aleksis/core/models.py:151 aleksis/core/models.py:899 msgid "Person" msgstr "" -#: aleksis/core/models.py:150 +#: aleksis/core/models.py:154 msgid "Can view address" msgstr "" -#: aleksis/core/models.py:151 +#: aleksis/core/models.py:155 msgid "Can view contact details" msgstr "" -#: aleksis/core/models.py:152 +#: aleksis/core/models.py:156 msgid "Can view photo" msgstr "" -#: aleksis/core/models.py:153 +#: aleksis/core/models.py:157 msgid "Can view persons groups" msgstr "" -#: aleksis/core/models.py:154 +#: aleksis/core/models.py:158 msgid "Can view personal details" msgstr "" -#: aleksis/core/models.py:164 +#: aleksis/core/models.py:168 msgid "female" msgstr "" -#: aleksis/core/models.py:164 +#: aleksis/core/models.py:168 msgid "male" msgstr "" -#: aleksis/core/models.py:172 +#: aleksis/core/models.py:176 aleksis/core/models.py:1144 msgid "Linked user" msgstr "" -#: aleksis/core/models.py:174 +#: aleksis/core/models.py:178 msgid "Is person active?" msgstr "" -#: aleksis/core/models.py:176 +#: aleksis/core/models.py:180 msgid "First name" msgstr "" -#: aleksis/core/models.py:177 +#: aleksis/core/models.py:181 msgid "Last name" msgstr "" -#: aleksis/core/models.py:179 +#: aleksis/core/models.py:183 msgid "Additional name(s)" msgstr "" -#: aleksis/core/models.py:183 aleksis/core/models.py:429 +#: aleksis/core/models.py:187 aleksis/core/models.py:431 msgid "Short name" msgstr "" -#: aleksis/core/models.py:186 +#: aleksis/core/models.py:190 msgid "Street" msgstr "" -#: aleksis/core/models.py:187 +#: aleksis/core/models.py:191 msgid "Street number" msgstr "" -#: aleksis/core/models.py:188 +#: aleksis/core/models.py:192 msgid "Postal code" msgstr "" -#: aleksis/core/models.py:189 +#: aleksis/core/models.py:193 msgid "Place" msgstr "" -#: aleksis/core/models.py:191 +#: aleksis/core/models.py:195 msgid "Home phone" msgstr "" -#: aleksis/core/models.py:192 +#: aleksis/core/models.py:196 msgid "Mobile phone" msgstr "" -#: aleksis/core/models.py:196 +#: aleksis/core/models.py:200 msgid "Date of birth" msgstr "" -#: aleksis/core/models.py:198 +#: aleksis/core/models.py:201 msgid "Place of birth" msgstr "" -#: aleksis/core/models.py:200 +#: aleksis/core/models.py:202 msgid "Sex" msgstr "" -#: aleksis/core/models.py:202 +#: aleksis/core/models.py:204 msgid "Photo" msgstr "" -#: aleksis/core/models.py:206 aleksis/core/templates/core/person/full.html:138 +#: aleksis/core/models.py:208 aleksis/core/templates/core/person/full.html:145 msgid "Guardians / Parents" msgstr "" -#: aleksis/core/models.py:213 +#: aleksis/core/models.py:215 msgid "Primary group" msgstr "" -#: aleksis/core/models.py:216 aleksis/core/models.py:583 -#: aleksis/core/models.py:607 aleksis/core/models.py:692 -#: aleksis/core/models.py:972 aleksis/core/templates/core/person/full.html:121 +#: aleksis/core/models.py:218 aleksis/core/models.py:585 +#: aleksis/core/models.py:609 aleksis/core/models.py:694 +#: aleksis/core/models.py:974 aleksis/core/templates/core/person/full.html:128 msgid "Description" msgstr "" -#: aleksis/core/models.py:384 +#: aleksis/core/models.py:386 msgid "Title of field" msgstr "" -#: aleksis/core/models.py:386 +#: aleksis/core/models.py:388 msgid "Type of field" msgstr "" -#: aleksis/core/models.py:393 +#: aleksis/core/models.py:395 msgid "Addtitional field for groups" msgstr "" -#: aleksis/core/models.py:394 +#: aleksis/core/models.py:396 msgid "Addtitional fields for groups" msgstr "" -#: aleksis/core/models.py:414 +#: aleksis/core/models.py:416 msgid "Can assign child groups to groups" msgstr "" -#: aleksis/core/models.py:415 +#: aleksis/core/models.py:417 msgid "Can view statistics about group." msgstr "" -#: aleksis/core/models.py:427 +#: aleksis/core/models.py:429 msgid "Long name" msgstr "" -#: aleksis/core/models.py:437 aleksis/core/templates/core/group/full.html:85 +#: aleksis/core/models.py:439 aleksis/core/templates/core/group/full.html:85 msgid "Members" msgstr "" -#: aleksis/core/models.py:440 aleksis/core/templates/core/group/full.html:82 +#: aleksis/core/models.py:442 aleksis/core/templates/core/group/full.html:82 msgid "Owners" msgstr "" -#: aleksis/core/models.py:447 aleksis/core/templates/core/group/full.html:55 +#: aleksis/core/models.py:449 aleksis/core/templates/core/group/full.html:55 msgid "Parent groups" msgstr "" -#: aleksis/core/models.py:455 +#: aleksis/core/models.py:457 msgid "Type of group" msgstr "" -#: aleksis/core/models.py:582 aleksis/core/models.py:606 -#: aleksis/core/models.py:691 +#: aleksis/core/models.py:584 aleksis/core/models.py:608 +#: aleksis/core/models.py:693 #: aleksis/core/templates/core/announcement/list.html:18 msgid "Title" msgstr "" -#: aleksis/core/models.py:585 +#: aleksis/core/models.py:587 msgid "Application" msgstr "" -#: aleksis/core/models.py:591 +#: aleksis/core/models.py:593 msgid "Activity" msgstr "" -#: aleksis/core/models.py:592 +#: aleksis/core/models.py:594 msgid "Activities" msgstr "" -#: aleksis/core/models.py:598 +#: aleksis/core/models.py:600 msgid "Sender" msgstr "" -#: aleksis/core/models.py:603 +#: aleksis/core/models.py:605 msgid "Recipient" msgstr "" -#: aleksis/core/models.py:608 aleksis/core/models.py:949 +#: aleksis/core/models.py:610 aleksis/core/models.py:951 msgid "Link" msgstr "" -#: aleksis/core/models.py:610 +#: aleksis/core/models.py:612 msgid "Read" msgstr "" -#: aleksis/core/models.py:611 +#: aleksis/core/models.py:613 msgid "Sent" msgstr "" -#: aleksis/core/models.py:624 +#: aleksis/core/models.py:626 msgid "Notification" msgstr "" -#: aleksis/core/models.py:693 +#: aleksis/core/models.py:695 msgid "Link to detailed view" msgstr "" -#: aleksis/core/models.py:696 +#: aleksis/core/models.py:698 msgid "Date and time from when to show" msgstr "" -#: aleksis/core/models.py:699 +#: aleksis/core/models.py:701 msgid "Date and time until when to show" msgstr "" -#: aleksis/core/models.py:724 +#: aleksis/core/models.py:726 msgid "Announcement" msgstr "" -#: aleksis/core/models.py:762 +#: aleksis/core/models.py:764 msgid "Announcement recipient" msgstr "" -#: aleksis/core/models.py:763 +#: aleksis/core/models.py:765 msgid "Announcement recipients" msgstr "" -#: aleksis/core/models.py:818 +#: aleksis/core/models.py:820 msgid "Widget Title" msgstr "" -#: aleksis/core/models.py:819 +#: aleksis/core/models.py:821 msgid "Activate Widget" msgstr "" -#: aleksis/core/models.py:820 +#: aleksis/core/models.py:822 msgid "Widget is broken" msgstr "" -#: aleksis/core/models.py:823 +#: aleksis/core/models.py:825 msgid "Size on mobile devices" msgstr "" -#: aleksis/core/models.py:824 +#: aleksis/core/models.py:826 msgid "<= 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:829 +#: aleksis/core/models.py:831 msgid "Size on tablet devices" msgstr "" -#: aleksis/core/models.py:830 +#: aleksis/core/models.py:832 msgid "> 600 px, 12 columns" msgstr "" -#: aleksis/core/models.py:835 +#: aleksis/core/models.py:837 msgid "Size on desktop devices" msgstr "" -#: aleksis/core/models.py:836 +#: aleksis/core/models.py:838 msgid "> 992 px, 12 columns" msgstr "" -#: aleksis/core/models.py:841 +#: aleksis/core/models.py:843 msgid "Size on large desktop devices" msgstr "" -#: aleksis/core/models.py:842 +#: aleksis/core/models.py:844 msgid "> 1200 px>, 12 columns" msgstr "" -#: aleksis/core/models.py:873 +#: aleksis/core/models.py:875 msgid "Can edit default dashboard" msgstr "" -#: aleksis/core/models.py:874 +#: aleksis/core/models.py:876 msgid "Dashboard Widget" msgstr "" -#: aleksis/core/models.py:875 +#: aleksis/core/models.py:877 msgid "Dashboard Widgets" msgstr "" -#: aleksis/core/models.py:881 +#: aleksis/core/models.py:883 msgid "URL" msgstr "" -#: aleksis/core/models.py:882 +#: aleksis/core/models.py:884 msgid "Icon URL" msgstr "" -#: aleksis/core/models.py:888 +#: aleksis/core/models.py:890 msgid "External link widget" msgstr "" -#: aleksis/core/models.py:889 +#: aleksis/core/models.py:891 msgid "External link widgets" msgstr "" -#: aleksis/core/models.py:894 +#: aleksis/core/models.py:896 msgid "Dashboard widget" msgstr "" -#: aleksis/core/models.py:899 +#: aleksis/core/models.py:901 msgid "Order" msgstr "" -#: aleksis/core/models.py:900 +#: aleksis/core/models.py:902 msgid "Part of the default dashboard" msgstr "" -#: aleksis/core/models.py:915 +#: aleksis/core/models.py:917 msgid "Dashboard widget order" msgstr "" -#: aleksis/core/models.py:916 +#: aleksis/core/models.py:918 msgid "Dashboard widget orders" msgstr "" -#: aleksis/core/models.py:922 +#: aleksis/core/models.py:924 msgid "Menu ID" msgstr "" -#: aleksis/core/models.py:935 +#: aleksis/core/models.py:937 msgid "Custom menu" msgstr "" -#: aleksis/core/models.py:936 +#: aleksis/core/models.py:938 msgid "Custom menus" msgstr "" -#: aleksis/core/models.py:946 +#: aleksis/core/models.py:948 msgid "Menu" msgstr "" -#: aleksis/core/models.py:950 +#: aleksis/core/models.py:952 msgid "Icon" msgstr "" -#: aleksis/core/models.py:956 +#: aleksis/core/models.py:958 msgid "Custom menu item" msgstr "" -#: aleksis/core/models.py:957 +#: aleksis/core/models.py:959 msgid "Custom menu items" msgstr "" -#: aleksis/core/models.py:971 +#: aleksis/core/models.py:973 msgid "Title of type" msgstr "" -#: aleksis/core/models.py:978 aleksis/core/templates/core/group/full.html:47 +#: aleksis/core/models.py:980 aleksis/core/templates/core/group/full.html:47 msgid "Group type" msgstr "" -#: aleksis/core/models.py:992 +#: aleksis/core/models.py:994 msgid "Can view system status" msgstr "" -#: aleksis/core/models.py:993 +#: aleksis/core/models.py:995 msgid "Can manage data" msgstr "" -#: aleksis/core/models.py:994 +#: aleksis/core/models.py:996 msgid "Can impersonate" msgstr "" -#: aleksis/core/models.py:995 +#: aleksis/core/models.py:997 msgid "Can use search" msgstr "" -#: aleksis/core/models.py:996 +#: aleksis/core/models.py:998 msgid "Can change site preferences" msgstr "" -#: aleksis/core/models.py:997 +#: aleksis/core/models.py:999 msgid "Can change person preferences" msgstr "" -#: aleksis/core/models.py:998 +#: aleksis/core/models.py:1000 msgid "Can change group preferences" msgstr "" -#: aleksis/core/models.py:999 +#: aleksis/core/models.py:1001 msgid "Can test PDF generation" msgstr "" -#: aleksis/core/models.py:1035 +#: aleksis/core/models.py:1037 msgid "Related data check task" msgstr "" -#: aleksis/core/models.py:1043 +#: aleksis/core/models.py:1045 msgid "Issue solved" msgstr "" -#: aleksis/core/models.py:1044 +#: aleksis/core/models.py:1046 msgid "Notification sent" msgstr "" -#: aleksis/core/models.py:1057 +#: aleksis/core/models.py:1059 msgid "Data check result" msgstr "" -#: aleksis/core/models.py:1058 +#: aleksis/core/models.py:1060 msgid "Data check results" msgstr "" -#: aleksis/core/models.py:1060 +#: aleksis/core/models.py:1062 msgid "Can run data checks" msgstr "" -#: aleksis/core/models.py:1061 +#: aleksis/core/models.py:1063 msgid "Can solve data check problems" msgstr "" -#: aleksis/core/models.py:1076 +#: aleksis/core/models.py:1070 +msgid "E-Mail address" +msgstr "" + +#: aleksis/core/models.py:1094 msgid "Owner" msgstr "" -#: aleksis/core/models.py:1080 +#: aleksis/core/models.py:1098 msgid "File expires at" msgstr "" -#: aleksis/core/models.py:1082 +#: aleksis/core/models.py:1100 msgid "Generated HTML file" msgstr "" -#: aleksis/core/models.py:1084 +#: aleksis/core/models.py:1102 msgid "Generated PDF file" msgstr "" -#: aleksis/core/models.py:1091 +#: aleksis/core/models.py:1109 msgid "PDF file" msgstr "" -#: aleksis/core/models.py:1092 +#: aleksis/core/models.py:1110 msgid "PDF files" msgstr "" -#: aleksis/core/models.py:1097 +#: aleksis/core/models.py:1115 msgid "Task result" msgstr "" -#: aleksis/core/models.py:1100 +#: aleksis/core/models.py:1118 msgid "Task user" msgstr "" -#: aleksis/core/models.py:1112 +#: aleksis/core/models.py:1130 msgid "Task user assignment" msgstr "" -#: aleksis/core/models.py:1113 +#: aleksis/core/models.py:1131 msgid "Task user assignments" msgstr "" -#: aleksis/core/models.py:1127 +#: aleksis/core/models.py:1147 +msgid "Additional attributes" +msgstr "" + +#: aleksis/core/models.py:1185 msgid "Allowed scopes that clients can request" msgstr "" -#: aleksis/core/preferences.py:23 +#: aleksis/core/preferences.py:24 msgid "General" msgstr "" -#: aleksis/core/preferences.py:24 +#: aleksis/core/preferences.py:25 msgid "School" msgstr "" -#: aleksis/core/preferences.py:25 +#: aleksis/core/preferences.py:26 msgid "Theme" msgstr "" -#: aleksis/core/preferences.py:26 +#: aleksis/core/preferences.py:27 msgid "Mail" msgstr "" -#: aleksis/core/preferences.py:28 +#: aleksis/core/preferences.py:29 msgid "Footer" msgstr "" -#: aleksis/core/preferences.py:29 +#: aleksis/core/preferences.py:30 msgid "Accounts" msgstr "" -#: aleksis/core/preferences.py:30 +#: aleksis/core/preferences.py:31 msgid "Authentication" msgstr "" -#: aleksis/core/preferences.py:31 +#: aleksis/core/preferences.py:32 msgid "Internationalisation" msgstr "" -#: aleksis/core/preferences.py:42 +#: aleksis/core/preferences.py:43 msgid "Site title" msgstr "" -#: aleksis/core/preferences.py:53 +#: aleksis/core/preferences.py:54 msgid "Site description" msgstr "" -#: aleksis/core/preferences.py:64 +#: aleksis/core/preferences.py:65 msgid "Primary colour" msgstr "" -#: aleksis/core/preferences.py:76 +#: aleksis/core/preferences.py:77 msgid "Secondary colour" msgstr "" -#: aleksis/core/preferences.py:87 +#: aleksis/core/preferences.py:88 msgid "Logo" msgstr "" -#: aleksis/core/preferences.py:97 +#: aleksis/core/preferences.py:98 msgid "Favicon" msgstr "" -#: aleksis/core/preferences.py:107 +#: aleksis/core/preferences.py:108 msgid "PWA-Icon" msgstr "" -#: aleksis/core/preferences.py:118 +#: aleksis/core/preferences.py:119 msgid "Mail out name" msgstr "" -#: aleksis/core/preferences.py:129 +#: aleksis/core/preferences.py:130 msgid "Mail out address" msgstr "" -#: aleksis/core/preferences.py:141 +#: aleksis/core/preferences.py:142 msgid "Link to privacy policy" msgstr "" -#: aleksis/core/preferences.py:153 +#: aleksis/core/preferences.py:154 msgid "Link to imprint" msgstr "" -#: aleksis/core/preferences.py:165 +#: aleksis/core/preferences.py:166 msgid "Name format for addressing" msgstr "" -#: aleksis/core/preferences.py:181 +#: aleksis/core/preferences.py:182 msgid "Channels to use for notifications" msgstr "" -#: aleksis/core/preferences.py:193 +#: aleksis/core/preferences.py:194 msgid "Regular expression to match primary group, e.g. '^Class .*'" msgstr "" -#: aleksis/core/preferences.py:204 +#: aleksis/core/preferences.py:205 msgid "Field on person to match primary group against" msgstr "" -#: aleksis/core/preferences.py:216 +#: aleksis/core/preferences.py:217 msgid "Automatically create new persons for new users" msgstr "" -#: aleksis/core/preferences.py:225 +#: aleksis/core/preferences.py:226 msgid "Automatically link existing persons to new users by their e-mail address" msgstr "" -#: aleksis/core/preferences.py:236 +#: aleksis/core/preferences.py:237 msgid "Display name of the school" msgstr "" -#: aleksis/core/preferences.py:247 +#: aleksis/core/preferences.py:248 msgid "Official name of the school, e.g. as given by supervisory authority" msgstr "" -#: aleksis/core/preferences.py:255 +#: aleksis/core/preferences.py:256 msgid "Allow users to change their passwords" msgstr "" -#: aleksis/core/preferences.py:263 +#: aleksis/core/preferences.py:264 msgid "Enable signup" msgstr "" -#: aleksis/core/preferences.py:274 +#: aleksis/core/preferences.py:272 +msgid "Enable invitations" +msgstr "" + +#: aleksis/core/preferences.py:280 +msgid "Length of invite code. (Default 3: abcde-acbde-abcde)" +msgstr "" + +#: aleksis/core/preferences.py:288 +msgid "Size of packets. (Default 5: abcde)" +msgstr "" + +#: aleksis/core/preferences.py:298 msgid "Allowed Grant Flows for OAuth applications" msgstr "" -#: aleksis/core/preferences.py:287 +#: aleksis/core/preferences.py:311 msgid "Available languages" msgstr "" -#: aleksis/core/preferences.py:299 +#: aleksis/core/preferences.py:323 msgid "Send emails if data checks detect problems" msgstr "" -#: aleksis/core/preferences.py:310 +#: aleksis/core/preferences.py:334 msgid "Email recipients for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:321 +#: aleksis/core/preferences.py:345 msgid "Email recipient groups for data checks problem emails" msgstr "" -#: aleksis/core/preferences.py:330 +#: aleksis/core/preferences.py:354 msgid "Show dashboard to users without login" msgstr "" -#: aleksis/core/preferences.py:339 +#: aleksis/core/preferences.py:363 msgid "Allow users to edit their dashboard" msgstr "" -#: aleksis/core/preferences.py:350 +#: aleksis/core/preferences.py:374 msgid "Fields on person model which are editable by themselves." msgstr "" -#: aleksis/core/preferences.py:364 +#: aleksis/core/preferences.py:388 msgid "Editable fields on person model which should trigger a notification on change" msgstr "" -#: aleksis/core/preferences.py:377 +#: aleksis/core/preferences.py:401 msgid "Contact for notification if a person changes their data" msgstr "" -#: aleksis/core/preferences.py:387 +#: aleksis/core/preferences.py:411 msgid "PDF file expiration duration" msgstr "" -#: aleksis/core/preferences.py:388 +#: aleksis/core/preferences.py:412 msgid "in minutes" msgstr "" -#: aleksis/core/preferences.py:398 +#: aleksis/core/preferences.py:422 msgid "Automatically update the dashboard and its widgets" msgstr "" -#: aleksis/core/preferences.py:408 +#: aleksis/core/preferences.py:432 msgid "Automatically update the dashboard and its widgets sitewide" msgstr "" -#: aleksis/core/settings.py:474 +#: aleksis/core/settings.py:507 msgid "English" msgstr "" -#: aleksis/core/settings.py:475 +#: aleksis/core/settings.py:508 msgid "German" msgstr "" -#: aleksis/core/tables.py:19 +#: aleksis/core/tables.py:24 #: aleksis/core/templates/core/announcement/list.html:36 #: aleksis/core/templates/core/group/full.html:24 -#: aleksis/core/templates/core/person/full.html:23 +#: aleksis/core/templates/core/person/full.html:24 #: aleksis/core/templates/oauth2_provider/application/detail.html:17 msgid "Edit" msgstr "" -#: aleksis/core/tables.py:21 aleksis/core/tables.py:89 -#: aleksis/core/tables.py:105 +#: aleksis/core/tables.py:26 aleksis/core/tables.py:94 +#: aleksis/core/tables.py:137 #: aleksis/core/templates/core/announcement/list.html:22 msgid "Actions" msgstr "" -#: aleksis/core/tables.py:56 aleksis/core/tables.py:57 -#: aleksis/core/tables.py:71 aleksis/core/tables.py:87 -#: aleksis/core/tables.py:103 +#: aleksis/core/tables.py:61 aleksis/core/tables.py:62 +#: aleksis/core/tables.py:76 aleksis/core/tables.py:92 +#: aleksis/core/tables.py:135 #: aleksis/core/templates/core/announcement/list.html:42 #: aleksis/core/templates/core/group/full.html:31 #: aleksis/core/templates/core/pages/delete.html:22 -#: aleksis/core/templates/core/person/full.html:30 +#: aleksis/core/templates/core/person/full.html:31 #: aleksis/core/templates/oauth2_provider/application/detail.html:21 msgid "Delete" msgstr "" @@ -1207,11 +1226,11 @@ msgstr "" msgid "Account inactive" msgstr "" -#: aleksis/core/templates/account/account_inactive.html:13 +#: aleksis/core/templates/account/account_inactive.html:14 msgid "Account inactive." msgstr "" -#: aleksis/core/templates/account/account_inactive.html:15 +#: aleksis/core/templates/account/account_inactive.html:17 msgid "" "\n" " This account is currently inactive. If you think this is an\n" @@ -1363,11 +1382,11 @@ msgstr "" msgid "Signup closed" msgstr "" -#: aleksis/core/templates/account/signup_closed.html:13 +#: aleksis/core/templates/account/signup_closed.html:14 msgid "Signup closed." msgstr "" -#: aleksis/core/templates/account/signup_closed.html:15 +#: aleksis/core/templates/account/signup_closed.html:17 msgid "" "\n" " This sign up is currently closed. If you think this is an\n" @@ -1405,11 +1424,6 @@ msgid "" " " msgstr "" -#: aleksis/core/templates/account/verification_sent.html:30 -#, python-format -msgid "<strong>Note:</strong> you can still <a href=\"%(email_url)s\">change your e-mail address</a>" -msgstr "" - #: aleksis/core/templates/core/additional_field/edit.html:6 #: aleksis/core/templates/core/additional_field/edit.html:7 msgid "Edit additional field" @@ -1458,11 +1472,11 @@ msgid "Logged in as" msgstr "" #: aleksis/core/templates/core/base.html:175 -msgid "About AlekSIS — The Free School Information System" +msgid "About AlekSIS® — The Free School Information System" msgstr "" #: aleksis/core/templates/core/base.html:183 -msgid "Impress" +msgid "Imprint" msgstr "" #: aleksis/core/templates/core/base.html:191 @@ -1470,7 +1484,7 @@ msgid "Privacy Policy" msgstr "" #: aleksis/core/templates/core/base_print.html:72 -msgid "Powered by AlekSIS" +msgid "Powered by AlekSIS®" msgstr "" #: aleksis/core/templates/core/dashboard_widget/create.html:8 @@ -1685,7 +1699,7 @@ msgid "Edit group" msgstr "" #: aleksis/core/templates/core/group/full.html:38 -#: aleksis/core/templates/core/person/full.html:37 +#: aleksis/core/templates/core/person/full.html:38 msgid "Change preferences" msgstr "" @@ -1774,36 +1788,46 @@ msgid "No notifications available yet." msgstr "" #: aleksis/core/templates/core/pages/about.html:6 -#: aleksis/core/templates/core/pages/about.html:15 -msgid "About AlekSIS" +msgid "About AlekSIS®" msgstr "" #: aleksis/core/templates/core/pages/about.html:7 -msgid "AlekSIS – The Free School Information System" +msgid "AlekSIS® – The Free School Information System" +msgstr "" + +#: aleksis/core/templates/core/pages/about.html:15 +msgid "About AlekSIS" msgstr "" #: aleksis/core/templates/core/pages/about.html:17 msgid "" "\n" -" This platform is powered by AlekSIS, a web-based school information system (SIS) which can be used\n" +" This platform is powered by AlekSIS®, a web-based school information system (SIS) which can be used\n" " to manage and/or publish organisational artifacts of educational institutions. AlekSIS is free software and\n" " can be used by anyone.\n" " " msgstr "" -#: aleksis/core/templates/core/pages/about.html:25 +#: aleksis/core/templates/core/pages/about.html:24 +msgid "" +"\n" +" AlekSIS® is a registered trademark of the AlekSIS open source project, represented by Teckids e.V.\n" +" " +msgstr "" + +#: aleksis/core/templates/core/pages/about.html:30 msgid "Website of AlekSIS" msgstr "" -#: aleksis/core/templates/core/pages/about.html:26 +#: aleksis/core/templates/core/pages/about.html:31 msgid "Source code" msgstr "" -#: aleksis/core/templates/core/pages/about.html:35 +#: aleksis/core/templates/core/pages/about.html:40 msgid "Licence information" msgstr "" -#: aleksis/core/templates/core/pages/about.html:37 +#: aleksis/core/templates/core/pages/about.html:42 msgid "" "\n" " The core and the official apps of AlekSIS are licenced under the EUPL, version 1.2 or later. For licence\n" @@ -1812,23 +1836,23 @@ msgid "" " " msgstr "" -#: aleksis/core/templates/core/pages/about.html:45 +#: aleksis/core/templates/core/pages/about.html:50 msgid "Free/Open Source Licence" msgstr "" -#: aleksis/core/templates/core/pages/about.html:46 +#: aleksis/core/templates/core/pages/about.html:51 msgid "Other Licence" msgstr "" -#: aleksis/core/templates/core/pages/about.html:50 +#: aleksis/core/templates/core/pages/about.html:55 msgid "Full licence text" msgstr "" -#: aleksis/core/templates/core/pages/about.html:51 +#: aleksis/core/templates/core/pages/about.html:56 msgid "More information about the EUPL" msgstr "" -#: aleksis/core/templates/core/pages/about.html:90 +#: aleksis/core/templates/core/pages/about.html:95 #, python-format msgid "" "\n" @@ -2069,17 +2093,19 @@ msgstr "" msgid "Edit person" msgstr "" -#: aleksis/core/templates/core/person/full.html:44 -#: aleksis/core/templates/impersonate/list_users.html:7 -#: aleksis/core/templates/impersonate/list_users.html:8 +#: aleksis/core/templates/core/person/full.html:45 msgid "Impersonate" msgstr "" -#: aleksis/core/templates/core/person/full.html:50 +#: aleksis/core/templates/core/person/full.html:51 +msgid "Invite user" +msgstr "" + +#: aleksis/core/templates/core/person/full.html:57 msgid "Contact details" msgstr "" -#: aleksis/core/templates/core/person/full.html:131 +#: aleksis/core/templates/core/person/full.html:138 msgid "Children" msgstr "" @@ -2119,6 +2145,49 @@ msgstr "" msgid "Save preferences" msgstr "" +#: aleksis/core/templates/invitations/enter.html:21 +msgid "Accept your invitation" +msgstr "" + +#: aleksis/core/templates/invitations/enter.html:25 +msgid "" +"\n" +" Please enter your invitation code to register\n" +" your new user account:\n" +" " +msgstr "" + +#: aleksis/core/templates/invitations/enter.html:37 +msgid "Accept invite" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:9 +#: aleksis/core/templates/invitations/forms/_invite.html:10 +#: aleksis/core/templates/invitations/forms/_invite.html:21 +msgid "Invite" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:17 +msgid "Invite by email address" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:26 +msgid "Generate invitation code" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:29 +msgid "Generate code" +msgstr "" + +#: aleksis/core/templates/invitations/forms/_invite.html:33 +msgid "Invitations" +msgstr "" + +#: aleksis/core/templates/invitations/messages/invite_accepted.txt:3 +#, python-format +msgid "The invitation for %(email)s has been accepted." +msgstr "" + #: aleksis/core/templates/oauth2_provider/application/create.html:5 #: aleksis/core/templates/oauth2_provider/application/create.html:6 msgid "Register OAuth2 Application" @@ -2775,147 +2844,160 @@ msgstr "" msgid "SMS" msgstr "" -#: aleksis/core/util/pdf.py:105 +#: aleksis/core/util/pdf.py:113 msgid "Progress: Generate PDF file" msgstr "" -#: aleksis/core/util/pdf.py:106 +#: aleksis/core/util/pdf.py:114 msgid "Generating PDF file …" msgstr "" -#: aleksis/core/util/pdf.py:107 +#: aleksis/core/util/pdf.py:115 msgid "The PDF file has been generated successfully." msgstr "" -#: aleksis/core/util/pdf.py:108 +#: aleksis/core/util/pdf.py:116 msgid "There was a problem while generating the PDF file." msgstr "" -#: aleksis/core/util/pdf.py:111 +#: aleksis/core/util/pdf.py:119 msgid "Download PDF" msgstr "" -#: aleksis/core/views.py:270 +#: aleksis/core/views.py:280 msgid "The school term has been created." msgstr "" -#: aleksis/core/views.py:282 +#: aleksis/core/views.py:292 msgid "The school term has been saved." msgstr "" -#: aleksis/core/views.py:406 +#: aleksis/core/views.py:416 msgid "The child groups were successfully saved." msgstr "" -#: aleksis/core/views.py:425 aleksis/core/views.py:435 +#: aleksis/core/views.py:435 aleksis/core/views.py:445 msgid "The person has been saved." msgstr "" -#: aleksis/core/views.py:485 +#: aleksis/core/views.py:495 msgid "The group has been saved." msgstr "" -#: aleksis/core/views.py:582 +#: aleksis/core/views.py:592 msgid "The announcement has been saved." msgstr "" -#: aleksis/core/views.py:598 +#: aleksis/core/views.py:608 msgid "The announcement has been deleted." msgstr "" -#: aleksis/core/views.py:682 +#: aleksis/core/views.py:695 msgid "The preferences have been saved successfully." msgstr "" -#: aleksis/core/views.py:706 +#: aleksis/core/views.py:719 msgid "The person has been deleted." msgstr "" -#: aleksis/core/views.py:720 +#: aleksis/core/views.py:733 msgid "The group has been deleted." msgstr "" -#: aleksis/core/views.py:752 +#: aleksis/core/views.py:765 msgid "The additional_field has been saved." msgstr "" -#: aleksis/core/views.py:786 +#: aleksis/core/views.py:799 msgid "The additional field has been deleted." msgstr "" -#: aleksis/core/views.py:811 +#: aleksis/core/views.py:824 msgid "The group type has been saved." msgstr "" -#: aleksis/core/views.py:841 +#: aleksis/core/views.py:854 msgid "The group type has been deleted." msgstr "" -#: aleksis/core/views.py:874 +#: aleksis/core/views.py:887 msgid "Progress: Run data checks" msgstr "" -#: aleksis/core/views.py:875 +#: aleksis/core/views.py:888 msgid "Run data checks …" msgstr "" -#: aleksis/core/views.py:876 +#: aleksis/core/views.py:889 msgid "The data checks were run successfully." msgstr "" -#: aleksis/core/views.py:877 +#: aleksis/core/views.py:890 msgid "There was a problem while running data checks." msgstr "" -#: aleksis/core/views.py:893 +#: aleksis/core/views.py:906 #, python-brace-format msgid "The solve option '{solve_option_obj.verbose_name}' " msgstr "" -#: aleksis/core/views.py:935 +#: aleksis/core/views.py:948 msgid "The dashboard widget has been saved." msgstr "" -#: aleksis/core/views.py:965 +#: aleksis/core/views.py:978 msgid "The dashboard widget has been created." msgstr "" -#: aleksis/core/views.py:975 +#: aleksis/core/views.py:988 msgid "The dashboard widget has been deleted." msgstr "" -#: aleksis/core/views.py:1042 +#: aleksis/core/views.py:1055 msgid "Your dashboard configuration has been saved successfully." msgstr "" -#: aleksis/core/views.py:1044 +#: aleksis/core/views.py:1057 msgid "The configuration of the default dashboard has been saved successfully." msgstr "" -#: aleksis/core/views.py:1139 +#: aleksis/core/views.py:1127 +#, python-brace-format +msgid "The invitation was successfully created. The invitation code is {code}" +msgstr "" + +#: aleksis/core/views.py:1218 msgid "We have successfully assigned the permissions." msgstr "" -#: aleksis/core/views.py:1149 +#: aleksis/core/views.py:1228 msgid "The global user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1159 +#: aleksis/core/views.py:1238 msgid "The global group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1169 +#: aleksis/core/views.py:1248 msgid "The object user permission has been deleted." msgstr "" -#: aleksis/core/views.py:1179 +#: aleksis/core/views.py:1258 msgid "The object group permission has been deleted." msgstr "" -#: aleksis/core/views.py:1298 +#: aleksis/core/views.py:1377 msgid "The third-party account could not be disconnected because it is the only login method available." msgstr "" -#: aleksis/core/views.py:1305 +#: aleksis/core/views.py:1384 msgid "The third-party account has been successfully disconnected." msgstr "" + +#: aleksis/core/views.py:1441 +msgid "Person was invited successfully." +msgstr "" + +#: aleksis/core/views.py:1443 +msgid "Person was already invited." +msgstr "" diff --git a/aleksis/core/locale/tr_TR/LC_MESSAGES/djangojs.po b/aleksis/core/locale/tr_TR/LC_MESSAGES/djangojs.po index 2458849847f712fe1cf63743640716c5b3ef561a..d67bdb0055bf1ee96915909ce9e21023085c466b 100644 --- a/aleksis/core/locale/tr_TR/LC_MESSAGES/djangojs.po +++ b/aleksis/core/locale/tr_TR/LC_MESSAGES/djangojs.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-29 09:59+0100\n" +"POT-Creation-Date: 2021-12-28 12:14+0100\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" @@ -29,6 +29,6 @@ msgstr "" msgid "OK" msgstr "" -#: aleksis/core/static/js/main.js:127 +#: aleksis/core/static/js/main.js:128 msgid "This page may contain outdated information since there is no internet connection." msgstr "" diff --git a/aleksis/core/managers.py b/aleksis/core/managers.py index aed4cab72d4b0cd53d3544b20f0180a7087dfd2c..7a549775f1730d57f83e6c3486644fd2c3bdda65 100644 --- a/aleksis/core/managers.py +++ b/aleksis/core/managers.py @@ -7,6 +7,7 @@ from django.db.models import QuerySet from django.db.models.manager import Manager from calendarweek import CalendarWeek +from django_cte import CTEManager, CTEQuerySet from polymorphic.managers import PolymorphicManager @@ -84,15 +85,15 @@ class SchoolTermRelatedQuerySet(QuerySet): return None -class GroupManager(CurrentSiteManagerWithoutMigrations): +class GroupManager(CurrentSiteManagerWithoutMigrations, CTEManager): """Manager adding specific methods to groups.""" def get_queryset(self): """Ensure all related data is loaded as well.""" - return super().get_queryset().select_related("school_term") + return Manager.get_queryset(self).select_related("school_term") -class GroupQuerySet(SchoolTermRelatedQuerySet): +class GroupQuerySet(SchoolTermRelatedQuerySet, CTEQuerySet): pass diff --git a/aleksis/core/menus.py b/aleksis/core/menus.py index 924e34af935c9b171dba20a3389afa6c775adaa2..7938539c53327936d86d6c08334834e8e2a4fb0a 100644 --- a/aleksis/core/menus.py +++ b/aleksis/core/menus.py @@ -20,6 +20,15 @@ MENUS = { ("aleksis.core.util.predicates.permission_validator", "core.can_register"), ], }, + { + "name": _("Accept invitation"), + "url": "enter_invitation_code", + "icon": "vpn_key", + "validators": [ + "menu_generator.validators.is_anonymous", + ("aleksis.core.util.predicates.permission_validator", "core.invite_enabled"), + ], + }, { "name": _("Dashboard"), "url": "index", @@ -183,17 +192,6 @@ MENUS = { ), ], }, - { - "name": _("Impersonation"), - "url": "impersonate-list", - "icon": "people", - "validators": [ - ( - "aleksis.core.util.predicates.permission_validator", - "core.impersonate_rule", - ), - ], - }, { "name": _("Configuration"), "url": "preferences_site", @@ -307,6 +305,15 @@ MENUS = { ) ], }, + { + "name": _("Invite person"), + "url": "invite_person", + "icon": "card_giftcard", + "validators": [ + "menu_generator.validators.is_authenticated", + ("aleksis.core.util.predicates.permission_validator", "core.can_invite"), + ], + }, ], }, ], diff --git a/aleksis/core/migrations/0028_char_field_not_null.py b/aleksis/core/migrations/0028_char_field_not_null.py new file mode 100644 index 0000000000000000000000000000000000000000..76c715e03f35d94d92ed26a67b7796f6901b8f10 --- /dev/null +++ b/aleksis/core/migrations/0028_char_field_not_null.py @@ -0,0 +1,25 @@ +# Generated by Django 3.2.10 on 2021-12-15 21:10 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0027_person_place_of_birth'), + ] + + operations = [ + migrations.AlterField( + model_name='oauthapplication', + name='authorization_grant_type', + field=models.CharField(blank=True, choices=[('authorization-code', 'Authorization code'), ('implicit', 'Implicit'), ('password', 'Resource owner password-based'), ('client-credentials', 'Client credentials'), ('openid-hybrid', 'OpenID connect hybrid')], default='', max_length=32), + preserve_default=False, + ), + migrations.AlterField( + model_name='person', + name='place_of_birth', + field=models.CharField(blank=True, default='', max_length=255, verbose_name='Place of birth'), + preserve_default=False, + ), + ] diff --git a/aleksis/core/migrations/0029_invitations.py b/aleksis/core/migrations/0029_invitations.py new file mode 100644 index 0000000000000000000000000000000000000000..0c4410267bf7064dbb0b8c9b57ff7f15a9645e93 --- /dev/null +++ b/aleksis/core/migrations/0029_invitations.py @@ -0,0 +1,34 @@ +# Generated by Django 3.1.7 on 2021-03-31 16:55 + +import aleksis.core.mixins +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('core', '0028_char_field_not_null'), + ] + + operations = [ + migrations.CreateModel( + name='PersonInvitation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('accepted', models.BooleanField(default=False, verbose_name='accepted')), + ('key', models.CharField(max_length=64, unique=True, verbose_name='key')), + ('sent', models.DateTimeField(null=True, verbose_name='sent')), + ('email', models.EmailField(blank=True, max_length=254, verbose_name='E-Mail address')), + ('inviter', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('person', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='invitation', to='core.person')) + ], + options={ + 'abstract': False, + }, + bases=(models.Model, aleksis.core.mixins.PureDjangoModel), + ), + ] diff --git a/aleksis/core/migrations/0030_user_attributes.py b/aleksis/core/migrations/0030_user_attributes.py new file mode 100644 index 0000000000000000000000000000000000000000..38434842aae54f5f4ad004094c33c524dd0a69ba --- /dev/null +++ b/aleksis/core/migrations/0030_user_attributes.py @@ -0,0 +1,46 @@ +# Generated by Django 3.2.10 on 2021-12-25 10:59 + +import aleksis.core.mixins +from django.conf import settings +from django.contrib.auth import get_user_model +from django.db import migrations, models +import django.db.models.deletion + + +def assume_ldap_authenticated_true(apps, schema_editor): + """Set ldap_authenticated user attribute to True to protect existing sites.""" + if not hasattr(settings, "AUTH_LDAP_SERVER_URI"): + # Skip if LDAP is not used on site + return + + User = get_user_model() + UserAdditionalAttributes = apps.get_model("core", "UserAdditionalAttributes") + + db_alias = schema_editor.connection.alias + + attributes = [ + UserAdditionalAttributes(user_id=user.pk, attributes={"ldap_authenticated": True}) + for user in User.objects.using(db_alias).all() + ] + UserAdditionalAttributes.objects.using(db_alias).bulk_create(attributes) + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('core', '0029_invitations'), + ] + + operations = [ + migrations.CreateModel( + name='UserAdditionalAttributes', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('attributes', models.JSONField(default=dict, verbose_name='Additional attributes')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='additional_attributes', to=settings.AUTH_USER_MODEL, verbose_name='Linked user')), + ], + bases=(models.Model, aleksis.core.mixins.PureDjangoModel), + ), + migrations.RunPython(assume_ldap_authenticated_true, lambda a, s: None), + ] diff --git a/aleksis/core/migrations/0031_oauthapplication_icon.py b/aleksis/core/migrations/0031_oauthapplication_icon.py new file mode 100644 index 0000000000000000000000000000000000000000..26f2d6575e768578e653088c582fd3dadd147dc5 --- /dev/null +++ b/aleksis/core/migrations/0031_oauthapplication_icon.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.11 on 2022-01-08 13:59 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0030_user_attributes'), + ] + + operations = [ + migrations.AddField( + model_name='oauthapplication', + name='icon', + field=models.ImageField(blank=True, help_text='This image will be shown as icon in the authorization flow. It should be squared.', null=True, upload_to='', verbose_name='Icon'), + ), + ] diff --git a/aleksis/core/migrations/0031_remove_person_is_active.py b/aleksis/core/migrations/0031_remove_person_is_active.py new file mode 100644 index 0000000000000000000000000000000000000000..a3c3f7a444964a62f7b69a293e9a452976f0300d --- /dev/null +++ b/aleksis/core/migrations/0031_remove_person_is_active.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.11 on 2022-01-08 10:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0030_user_attributes'), + ] + + operations = [ + migrations.RemoveField( + model_name='person', + name='is_active', + ), + ] diff --git a/aleksis/core/mixins.py b/aleksis/core/mixins.py index 3232aac4deb912dfb65f28d69831767bf2fd8445..c6cee9a8c6bbefed3439eef156b685f5484e4a13 100644 --- a/aleksis/core/mixins.py +++ b/aleksis/core/mixins.py @@ -1,5 +1,6 @@ # flake8: noqa: DJ12 +import os from datetime import datetime from typing import Any, Callable, List, Optional, Union @@ -21,6 +22,8 @@ from django.views.generic import CreateView, UpdateView from django.views.generic.edit import DeleteView, ModelFormMixin import reversion +from dynamic_preferences.settings import preferences_settings +from dynamic_preferences.types import FilePreference from guardian.admin import GuardedModelAdmin from guardian.core import ObjectPermissionChecker from jsonstore.fields import IntegerField, JSONFieldMixin @@ -529,3 +532,14 @@ class SchoolTermRelatedExtensibleForm(ExtensibleForm): kwargs["initial"] = {"school_term": SchoolTerm.current} super().__init__(*args, **kwargs) + + +class PublicFilePreferenceMixin(FilePreference): + """Uploads a file to the public namespace.""" + + upload_path = "public" + + def get_upload_path(self): + return os.path.join( + self.upload_path, preferences_settings.FILE_PREFERENCE_UPLOAD_DIR, self.identifier() + ) diff --git a/aleksis/core/models.py b/aleksis/core/models.py index 1176c743b53ca432ca5d800245b8b1d4cb67ecae..cac2d9d950e9d968983584ab3dbd0bf59405269b 100644 --- a/aleksis/core/models.py +++ b/aleksis/core/models.py @@ -1,7 +1,7 @@ # flake8: noqa: DJ01 import hmac from datetime import date, datetime, timedelta -from typing import Iterable, List, Optional, Sequence, Union +from typing import Any, Iterable, List, Optional, Sequence, Union from urllib.parse import urlparse from django.conf import settings @@ -14,7 +14,7 @@ from django.contrib.sites.models import Site from django.core.exceptions import ValidationError from django.core.validators import MaxValueValidator from django.db import models, transaction -from django.db.models import QuerySet +from django.db.models import Q, QuerySet from django.db.models.signals import m2m_changed from django.dispatch import receiver from django.forms.widgets import Media @@ -28,8 +28,13 @@ import jsonstore from cachalot.api import cachalot_disabled from cache_memoize import cache_memoize from django_celery_results.models import TaskResult +from django_cte import CTEQuerySet, With from dynamic_preferences.models import PerInstancePreferenceModel from image_cropping import ImageCropField, ImageRatioField +from invitations import signals +from invitations.adapters import get_invitations_adapter +from invitations.base_invitation import AbstractBaseInvitation +from invitations.models import Invitation from model_utils import FieldTracker from model_utils.models import TimeStampedModel from oauth2_provider.models import ( @@ -60,7 +65,7 @@ from .mixins import ( SchoolTermRelatedExtensibleModel, ) from .tasks import send_notification -from .util.core_helpers import get_site_preferences, now_tomorrow +from .util.core_helpers import generate_random_code, get_site_preferences, now_tomorrow from .util.model_helpers import ICONS FIELD_CHOICES = ( @@ -172,7 +177,6 @@ class Person(ExtensibleModel): related_name="person", verbose_name=_("Linked user"), ) - is_active = models.BooleanField(verbose_name=_("Is person active?"), default=True) first_name = models.CharField(verbose_name=_("First name"), max_length=255) last_name = models.CharField(verbose_name=_("Last name"), max_length=255) @@ -195,9 +199,7 @@ class Person(ExtensibleModel): email = models.EmailField(verbose_name=_("E-mail address"), blank=True) date_of_birth = models.DateField(verbose_name=_("Date of birth"), blank=True, null=True) - place_of_birth = models.CharField( - verbose_name=_("Place of birth"), max_length=255, blank=True, null=True - ) + place_of_birth = models.CharField(verbose_name=_("Place of birth"), max_length=255, blank=True) sex = models.CharField(verbose_name=_("Sex"), max_length=1, choices=SEX_CHOICES, blank=True) photo = ImageCropField( @@ -316,6 +318,22 @@ class Person(ExtensibleModel): user_info_tracker = FieldTracker(fields=("first_name", "last_name", "email")) + @property + def member_of_recursive(self) -> QuerySet: + """Get all groups this person is a member of, recursively.""" + q = self.member_of + for group in q.all(): + q = q.union(group.parent_groups_recursive) + return q + + @property + def owner_of_recursive(self) -> QuerySet: + """Get all groups this person is a member of, recursively.""" + q = self.owner_of + for group in q.all(): + q = q.union(group.child_groups_recursive) + return q + def save(self, *args, **kwargs): # Determine all fields that were changed since last load dirty = self.pk is None or bool(self.user_info_tracker.changed()) @@ -523,6 +541,50 @@ class Group(SchoolTermRelatedExtensibleModel): return stats + @property + def parent_groups_recursive(self) -> CTEQuerySet: + """Get all parent groups recursively.""" + + def _make_cte(cte): + Through = self.parent_groups.through + return ( + Through.objects.values("to_group_id") + .filter(from_group=self) + .union(cte.join(Through, from_group=cte.col.to_group_id), all=True) + ) + + cte = With.recursive(_make_cte) + return cte.join(Group, id=cte.col.to_group_id).with_cte(cte) + + @property + def child_groups_recursive(self) -> CTEQuerySet: + """Get all child groups recursively.""" + + def _make_cte(cte): + Through = self.child_groups.through + return ( + Through.objects.values("from_group_id") + .filter(to_group=self) + .union(cte.join(Through, to_group=cte.col.from_group_id), all=True) + ) + + cte = With.recursive(_make_cte) + return cte.join(Group, id=cte.col.from_group_id).with_cte(cte) + + @property + def members_recursive(self) -> QuerySet: + """Get all members of this group and its child groups.""" + return Person.objects.filter( + Q(member_of=self) | Q(member_of__in=self.child_groups_recursive) + ) + + @property + def owners_recursive(self) -> QuerySet: + """Get all ownerss of this group and its parent groups.""" + return Person.objects.filter( + Q(owner_of=self) | Q(owner_of__in=self.parent_groups_recursive) + ) + def __str__(self) -> str: if self.school_term: return f"{self.name} ({self.short_name}) ({self.school_term})" @@ -1101,6 +1163,22 @@ class DataCheckResult(ExtensibleModel): ) +class PersonInvitation(AbstractBaseInvitation, PureDjangoModel): + """Custom model for invitations to allow to generate invitations codes without email address.""" + + email = models.EmailField(verbose_name=_("E-Mail address"), blank=True) + person = models.ForeignKey( + Person, on_delete=models.CASCADE, blank=True, related_name="invitation", null=True + ) + + def __str__(self) -> str: + return f"{self.email} ({self.inviter})" + + key_expired = Invitation.key_expired + + send_invitation = Invitation.send_invitation + + class PDFFile(ExtensibleModel): """Link to a rendered PDF file.""" @@ -1152,12 +1230,52 @@ class TaskUserAssignment(ExtensibleModel): verbose_name_plural = _("Task user assignments") +class UserAdditionalAttributes(models.Model, PureDjangoModel): + """Additional attributes for Django user accounts. + + These attributes are explicitly linked to a User, not to a Person. + """ + + user = models.OneToOneField( + get_user_model(), + on_delete=models.CASCADE, + related_name="additional_attributes", + verbose_name=_("Linked user"), + ) + + attributes = models.JSONField(verbose_name=_("Additional attributes"), default=dict) + + @classmethod + def get_user_attribute( + cls, username: str, attribute: str, default: Optional[Any] = None + ) -> Any: + """Get a user attribute for a user by name.""" + try: + attributes = cls.objects.get(user__username=username) + except cls.DoesNotExist: + return default + + return attributes.attributes.get(attribute, default) + + @classmethod + def set_user_attribute(cls, username: str, attribute: str, value: Any): + """Set a user attribute for a user by name. + + Raises DoesNotExist if a username for a non-existing Django user is passed. + """ + user = get_user_model().objects.get(username=username) + attributes, __ = cls.objects.update_or_create(user=user) + + attributes.attributes[attribute] = value + attributes.save() + + class OAuthApplication(AbstractApplication): """Modified OAuth application class that supports Grant Flows configured in preferences.""" # Override grant types to make field optional authorization_grant_type = models.CharField( - max_length=32, choices=AbstractApplication.GRANT_TYPES, blank=True, null=True + max_length=32, choices=AbstractApplication.GRANT_TYPES, blank=True ) # Optional list of alloewd scopes @@ -1168,6 +1286,15 @@ class OAuthApplication(AbstractApplication): blank=True, ) + icon = models.ImageField( + verbose_name=_("Icon"), + blank=True, + null=True, + help_text=_( + "This image will be shown as icon in the authorization flow. It should be squared." + ), + ) + def allows_grant_type(self, *grant_types: set[str]) -> bool: allowed_grants = get_site_preferences()["auth__oauth_allowed_grants"] diff --git a/aleksis/core/preferences.py b/aleksis/core/preferences.py index d0de22fe03cc044fa5722982dfcc7faf86a4503c..cb351100a5da31c4d5cffc2255542bc86f4a77c1 100644 --- a/aleksis/core/preferences.py +++ b/aleksis/core/preferences.py @@ -3,6 +3,7 @@ from django.forms import EmailField, ImageField, URLField from django.forms.widgets import SelectMultiple from django.utils.translation import gettext_lazy as _ +import pycountry from colorfield.widgets import ColorWidget from dynamic_preferences.preferences import Section from dynamic_preferences.types import ( @@ -16,6 +17,7 @@ from dynamic_preferences.types import ( ) from oauth2_provider.models import AbstractApplication +from .mixins import PublicFilePreferenceMixin from .models import Group, Person from .registries import person_preferences_registry, site_preferences_registry from .util.notifications import get_notification_choices_lazy @@ -78,7 +80,7 @@ class ColourSecondary(StringPreference): @site_preferences_registry.register -class Logo(FilePreference): +class Logo(PublicFilePreferenceMixin, FilePreference): """Logo of your AlekSIS instance.""" section = theme @@ -88,7 +90,7 @@ class Logo(FilePreference): @site_preferences_registry.register -class Favicon(FilePreference): +class Favicon(PublicFilePreferenceMixin, FilePreference): """Favicon of your AlekSIS instance.""" section = theme @@ -98,7 +100,7 @@ class Favicon(FilePreference): @site_preferences_registry.register -class PWAIcon(FilePreference): +class PWAIcon(PublicFilePreferenceMixin, FilePreference): """PWA-Icon of your AlekSIS instance.""" section = theme @@ -263,6 +265,30 @@ class SignupEnabled(BooleanPreference): verbose_name = _("Enable signup") +@site_preferences_registry.register +class InviteEnabled(BooleanPreference): + section = auth + name = "invite_enabled" + default = False + verbose_name = _("Enable invitations") + + +@site_preferences_registry.register +class InviteCodeLength(IntegerPreference): + section = auth + name = "invite_code_length" + default = 3 + verbose_name = _("Length of invite code. (Default 3: abcde-acbde-abcde)") + + +@site_preferences_registry.register +class InviteCodePacketSize(IntegerPreference): + section = auth + name = "invite_code_packet_size" + default = 5 + verbose_name = _("Size of packets. (Default 5: abcde)") + + @site_preferences_registry.register class OAuthAllowedGrants(MultipleChoicePreference): """Grant Flows allowed for OAuth applications.""" @@ -406,3 +432,13 @@ class AutoUpdatingDashboardSite(BooleanPreference): name = "automatically_update_dashboard_site" default = True verbose_name = _("Automatically update the dashboard and its widgets sitewide") + + +@site_preferences_registry.register +class PhoneNumberCountry(ChoicePreference): + section = internationalisation + name = "phone_number_country" + required = True + default = "GB" + choices = [(x.alpha_2, x.alpha_2) for x in pycountry.countries] + verbose_name = _("Country for phone number parsing") diff --git a/aleksis/core/settings.py b/aleksis/core/settings.py index a72efec88014768c0c5a1243e8d9acc2f992d699..8e1207d490b839bbbdc9a7bda328451724779a83 100644 --- a/aleksis/core/settings.py +++ b/aleksis/core/settings.py @@ -1,4 +1,5 @@ import os +import warnings from glob import glob from socket import getfqdn @@ -15,6 +16,7 @@ IN_PYTEST = "PYTEST_CURRENT_TEST" in os.environ or "TOX_ENV_DIR" in os.environ ENVVAR_PREFIX_FOR_DYNACONF = "ALEKSIS" DIRS_FOR_DYNACONF = ["/etc/aleksis"] +MERGE_ENABLED_FOR_DYNACONF = True SETTINGS_FILE_FOR_DYNACONF = [] for directory in DIRS_FOR_DYNACONF: @@ -30,6 +32,7 @@ for directory in DIRS_FOR_DYNACONF: _settings = LazySettings( ENVVAR_PREFIX_FOR_DYNACONF=ENVVAR_PREFIX_FOR_DYNACONF, SETTINGS_FILE_FOR_DYNACONF=SETTINGS_FILE_FOR_DYNACONF, + MERGE_ENABLED_FOR_DYNACONF=MERGE_ENABLED_FOR_DYNACONF, ) # Build paths inside the project like this: os.path.join(BASE_DIR, ...) @@ -94,6 +97,7 @@ INSTALLED_APPS = [ "rules.apps.AutodiscoverRulesConfig", "haystack", "polymorphic", + "dj_cleavejs.apps.DjCleaveJSConfig", "dbbackup", "django_celery_beat", "django_celery_results", @@ -122,6 +126,7 @@ INSTALLED_APPS = [ "allauth", "allauth.account", "allauth.socialaccount", + "invitations", "health_check", "health_check.db", "health_check.cache", @@ -199,6 +204,14 @@ TEMPLATES = [ }, ] +# Attention: The following context processors must accept None +# as first argument (in addition to a HttpRequest object) +PDF_CONTEXT_PROCESSORS = [ + "django.template.context_processors.i18n", + "django.template.context_processors.tz", + "aleksis.core.util.core_helpers.custom_information_processor", +] + WSGI_APPLICATION = "aleksis.core.wsgi.application" # Database @@ -213,6 +226,7 @@ DATABASES = { "HOST": _settings.get("database.host", "127.0.0.1"), "PORT": _settings.get("database.port", "5432"), "CONN_MAX_AGE": _settings.get("database.conn_max_age", None), + "OPTIONS": _settings.get("database.options", {}), } } @@ -320,8 +334,11 @@ ACCOUNT_AUTHENTICATION_METHOD = _settings.get("auth.registration.method", "usern ACCOUNT_EMAIL_REQUIRED = _settings.get("auth.registration.email_required", True) SOCIALACCOUNT_EMAIL_REQUIRED = False -# Require email verification after sigm up -ACCOUNT_EMAIL_VERIFICATION = _settings.get("auth.registration.email_verification", "mandatory") +# Cooldown for verification mails +ACCOUNT_EMAIL_CONFIRMATION_COOLDOWN = _settings.get("auth.registration.verification_cooldown", 180) + +# Require email verification after sign up +ACCOUNT_EMAIL_VERIFICATION = _settings.get("auth.registration.email_verification", "optional") SOCIALACCOUNT_EMAIL_VERIFICATION = False # Email subject prefix for verification mails @@ -339,26 +356,49 @@ ACCOUNT_SIGNUP_EMAIL_ENTER_TWICE = True # Enforce uniqueness of email addresses ACCOUNT_UNIQUE_EMAIL = _settings.get("auth.login.registration.unique_email", True) +# Configuration for django-invitations + +# Use custom account adapter +ACCOUNT_ADAPTER = "invitations.models.InvitationsAdapter" +# Expire invitations are configured amout of days +INVITATIONS_INVITATION_EXPIRY = _settings.get("auth.invitation.expiry", 3) +# Use email prefix configured for django-allauth +INVITATIONS_EMAIL_SUBJECT_PREFIX = ACCOUNT_EMAIL_SUBJECT_PREFIX +# Use custom invitation model +INVITATIONS_INVITATION_MODEL = "core.PersonInvitation" +# Display error message if invitation code is invalid +INVITATIONS_GONE_ON_ACCEPT_ERROR = False +# Mark invitation as accepted after signup +INVITATIONS_ACCEPT_INVITE_AFTER_SIGNUP = True + # Configuration for OAuth2 provider -OAUTH2_PROVIDER = {"SCOPES_BACKEND_CLASS": "aleksis.core.util.auth_helpers.AppScopes"} +OAUTH2_PROVIDER = { + "SCOPES_BACKEND_CLASS": "aleksis.core.util.auth_helpers.AppScopes", + "OAUTH2_VALIDATOR_CLASS": "aleksis.core.util.auth_helpers.CustomOAuth2Validator", + "OIDC_ENABLED": True, +} OAUTH2_PROVIDER_APPLICATION_MODEL = "core.OAuthApplication" OAUTH2_PROVIDER_GRANT_MODEL = "core.OAuthGrant" OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL = "core.OAuthAccessToken" # noqa: S105 OAUTH2_PROVIDER_ID_TOKEN_MODEL = "core.OAuthIDToken" # noqa: S105 OAUTH2_PROVIDER_REFRESH_TOKEN_MODEL = "core.OAuthRefreshToken" # noqa: S105 -if _settings.get("oauth2.oidc.enabled", False): - with open(_settings.get("oauth2.oidc.rsa_key", "/etc/aleksis/oidc.pem"), "r") as f: - oid_rsa_key = f.read() - - OAUTH2_PROVIDER.update( - { - "OAUTH2_VALIDATOR_CLASS": "aleksis.core.util.auth_helpers.CustomOAuth2Validator", - "OIDC_ENABLED": True, - "OIDC_RSA_PRIVATE_KEY": oid_rsa_key, - # "OIDC_ISS_ENDPOINT": _settings.get("oauth2.oidc.issuer_name", "example.com"), - } +_OIDC_RSA_KEY_DEFAULT = "/etc/aleksis/oidc.pem" +_OIDC_RSA_KEY = _settings.get("oauth2.oidc.rsa_key", "/etc/aleksis/oidc.pem") +if "BEGIN RSA PRIVATE KEY" in _OIDC_RSA_KEY: + OAUTH2_PROVIDER["OIDC_RSA_PRIVATE_KEY"] = _OIDC_RSA_KEY +elif _OIDC_RSA_KEY == _OIDC_RSA_KEY_DEFAULT and not os.path.exists(_OIDC_RSA_KEY): + warnings.warn( + ( + f"The default OIDC RSA key in {_OIDC_RSA_KEY} does not exist. " + f"RSA will be disabled for now, but creating and configuring a " + f"key is recommended. To silence this warning, set oauth2.oidc.rsa_key " + f"to the empty string in a configuration file." + ) ) +elif _OIDC_RSA_KEY: + with open(_OIDC_RSA_KEY, "r") as f: + OAUTH2_PROVIDER["OIDC_RSA_PRIVATE_KEY"] = f.read() # Configuration for REST framework REST_FRAMEWORK = { @@ -379,6 +419,10 @@ if _settings.get("ldap.uri", None): PosixGroupType, ) + AUTH_LDAP_GLOBAL_OPTIONS = { + ldap.OPT_NETWORK_TIMEOUT: _settings.get("ldap.network_timeout", 3), + } + # Enable Django's integration to LDAP AUTHENTICATION_BACKENDS.append("aleksis.core.util.ldap.LDAPBackend") @@ -389,7 +433,7 @@ if _settings.get("ldap.uri", None): AUTH_LDAP_BIND_DN = _settings.get("ldap.bind.dn") AUTH_LDAP_BIND_PASSWORD = _settings.get("ldap.bind.password") - # Keep local password for users to be required to proveide their old password on change + # Keep local password for users to be required to provide their old password on change AUTH_LDAP_SET_USABLE_PASSWORD = _settings.get("ldap.handle_passwords", True) # Keep bound as the authenticating user @@ -463,7 +507,7 @@ if _settings.get("ldap.uri", None): "is_superuser" ] -# Add ModelBckend last so all other backends get a chance +# Add ModelBackend last so all other backends get a chance # to verify passwords first AUTHENTICATION_BACKENDS.append("django.contrib.auth.backends.ModelBackend") @@ -498,6 +542,7 @@ MEDIA_ROOT = _settings.get("media.root", os.path.join(BASE_DIR, "media")) NODE_MODULES_ROOT = _settings.get("node_modules.root", os.path.join(BASE_DIR, "node_modules")) YARN_INSTALLED_APPS = [ + "cleave.js", "@fontsource/roboto", "jquery", "@materializecss/materialize", @@ -539,10 +584,13 @@ ANY_JS = { "Roboto700": {"css_url": JS_URL + "/@fontsource/roboto/700.css"}, "Roboto900": {"css_url": JS_URL + "/@fontsource/roboto/900.css"}, "Sentry": {"js_url": JS_URL + "/@sentry/tracing/build/bundle.tracing.js"}, + "cleavejs": {"js_url": "cleave.js/dist/cleave.min.js"}, } merge_app_settings("ANY_JS", ANY_JS, True) +CLEAVE_JS = ANY_JS["cleavejs"]["js_url"] + SASS_PROCESSOR_ENABLED = True SASS_PROCESSOR_AUTO_INCLUDE = False SASS_PROCESSOR_CUSTOM_FUNCTIONS = { @@ -658,7 +706,7 @@ if _settings.get("dev.uwsgi.celery", DEBUG): DEFAULT_FAVICON_PATHS = { "pwa_icon": os.path.join(STATIC_ROOT, "img/aleksis-icon.png"), - "favicon": os.path.join(STATIC_ROOT, "img/aleksis-icon.png"), + "favicon": os.path.join(STATIC_ROOT, "img/aleksis-favicon.png"), } PWA_ICONS_CONFIG = { "android": [192, 512], @@ -857,10 +905,16 @@ PROMETHEUS_METRICS_EXPORT_ADDRESS = _settings.get("prometheus.metrucs.address", SECURE_PROXY_SSL_HEADER = ("REQUEST_SCHEME", "https") +FILE_UPLOAD_HANDLERS = [ + "django.core.files.uploadhandler.MemoryFileUploadHandler", + "django.core.files.uploadhandler.TemporaryFileUploadHandler", +] + if _settings.get("storage.type", "").lower() == "s3": INSTALLED_APPS.append("storages") DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" + FILE_UPLOAD_HANDLERS.remove("django.core.files.uploadhandler.MemoryFileUploadHandler") if _settings.get("storage.s3.static.enabled", False): STATICFILES_STORAGE = "storages.backends.s3boto3.S3StaticStorage" @@ -930,5 +984,13 @@ THUMBNAIL_PROCESSORS = ( IMAGE_CROPPING_JQUERY_URL = None +SHELL_PLUS_MODEL_IMPORTS_RESOLVER = "django_extensions.collision_resolvers.AppLabelPrefixCR" +SHELL_PLUS_APP_PREFIXES = { + "auth": "auth", +} +SHELL_PLUS_DONT_LOAD = [] +merge_app_settings("SHELL_PLUS_APP_PREFIXES", SHELL_PLUS_APP_PREFIXES) +merge_app_settings("SHELL_PLUS_DONT_LOAD", SHELL_PLUS_DONT_LOAD) + # Add django-cleanup after all apps to ensure that it gets all signals as last app INSTALLED_APPS.append("django_cleanup.apps.CleanupConfig") diff --git a/aleksis/core/static/icons/android_192.png b/aleksis/core/static/icons/android_192.png deleted file mode 100644 index b5f7fec68184883830f68dabc606f7a95c45e8bb..0000000000000000000000000000000000000000 Binary files a/aleksis/core/static/icons/android_192.png and /dev/null differ diff --git a/aleksis/core/static/icons/android_512.png b/aleksis/core/static/icons/android_512.png deleted file mode 100644 index 5e042b4f98ef6dd8056ce643ad16ba085658684e..0000000000000000000000000000000000000000 Binary files a/aleksis/core/static/icons/android_512.png and /dev/null differ diff --git a/aleksis/core/static/icons/apple_114.png b/aleksis/core/static/icons/apple_114.png deleted file mode 100644 index eb8db13ad567105a819dab802b4f7ddd360e34be..0000000000000000000000000000000000000000 Binary files a/aleksis/core/static/icons/apple_114.png and /dev/null differ diff --git a/aleksis/core/static/icons/apple_152.png b/aleksis/core/static/icons/apple_152.png deleted file mode 100644 index 51eaa8d28988a16629e2b884d8de4df58fbadccc..0000000000000000000000000000000000000000 Binary files a/aleksis/core/static/icons/apple_152.png and /dev/null differ diff --git a/aleksis/core/static/icons/apple_180.png b/aleksis/core/static/icons/apple_180.png deleted file mode 100644 index 5c6b70846586ef0bf4bd44d177f6f79b49d1cddd..0000000000000000000000000000000000000000 Binary files a/aleksis/core/static/icons/apple_180.png and /dev/null differ diff --git a/aleksis/core/static/icons/apple_76.png b/aleksis/core/static/icons/apple_76.png deleted file mode 100644 index 3751b84654d01943148fc6f1b90125a4195d4af9..0000000000000000000000000000000000000000 Binary files a/aleksis/core/static/icons/apple_76.png and /dev/null differ diff --git a/aleksis/core/static/icons/favicon_16.png b/aleksis/core/static/icons/favicon_16.png deleted file mode 100644 index f1d02a7a8a34825726d20eeb1f6a63922d1a848e..0000000000000000000000000000000000000000 Binary files a/aleksis/core/static/icons/favicon_16.png and /dev/null differ diff --git a/aleksis/core/static/icons/favicon_32.png b/aleksis/core/static/icons/favicon_32.png deleted file mode 100644 index edc72d4556cce0fde923a0ac3db4d0f94bb74412..0000000000000000000000000000000000000000 Binary files a/aleksis/core/static/icons/favicon_32.png and /dev/null differ diff --git a/aleksis/core/static/icons/favicon_48.png b/aleksis/core/static/img/aleksis-favicon.png similarity index 100% rename from aleksis/core/static/icons/favicon_48.png rename to aleksis/core/static/img/aleksis-favicon.png diff --git a/aleksis/core/static/js/main.js b/aleksis/core/static/js/main.js index 1d2a2fe28e3c4304e72d8abfc398f0fda3908586..119103b5ea3885f290410a42758a5f672caffdc4 100644 --- a/aleksis/core/static/js/main.js +++ b/aleksis/core/static/js/main.js @@ -19,7 +19,8 @@ function initDatePicker(sel) { // Set monday as first day of week firstDay: get_format('FIRST_DAY_OF_WEEK'), - autoClose: true + autoClose: true, + yearRange: [new Date().getFullYear() - 100, new Date().getFullYear() + 100], }); el.datepicker("setDate", $(sel).val()); return el; diff --git a/aleksis/core/static/js/progress.js b/aleksis/core/static/js/progress.js index 9be718b7e67f30e8cc77a436755e50f08b540fd3..0b2509006029421273159617c9ff2646bb12800b 100644 --- a/aleksis/core/static/js/progress.js +++ b/aleksis/core/static/js/progress.js @@ -47,6 +47,7 @@ function customSuccess(progressBarElement, progressBarMessageElement) { $("#result-icon").text("check_circle"); $("#result-text").text(OPTIONS.success); $("#result-box").show(); + $("#result-button").show(); const redirect = "redirect_on_success" in OPTIONS && OPTIONS.redirect_on_success; if (redirect) { window.location.replace(OPTIONS.redirect_on_success); diff --git a/aleksis/core/static/public/style.scss b/aleksis/core/static/public/style.scss index bef226c7d4a8583cb2e925453c9a4a27293cd3f5..4fb6d9b2815555082d18cfd7ef18025704010035 100644 --- a/aleksis/core/static/public/style.scss +++ b/aleksis/core/static/public/style.scss @@ -64,6 +64,10 @@ header, main, footer { margin-left: 300px; } +.without-menu header, .without-menu main, .without-menu footer { + margin-left: 0; +} + @media only screen and (max-width: 992px) { header, main, footer { margin-left: 0; @@ -377,6 +381,12 @@ span.badge .material-icons { margin-left: -2px; } +.chip { + padding: 8px 12px; + height: auto; + line-height: 16px; +} + /*+++++++++*/ /* Buttons */ /*+++++++++*/ @@ -794,3 +804,15 @@ main figure.alert { height: 24px; margin-bottom: 8px; } + +.application-circle { + border-radius: 50%; + width: 20vh; + height: 20vh; +} + + +.application-circle img { + @extend .application-circle; + object-fit: cover; +} diff --git a/aleksis/core/tables.py b/aleksis/core/tables.py index 8f0e0b93bf3b79b96a50a2566b450fda05426bc9..ab19c80608f1a8966dab7ae2094eca7caf579252 100644 --- a/aleksis/core/tables.py +++ b/aleksis/core/tables.py @@ -1,14 +1,19 @@ +from textwrap import wrap + from django.utils.translation import gettext_lazy as _ import django_tables2 as tables from django_tables2.utils import A +from .models import Person +from .util.core_helpers import get_site_preferences + class SchoolTermTable(tables.Table): """Table to list persons.""" class Meta: - attrs = {"class": "responsive-table highlight"} + attrs = {"class": "highlight"} name = tables.LinkColumn("edit_school_term", args=[A("id")]) date_start = tables.Column() @@ -26,7 +31,7 @@ class PersonsTable(tables.Table): """Table to list persons.""" class Meta: - attrs = {"class": "responsive-table highlight"} + attrs = {"class": "highlight"} first_name = tables.LinkColumn("person_by_id", args=[A("id")]) last_name = tables.LinkColumn("person_by_id", args=[A("id")]) @@ -36,7 +41,7 @@ class GroupsTable(tables.Table): """Table to list groups.""" class Meta: - attrs = {"class": "responsive-table highlight"} + attrs = {"class": "highlight"} name = tables.LinkColumn("group_by_id", args=[A("id")]) short_name = tables.LinkColumn("group_by_id", args=[A("id")]) @@ -47,7 +52,7 @@ class AdditionalFieldsTable(tables.Table): """Table to list group types.""" class Meta: - attrs = {"class": "responsive-table hightlight"} + attrs = {"class": "hightlight"} title = tables.LinkColumn("edit_additional_field_by_id", args=[A("id")]) delete = tables.LinkColumn( @@ -63,7 +68,7 @@ class GroupTypesTable(tables.Table): """Table to list group types.""" class Meta: - attrs = {"class": "responsive-table highlight"} + attrs = {"class": "highlight"} name = tables.LinkColumn("edit_group_type_by_id", args=[A("id")]) description = tables.LinkColumn("edit_group_type_by_id", args=[A("id")]) @@ -76,7 +81,7 @@ class DashboardWidgetTable(tables.Table): """Table to list dashboard widgets.""" class Meta: - attrs = {"class": "responsive-table highlight"} + attrs = {"class": "highlight"} widget_name = tables.Column(accessor="pk") title = tables.LinkColumn("edit_dashboard_widget", args=[A("id")]) @@ -93,6 +98,33 @@ class DashboardWidgetTable(tables.Table): return record._meta.verbose_name +class PersonColumn(tables.Column): + """Returns person object from given id.""" + + def render(self, value): + return Person.objects.get(user__id=value) + + +class InvitationCodeColumn(tables.Column): + """Returns invitation code in a more readable format.""" + + def render(self, value): + packet_size = get_site_preferences()["auth__invite_code_packet_size"] + return "-".join(wrap(value, packet_size)) + + +class InvitationsTable(tables.Table): + """Table to list persons.""" + + email = tables.EmailColumn() + sent = tables.DateColumn() + inviter_id = PersonColumn() + key = InvitationCodeColumn() + accepted = tables.BooleanColumn( + yesno="check,cancel", attrs={"span": {"class": "material-icons"}} + ) + + class PermissionDeleteColumn(tables.LinkColumn): """Link column with label 'Delete'.""" diff --git a/aleksis/core/templates/404.html b/aleksis/core/templates/404.html index 33c311fcaf4c106d44c53788b44426584d014c33..cf68c12bf63624ecf40107ee6f3994b288548c3c 100644 --- a/aleksis/core/templates/404.html +++ b/aleksis/core/templates/404.html @@ -7,8 +7,7 @@ <div class="card red"> <div class="card-content white-text"> <i class="material-icons small left">error_outline</i> - <span class="card-title">{% trans "Error" %} (404): {% blocktrans %}The requested page or object was not - found.{% endblocktrans %}</span> + <span class="card-title">{{ exception }}</span> <p> {% blocktrans %} If you were redirected by a link on an external page, diff --git a/aleksis/core/templates/account/account_inactive.html b/aleksis/core/templates/account/account_inactive.html index 62b03a3db859699aabb816ef1d05455777965bd9..5c328abcfbca48c6499f71b4b11fac5f1f91ccad 100644 --- a/aleksis/core/templates/account/account_inactive.html +++ b/aleksis/core/templates/account/account_inactive.html @@ -9,8 +9,10 @@ <div class="container"> <div class="card red"> <div class="card-content white-text"> - <div class="material-icons small left">error_outline</div> - <span class="card-title">{% blocktrans %}Account inactive.{% endblocktrans %}</span> + <div class="card-title"> + <i class="material-icons small left">error_outline</i> + {% blocktrans %}Account inactive.{% endblocktrans %} + </div> <p> {% blocktrans %} This account is currently inactive. If you think this is an diff --git a/aleksis/core/templates/account/signup_closed.html b/aleksis/core/templates/account/signup_closed.html index 33ef749f5598fbd209e3f72dc2b4a79620f17b1a..0d5cbd51095e9c24fceacbc4ba8f6a510a5705a9 100644 --- a/aleksis/core/templates/account/signup_closed.html +++ b/aleksis/core/templates/account/signup_closed.html @@ -9,8 +9,10 @@ <div class="container"> <div class="card red"> <div class="card-content white-text"> - <div class="material-icons small left">error_outline</div> - <span class="card-title">{% blocktrans %}Signup closed.{% endblocktrans %}</span> + <div class="card-title"> + <i class="material-icons small left">error_outline</i> + {% blocktrans %}Signup closed.{% endblocktrans %} + </div> <p> {% blocktrans %} This sign up is currently closed. If you think this is an diff --git a/aleksis/core/templates/account/verification_sent.html b/aleksis/core/templates/account/verification_sent.html index dd486aeb2bf212838a014fe868db4cfe6716cf8d..df3ae47c82911a01997ac9f4d7919c9e1b95a36e 100644 --- a/aleksis/core/templates/account/verification_sent.html +++ b/aleksis/core/templates/account/verification_sent.html @@ -25,10 +25,6 @@ contact us if you do not receive it within a few minutes. {% endblocktrans %} </p> - <p> - {% url 'account_email' as email_url %} - {% blocktrans with email_url=email_url %}<strong>Note:</strong> you can still <a href="{{ email_url }}">change your e-mail address</a>{% endblocktrans %} - </p> {% include "core/partials/admins_list.html" %} </div> </div> diff --git a/aleksis/core/templates/core/base.html b/aleksis/core/templates/core/base.html index 6c47c2a3bd0da7ba02e4c8aa96e7a5787cd933c0..7fd4e38f8449b0a649fcd01e08051a2332070a15 100644 --- a/aleksis/core/templates/core/base.html +++ b/aleksis/core/templates/core/base.html @@ -58,7 +58,7 @@ {% block extra_head %}{% endblock %} </head> -<body> +<body {% if no_menu %}class="without-menu"{% endif %}> <header> <!-- Menu button (sidenav) --> @@ -88,32 +88,36 @@ </nav> <!-- Main nav (sidenav) --> - <ul id="slide-out" class="sidenav sidenav-fixed"> - <li class="logo"> - {% static "img/aleksis-banner.svg" as aleksis_banner %} - <a id="logo-container" href="/" class="brand-logo"> - <img src="{% firstof request.site.preferences.theme__logo.url aleksis_banner %}" - alt="{{ request.site.preferences.general__title }} – Logo"> - </a> - </li> - {% has_perm 'core.search_rule' user as search %} - {% if search %} - <li class="search"> - <form method="get" action="{% url "haystack_search" %}" id="search-form" class="autocomplete"> - <div class="search-wrapper"> - <input id="search" name="q" type="search" enterkeyhint="search" placeholder="{% trans "Search" %}"> - <button class="btn btn-flat search-button" type="submit" aria-label="{% trans "Search" %}"> - <i class="material-icons">search</i> - </button> - <div class="progress" id="search-loader"><div class="indeterminate"></div></div> - </div> - </form> + {% if not no_menu %} + <ul id="slide-out" class="sidenav sidenav-fixed"> + <li class="logo"> + {% static "img/aleksis-banner.svg" as aleksis_banner %} + <a id="logo-container" href="/" class="brand-logo"> + <img src="{% firstof request.site.preferences.theme__logo.url aleksis_banner %}" + alt="{{ request.site.preferences.general__title }} – Logo"> + </a> </li> - {% endif %} - <li class="no-padding"> - {% include "core/partials/sidenav.html" %} - </li> - </ul> + {% has_perm 'core.search_rule' user as search %} + {% if search %} + <li class="search"> + <form method="get" action="{% url "haystack_search" %}" id="search-form" class="autocomplete"> + <div class="search-wrapper"> + <input id="search" name="q" type="search" enterkeyhint="search" placeholder="{% trans "Search" %}"> + <button class="btn btn-flat search-button" type="submit" aria-label="{% trans "Search" %}"> + <i class="material-icons">search</i> + </button> + <div class="progress" id="search-loader"> + <div class="indeterminate"></div> + </div> + </div> + </form> + </li> + {% endif %} + <li class="no-padding"> + {% include "core/partials/sidenav.html" %} + </li> + </ul> + {% endif %} </header> @@ -180,7 +184,7 @@ <span id="doit"></span> {% if request.site.preferences.footer__imprint_url %} <a class="blue-text text-lighten-4" href="{{ request.site.preferences.footer__imprint_url }}"> - {% trans "Impress" %} + {% trans "Imprint" %} </a> {% endif %} {% if request.site.preferences.footer__privacy_url and request.site.preferences.footer__imprint_url %} diff --git a/aleksis/core/templates/core/data_check/list.html b/aleksis/core/templates/core/data_check/list.html index 5a510fdd92f550ad1b7ff6b0b81983ea225420ba..36d83d4cd7d3c917db98c104586bd2aa9c82c139 100644 --- a/aleksis/core/templates/core/data_check/list.html +++ b/aleksis/core/templates/core/data_check/list.html @@ -50,27 +50,29 @@ </thead> <tbody> {% for result in results %} - <tr> - <td> - <code>{{ result.id }}</code> - </td> - <td>{% verbose_name_object result.related_object %}</td> - <td>{{ result.related_object }}</td> - <td>{{ result.related_check.problem_name }}</td> - <td> - <a class="btn-flat waves-effect waves-light" href="{{ result.related_object.get_absolute_url }}"> - {% trans "Show object" %} - </a> - </td> - <td> - {% for option_name, option in result.related_check.solve_options.items %} - <a class="btn btn-margin waves-effect waves-light" - href="{% url "data_check_solve" result.pk option_name %}"> - {{ option.verbose_name }} + {% if result.related_object %} + <tr> + <td> + <code>{{ result.id }}</code> + </td> + <td>{% verbose_name_object result.related_object %}</td> + <td>{{ result.related_object }}</td> + <td>{{ result.related_check.problem_name }}</td> + <td> + <a class="btn-flat waves-effect waves-light" href="{{ result.related_object.get_absolute_url }}"> + {% trans "Show object" %} </a> - {% endfor %} - </td> - </tr> + </td> + <td> + {% for option_name, option in result.related_check.solve_options.items %} + <a class="btn btn-margin waves-effect waves-light" + href="{% url "data_check_solve" result.pk option_name %}"> + {{ option.verbose_name }} + </a> + {% endfor %} + </td> + </tr> + {% endif %} {% endfor %} </tbody> </table> diff --git a/aleksis/core/templates/core/pages/progress.html b/aleksis/core/templates/core/pages/progress.html index 799f1f93648ab1de05be3f9432653b8c4e8b1466..fca1ddfc2ebe5980ee132de77bdf1baafce24ae0 100644 --- a/aleksis/core/templates/core/pages/progress.html +++ b/aleksis/core/templates/core/pages/progress.html @@ -47,7 +47,7 @@ {% trans "Go back" %} </a> {% if additional_button %} - <a class="btn waves-effect waves-light" href="{{ additional_button.href }}"> + <a class="btn waves-effect waves-light" href="{{ additional_button.href }}" id="result-button" style="display: none;"> <i class="material-icons left">{{ additional_button.icon|default:"" }}</i> {{ additional_button.caption }} </a> diff --git a/aleksis/core/templates/core/person/full.html b/aleksis/core/templates/core/person/full.html index d16354f00ebcd2162ffc7bab16715707b41adb81..4a2e68a09517d1888f708b8ece3f757c6b1d8b1f 100644 --- a/aleksis/core/templates/core/person/full.html +++ b/aleksis/core/templates/core/person/full.html @@ -14,6 +14,7 @@ {% has_perm 'core.change_person_preferences_rule' user person as can_change_person_preferences %} {% has_perm 'core.delete_person_rule' user person as can_delete_person %} {% has_perm "core.impersonate_rule" user person as can_impersonate %} + {% has_perm "core.can_invite" user person as can_invite %} {% if can_change_person or can_change_person_preferences or can_delete_person or can_impersonate %} <p> @@ -43,7 +44,13 @@ <i class="material-icons left">portrait</i> {% trans "Impersonate" %} </a> - {% endif %} + {% endif %} + {% if can_invite and not person.user %} + <a href="{% url "invite_person_by_id" person.id %}" class="btn waves-effect waves-light"> + <i class="material-icons left">card_giftcard</i> + {% trans "Invite user" %} + </a> + {% endif %} </p> {% endif %} diff --git a/aleksis/core/templates/dynamic_preferences/form.html b/aleksis/core/templates/dynamic_preferences/form.html index 692d25e90b3dd5cb6554fe23010f5cbc542c3c94..22f036912c6493ac3f9a17815f1c46c6bdb413fe 100644 --- a/aleksis/core/templates/dynamic_preferences/form.html +++ b/aleksis/core/templates/dynamic_preferences/form.html @@ -10,7 +10,7 @@ {% elif registry_name == "person" and instance == request.user.person %} {% blocktrans %}My preferences{% endblocktrans %} {% else %} - {% blocktrans with instace=instance %}Preferences for {{ instance }}{% endblocktrans %} + {% blocktrans with instance=instance %}Preferences for {{ instance }}{% endblocktrans %} {% endif %} {% endblock %} diff --git a/aleksis/core/templates/impersonate/list_users.html b/aleksis/core/templates/impersonate/list_users.html deleted file mode 100644 index fd273ca60902e5defbc41e567a9205cfe99fb349..0000000000000000000000000000000000000000 --- a/aleksis/core/templates/impersonate/list_users.html +++ /dev/null @@ -1,28 +0,0 @@ -{# -*- engine:django -*- #} -{# Derived from the original template in django-impersonate #} - -{% extends "core/base.html" %} -{% load i18n %} - -{% block browser_title %}{% trans "Impersonate" %}{% endblock %} -{% block page_title %}{% trans "Impersonate" %}{% endblock %} - -{% block content %} - {% if page.object_list %} - <div class="collection"> - {% for user in page.object_list %} - <a class="collection-item" href="{% url 'impersonate-start' user.pk %}{{ redirect }}"> - {{ user }} - </a> - {% endfor %} - </div> - {% endif %} - - {% if page.has_previous %} - <a href="{% url 'impersonate-list' %}?page={{ page.previous_page_number }}">Previous Page</a> - {% endif %} - - {% if page.has_next %} - <a href="{% url 'impersonate-list' %}?page={{ page.next_page_number }}">Next Page</a> - {% endif %} -{% endblock %} diff --git a/aleksis/core/templates/invitations/enter.html b/aleksis/core/templates/invitations/enter.html new file mode 100644 index 0000000000000000000000000000000000000000..03605a710697334567384a74a289783b64a7f55e --- /dev/null +++ b/aleksis/core/templates/invitations/enter.html @@ -0,0 +1,44 @@ +{# -*- engine:django -*- #} + +{% extends "core/base.html" %} + +{% load material_form i18n %} + +{% block browser_title %}{% blocktrans %}Accept invitation{% endblocktrans %}{% endblock %} +{% block no_page_title %}{% endblock %} + +{% block extra_head %} + {{ form.media.css }} +{% endblock %} + +{% block content %} + <div class="row"> + <div class="col m1 l2 xl3"></div> + <div class="col s12 m10 l8 xl6"> + <div class="card"> + <form method="post"> + <div class="card-content"> + <div class="card-title">{% trans "Accept your invitation" %}</div> + <div class="alert primary"> + <div> + <i class="material-icons left">info</i> + {% blocktrans %} + Please enter your invitation code to register + your new user account: + {% endblocktrans %} + </div> + </div> + {% csrf_token %} + {% form form=form %}{% endform %} + </div> + <div class="card-action-light"> + <button type="submit" class="btn green waves-effect waves-light"> + <i class="material-icons left">card_giftcard</i> + {% trans "Accept invite" %} + </button> + </div> + </form> + </div> + </div> + {{ form.media.js }} +{% endblock %} diff --git a/aleksis/core/templates/invitations/forms/_invite.html b/aleksis/core/templates/invitations/forms/_invite.html new file mode 100644 index 0000000000000000000000000000000000000000..297997e0b04f3d99a1e1279c8900d0bcc9c50024 --- /dev/null +++ b/aleksis/core/templates/invitations/forms/_invite.html @@ -0,0 +1,38 @@ +{# -*- engine:django -*- #} + +{% extends "core/base.html" %} + +{% load material_form i18n %} + +{% load render_table from django_tables2 %} + +{% block browser_title %}{% blocktrans %}Invite{% endblocktrans %}{% endblock %} +{% block page_title %}{% blocktrans %}Invite{% endblocktrans %}{% endblock %} + + +{% block content %} + + <div class="row"> + <div class="col s6"> + <h5>{% trans "Invite by email address" %}</h5> + <form method="post"> + {% csrf_token %} + {% form form=form %}{% endform %} + {% trans "Invite" as caption %} + {% include "core/partials/save_button.html" with caption=caption icon="card_giftcard" %} + </form> + </div> + <div class="col s6"> + <h5>{% trans "Generate invitation code" %}</h5> + + <a class="btn waves-effect waves-light hundred-percent" href="{% url 'generate_invitation_code' %}"> + {% trans "Generate code" %} + </a> + </div> + <div class="col s12"> + <h5>{% trans "Invitations" %}</h5> + + {% render_table table %} + </div> + </div> +{% endblock %} diff --git a/aleksis/core/templates/invitations/messages/invite_accepted.txt b/aleksis/core/templates/invitations/messages/invite_accepted.txt new file mode 100644 index 0000000000000000000000000000000000000000..59699adee30108f241eb6dd4db1478f75399292d --- /dev/null +++ b/aleksis/core/templates/invitations/messages/invite_accepted.txt @@ -0,0 +1,3 @@ +{% load i18n %} + +{% blocktrans %}The invitation for {{ email }} has been accepted.{% endblocktrans %} diff --git a/aleksis/core/templates/oauth2_provider/application/create.html b/aleksis/core/templates/oauth2_provider/application/create.html index d81489e922a76de8d7a8e92a7f48686714a3b3a7..73b94677206d38fca163858551536d575b2dce3d 100644 --- a/aleksis/core/templates/oauth2_provider/application/create.html +++ b/aleksis/core/templates/oauth2_provider/application/create.html @@ -6,7 +6,7 @@ {% block page_title %}{% blocktrans %}Register OAuth2 Application{% endblocktrans %}{% endblock %} {% block content %} - <form method="post"> + <form method="post" enctype="multipart/form-data"> {% csrf_token %} {% form form=form %}{% endform %} {% include "core/partials/save_button.html" %} diff --git a/aleksis/core/templates/oauth2_provider/application/detail.html b/aleksis/core/templates/oauth2_provider/application/detail.html index da6b8abf81ddc1916de7b0c7feb5a7262f453037..28e2af7d70ff4b6dd5d93b46b8ec52d31bc36538 100644 --- a/aleksis/core/templates/oauth2_provider/application/detail.html +++ b/aleksis/core/templates/oauth2_provider/application/detail.html @@ -22,6 +22,18 @@ </a> <table class="responsive-table"> <tbody> + <tr> + <th>{% trans "Icon" %}</th> + <td> + {% if application.icon %} + <div class="application-circle materialboxed z-depth-2"> + <img src="{{ application.icon.url }}" alt="{{ oauth_application.name }}" class="hundred-percent"> + </div> + {% else %} + – + {% endif %} + </td> + </tr> <tr> <th> {% trans "Client id" %} diff --git a/aleksis/core/templates/oauth2_provider/application/edit.html b/aleksis/core/templates/oauth2_provider/application/edit.html index 6755d2420fb6a181f671b825475afb4ec9581521..30f50fff94e330e941d7b4730fe7d875b039d74e 100644 --- a/aleksis/core/templates/oauth2_provider/application/edit.html +++ b/aleksis/core/templates/oauth2_provider/application/edit.html @@ -6,7 +6,7 @@ {% block page_title %}{% blocktrans %}Edit OAuth2 Application{% endblocktrans %}{% endblock %} {% block content %} - <form method="post"> + <form method="post" enctype="multipart/form-data"> {% csrf_token %} {% form form=form %}{% endform %} {% include "core/partials/save_button.html" %} diff --git a/aleksis/core/templates/oauth2_provider/application/list.html b/aleksis/core/templates/oauth2_provider/application/list.html index 06f1a95c4e05c14dcb5efe69f2416040d184f0bb..ced7d718dfe1b561c2ea8253e25658a9f449024d 100644 --- a/aleksis/core/templates/oauth2_provider/application/list.html +++ b/aleksis/core/templates/oauth2_provider/application/list.html @@ -12,8 +12,13 @@ </a> <div class="collection"> {% for application in applications %} - <a class="collection-item" href="{% url "oauth2_application" application.id %}"> - {{ application.name }} + <a class="collection-item avatar" href="{% url "oauth2_application" application.id %}"> + {% if application.icon %} + <img src="{{ application.icon.url }}" alt="{{ application.name }}" class="circle"> + {% endif %} + <span class="title"> + {{ application.name }} + </span> </a> {% empty %} <div class="collection-item flow-text"> diff --git a/aleksis/core/templates/oauth2_provider/authorize.html b/aleksis/core/templates/oauth2_provider/authorize.html index 48b996837b8721ef6ba74337d286236e91729f5b..c90d5e8dd9d3d72cff9e19ce167487900e904636 100644 --- a/aleksis/core/templates/oauth2_provider/authorize.html +++ b/aleksis/core/templates/oauth2_provider/authorize.html @@ -12,8 +12,15 @@ <div class="col s12 m10 l8 xl6"> <div class="card"> <div class="card-content"> - <div class="card-title"> - {% trans "Authorize" %} {{ application.name }} + {% if application.icon %} + <div class="center-via-flex margin-bottom"> + <div class="application-circle materialboxed z-depth-2"> + <img src="{{ application.icon.url }}" alt="{{ application.name }}" class="hundred-percent"> + </div> + </div> + {% endif %} + <div class="card-title {% if application.icon %}center{% endif %}"> + {% blocktrans with name=application.name %}Authorize {{ name }}{% endblocktrans %} </div> <p class="margin-bottom">{% trans "The application requests access to the following scopes:" %}</p> {% for scope in scopes_descriptions %} diff --git a/aleksis/core/templates/socialaccount/login.html b/aleksis/core/templates/socialaccount/login.html new file mode 100644 index 0000000000000000000000000000000000000000..1630b01fa4104f563a92663bc7fd386a2abd5266 --- /dev/null +++ b/aleksis/core/templates/socialaccount/login.html @@ -0,0 +1,33 @@ +{% extends "core/base.html" %} + +{% load i18n material_form account %} + +{% block browser_title %}{% trans "Authorize" %}{% endblock %} +{% block page_title %}{% trans "Authorize" %}{% endblock %} + +{% block content %} +{% if process == "connect" %} + <p class="flow-text"> + <i class="material-icons left">info</i> + {% blocktrans with provider.name as provider %}You are about to connect a new third party account from {{ provider }}.{% endblocktrans %} + </p> + <form method="post"> + {% csrf_token %} + {% form form=form %}{% endform %} + {% trans "Confirm" as caption %} + {% include "core/partials/save_button.html" with caption=caption icon="how_to_reg" %} + </form> +{% else %} + <p class="flow-text"> + <i class="material-icons left small">info</i> + {% blocktrans with provider.name as provider %}You are about to sign in using a third party account from {{ provider }}.{% endblocktrans %} + </p> + <form method="post"> + {% csrf_token %} + {% form form=form %}{% endform %} + {% trans "Continue" as caption %} + {% include "core/partials/save_button.html" with caption=caption icon="how_to_reg" %} + </form> + +{% endif %} +{% endblock %} diff --git a/aleksis/core/templates/two_factor/core/login.html b/aleksis/core/templates/two_factor/core/login.html index 9ea4bc6c24b7d9e764742bbddf75ceb86b785868..834c4b98b543bd994542b105aec1b99932f7d186 100644 --- a/aleksis/core/templates/two_factor/core/login.html +++ b/aleksis/core/templates/two_factor/core/login.html @@ -16,7 +16,17 @@ <div class="col s12 m10 l8 xl6"> <div class="card"> <div class="card-content"> - {% if wizard.steps.current == 'auth' and socialaccount_providers %} + {% if oauth and oauth_application.icon %} + <div class="center-via-flex margin-bottom"> + <div class="application-circle materialboxed z-depth-2"> + <img src="{{ oauth_application.icon.url }}" alt="{{ oauth_application.name }}" + class="hundred-percent"> + </div> + </div> + <div class="card-title center"> + {% blocktrans with name=oauth_application.name %}Login for {{ name }}{% endblocktrans %} + </div> + {% elif wizard.steps.current == 'auth' and socialaccount_providers %} <div class="card-title">{% trans "Login with username and password" %}</div> {% else %} <div class="card-title">{% trans "Login" %}</div> @@ -30,12 +40,21 @@ </p> </div> {% elif wizard.steps.current == 'auth' %} - <div class="alert primary"> - <p> - <i class="material-icons left">info</i> - {% blocktrans %}Please login to see this page.{% endblocktrans %} - </p> - </div> + {% if oauth %} + <div class="alert primary"> + <p> + <i class="material-icons left">info</i> + {% blocktrans %}Please login with your account to use the external application.{% endblocktrans %} + </p> + </div> + {% else %} + <div class="alert primary"> + <p> + <i class="material-icons left">info</i> + {% blocktrans %}Please login to see this page.{% endblocktrans %} + </p> + </div> + {% endif %} {% endif %} {% if not wizard.steps.current == "auth" %} <div class="alert primary"> diff --git a/aleksis/core/tests/models/test_group.py b/aleksis/core/tests/models/test_group.py new file mode 100644 index 0000000000000000000000000000000000000000..8849a842d043b6bd3c91d04393cf5ccc695d2cf3 --- /dev/null +++ b/aleksis/core/tests/models/test_group.py @@ -0,0 +1,163 @@ +import pytest + +from aleksis.core.models import Group, Person + +pytestmark = pytest.mark.django_db + + +def test_child_groups_recursive(): + g_1st_grade = Group.objects.create(name="1st grade") + g_1a = Group.objects.create(name="1a") + g_1b = Group.objects.create(name="1b") + g_2nd_grade = Group.objects.create(name="2nd grade") + g_2a = Group.objects.create(name="2a") + g_2b = Group.objects.create(name="2b") + g_2c = Group.objects.create(name="2c") + g_2nd_grade_french = Group.objects.create(name="2nd grade French") + + g_1a.parent_groups.set([g_1st_grade]) + g_1b.parent_groups.set([g_1st_grade]) + g_2a.parent_groups.set([g_2nd_grade]) + g_2b.parent_groups.set([g_2nd_grade]) + g_2c.parent_groups.set([g_2nd_grade]) + g_2nd_grade_french.parent_groups.set([g_2b, g_2c]) + + assert g_2nd_grade_french in g_2nd_grade.child_groups_recursive + assert g_2nd_grade_french in g_2b.child_groups_recursive + assert g_2nd_grade_french in g_2c.child_groups_recursive + assert g_2nd_grade_french not in g_2a.child_groups_recursive + assert g_2nd_grade_french not in g_1st_grade.child_groups_recursive + + +def test_parent_groups_recursive(): + g_1st_grade = Group.objects.create(name="1st grade") + g_1a = Group.objects.create(name="1a") + g_1b = Group.objects.create(name="1b") + g_2nd_grade = Group.objects.create(name="2nd grade") + g_2a = Group.objects.create(name="2a") + g_2b = Group.objects.create(name="2b") + g_2c = Group.objects.create(name="2c") + g_2nd_grade_french = Group.objects.create(name="2nd grade French") + + g_1a.parent_groups.set([g_1st_grade]) + g_1b.parent_groups.set([g_1st_grade]) + g_2a.parent_groups.set([g_2nd_grade]) + g_2b.parent_groups.set([g_2nd_grade]) + g_2c.parent_groups.set([g_2nd_grade]) + g_2nd_grade_french.parent_groups.set([g_2b, g_2c]) + + assert g_1st_grade in g_1a.parent_groups_recursive + assert g_2nd_grade in g_2a.parent_groups_recursive + assert g_2nd_grade in g_2nd_grade_french.parent_groups_recursive + assert g_1st_grade not in g_2nd_grade_french.parent_groups_recursive + + +def test_members_recursive(): + g_2nd_grade = Group.objects.create(name="2nd grade") + g_2a = Group.objects.create(name="2a") + g_2b = Group.objects.create(name="2b") + g_2c = Group.objects.create(name="2c") + g_2nd_grade_french = Group.objects.create(name="2nd grade French") + + g_2a.parent_groups.set([g_2nd_grade]) + g_2b.parent_groups.set([g_2nd_grade]) + g_2c.parent_groups.set([g_2nd_grade]) + g_2nd_grade_french.parent_groups.set([g_2b, g_2c]) + + p_2a_1 = Person.objects.create(first_name="A", last_name="B") + p_2a_2 = Person.objects.create(first_name="A", last_name="B") + p_2b_1 = Person.objects.create(first_name="A", last_name="B") + p_2b_2 = Person.objects.create(first_name="A", last_name="B") + p_2c_1 = Person.objects.create(first_name="A", last_name="B") + p_2c_2 = Person.objects.create(first_name="A", last_name="B") + p_french_only = Person.objects.create(first_name="A", last_name="B") + + g_2a.members.set([p_2a_1, p_2a_2]) + g_2b.members.set([p_2b_1, p_2b_2]) + g_2c.members.set([p_2c_1, p_2c_2]) + g_2nd_grade_french.members.set([p_2b_1, p_2c_1, p_french_only]) + + assert p_2a_1 in g_2nd_grade.members_recursive + assert p_2a_2 in g_2nd_grade.members_recursive + assert p_2b_1 in g_2nd_grade.members_recursive + assert p_2b_2 in g_2nd_grade.members_recursive + assert p_2c_1 in g_2nd_grade.members_recursive + assert p_2c_2 in g_2nd_grade.members_recursive + assert p_french_only in g_2nd_grade.members_recursive + assert p_french_only in g_2b.members_recursive + assert p_french_only in g_2c.members_recursive + assert p_french_only not in g_2a.members_recursive + + +def test_member_of_recursive(): + g_2nd_grade = Group.objects.create(name="2nd grade") + g_2a = Group.objects.create(name="2a") + g_2b = Group.objects.create(name="2b") + g_2c = Group.objects.create(name="2c") + g_2nd_grade_french = Group.objects.create(name="2nd grade French") + + g_2a.parent_groups.set([g_2nd_grade]) + g_2b.parent_groups.set([g_2nd_grade]) + g_2c.parent_groups.set([g_2nd_grade]) + g_2nd_grade_french.parent_groups.set([g_2b, g_2c]) + + p_2a_1 = Person.objects.create(first_name="A", last_name="B") + p_2a_2 = Person.objects.create(first_name="A", last_name="B") + p_2b_1 = Person.objects.create(first_name="A", last_name="B") + p_2b_2 = Person.objects.create(first_name="A", last_name="B") + p_2c_1 = Person.objects.create(first_name="A", last_name="B") + p_2c_2 = Person.objects.create(first_name="A", last_name="B") + p_french_only = Person.objects.create(first_name="A", last_name="B") + + g_2a.members.set([p_2a_1, p_2a_2]) + g_2b.members.set([p_2b_1, p_2b_2]) + g_2c.members.set([p_2c_1, p_2c_2]) + g_2nd_grade_french.members.set([p_2b_1, p_2c_1, p_french_only]) + + assert g_2nd_grade in p_2a_1.member_of_recursive + assert g_2nd_grade in p_2a_2.member_of_recursive + assert g_2nd_grade in p_2b_1.member_of_recursive + assert g_2nd_grade in p_2b_2.member_of_recursive + assert g_2nd_grade in p_2c_1.member_of_recursive + assert g_2nd_grade in p_2c_2.member_of_recursive + assert g_2nd_grade in p_french_only.member_of_recursive + assert g_2b in p_french_only.member_of_recursive + assert g_2c in p_french_only.member_of_recursive + + +def test_owners_recursive(): + g_2nd_grade = Group.objects.create(name="2nd grade") + g_2a = Group.objects.create(name="2a") + g_2b = Group.objects.create(name="2b") + + g_2a.parent_groups.set([g_2nd_grade]) + g_2b.parent_groups.set([g_2nd_grade]) + + p_1 = Person.objects.create(first_name="A", last_name="B") + p_2 = Person.objects.create(first_name="A", last_name="B") + + g_2nd_grade.owners.set([p_1]) + + assert p_1 in g_2a.owners_recursive + assert p_1 in g_2b.owners_recursive + assert p_2 not in g_2a.owners_recursive + assert p_2 not in g_2b.owners_recursive + + +def test_owner_of_recursive(): + g_2nd_grade = Group.objects.create(name="2nd grade") + g_2a = Group.objects.create(name="2a") + g_2b = Group.objects.create(name="2b") + + g_2a.parent_groups.set([g_2nd_grade]) + g_2b.parent_groups.set([g_2nd_grade]) + + p_1 = Person.objects.create(first_name="A", last_name="B") + p_2 = Person.objects.create(first_name="A", last_name="B") + + g_2nd_grade.owners.set([p_1]) + + assert g_2a in p_1.owner_of_recursive.all() + assert g_2b in p_1.owner_of_recursive.all() + assert g_2a not in p_2.owner_of_recursive.all() + assert g_2b not in p_2.owner_of_recursive.all() diff --git a/aleksis/core/tests/models/test_pdffile.py b/aleksis/core/tests/models/test_pdffile.py index 1f1e936a8c72a6dca3c4796a18a69b9370adbb0a..d18e621d77043b3adafe93e5b18a04355950cfad 100644 --- a/aleksis/core/tests/models/test_pdffile.py +++ b/aleksis/core/tests/models/test_pdffile.py @@ -18,6 +18,7 @@ from aleksis.core.util.pdf import clean_up_expired_pdf_files pytestmark = pytest.mark.django_db +@pytest.mark.skip @pytest.mark.usefixtures("celery_worker") @override_settings(CELERY_BROKER_URL="memory://localhost//") class PDFFIleTest(TransactionTestCase): diff --git a/aleksis/core/tests/regression/test_regression.py b/aleksis/core/tests/regression/test_regression.py new file mode 100644 index 0000000000000000000000000000000000000000..7ac541531db385ea8e28b454dc487458a45d7a66 --- /dev/null +++ b/aleksis/core/tests/regression/test_regression.py @@ -0,0 +1,35 @@ +def test_all_settigns_registered(): + """Tests for regressions of preferences not being registered. + + https://edugit.org/AlekSIS/official/AlekSIS-Core/-/issues/592 + """ + + from dynamic_preferences.types import BasePreferenceType + + from aleksis.core import preferences + from aleksis.core.preferences import person_preferences_registry, site_preferences_registry + + for obj in preferences.__dict__.values(): + if not isinstance(obj, BasePreferenceType): + continue + + in_site_reg = site_preferences_registry.get(obj.section.name, {}).get(obj.name, None) is obj + in_person_reg = ( + person_preferences_registry.get(obj.section.name, {}).get(obj.name, None) is obj + ) + + assert in_site_reg != in_person_reg + + +def test_custom_managers_return_correct_qs(): + """Tests that custom managers' get_queryset methods return the expected qs. + + https://edugit.org/AlekSIS/official/AlekSIS-Core/-/issues/594 + """ + + from aleksis.core import managers + + def _check_get_queryset(Manager, QuerySet): + assert isinstance(Manager.from_queryset(QuerySet)().get_queryset(), QuerySet) + + _check_get_queryset(managers.GroupManager, managers.GroupQuerySet) diff --git a/aleksis/core/tests/views/test_account.py b/aleksis/core/tests/views/test_account.py index 28686eabf8290a7a72444d8fe5f4b71bb74f4626..ae598ab72826d403e94531ef2bf7194b4ee5225c 100644 --- a/aleksis/core/tests/views/test_account.py +++ b/aleksis/core/tests/views/test_account.py @@ -1,10 +1,23 @@ from django.conf import settings +from django.test import override_settings from django.urls import reverse +import ldap import pytest +from django_auth_ldap.config import LDAPSearch + +from aleksis.core.models import UserAdditionalAttributes pytestmark = pytest.mark.django_db +LDAP_BASE = "dc=example,dc=com" +LDAP_SETTINGS = { + "AUTH_LDAP_GLOBAL_OPTIONS": { + ldap.OPT_NETWORK_TIMEOUT: 1, + }, + "AUTH_LDAP_USER_SEARCH": LDAPSearch(LDAP_BASE, ldap.SCOPE_SUBTREE), +} + def test_index_not_logged_in(client): response = client.get("/") @@ -40,3 +53,34 @@ def test_logout(client, django_user_model): assert response.status_code == 200 assert "Please login to see this page." in response.content.decode("utf-8") + + +@override_settings( + AUTHENTICATION_BACKENDS=[ + "aleksis.core.util.ldap.LDAPBackend", + "django.contrib.auth.backends.ModelBackend", + ], + AUTH_LDAP_SERVER_URI="ldap://[100::0]", + AUTH_LDAP_SET_USABLE_PASSWORD=True, + **LDAP_SETTINGS +) +def test_login_ldap_fail_if_previously_ldap_authenticated(client, django_user_model): + username = "foo" + password = "bar" + + django_user_model.objects.create_user(username=username, password=password) + + # Logging in with a fresh account should success + res = client.login(username=username, password=password) + assert res + client.get(reverse("logout"), follow=True) + + # Logging in with a previously LDAP-authenticated account should fail + UserAdditionalAttributes.set_user_attribute(username, "ldap_authenticated", True) + res = client.login(username=username, password=password) + assert not res + + # Explicitly noting account has not been used with LDAP should succeed + UserAdditionalAttributes.set_user_attribute(username, "ldap_authenticated", False) + res = client.login(username=username, password=password) + assert res diff --git a/aleksis/core/urls.py b/aleksis/core/urls.py index 0c00bb8b26b397f2b0bdfb591bd232fcb3d13e74..b5dcb004d040b64b22242b977702a104fb2ea33a 100644 --- a/aleksis/core/urls.py +++ b/aleksis/core/urls.py @@ -23,6 +23,7 @@ urlpatterns = [ path("serviceworker.js", views.ServiceWorkerView.as_view(), name="service_worker"), path("offline/", views.OfflineView.as_view(), name="offline"), path("about/", views.about, name="about_aleksis"), + path("accounts/signup/", views.AccountRegisterView.as_view(), name="account_signup"), path("accounts/logout/", auth_views.LogoutView.as_view(), name="logout"), path( "accounts/password/change/", @@ -30,6 +31,16 @@ urlpatterns = [ name="account_change_password", ), path("accounts/", include("allauth.urls")), + path("invitations/send-invite", views.InvitePerson.as_view(), name="invite_person"), + path( + "invitations/code/enter", views.EnterInvitationCode.as_view(), name="enter_invitation_code" + ), + path( + "invitations/code/generate", + views.GenerateInvitationCode.as_view(), + name="generate_invitation_code", + ), + path("invitations/", include("invitations.urls")), path( "accounts/social/connections/<int:pk>/delete", views.SocialAccountDeleteView.as_view(), @@ -39,6 +50,7 @@ urlpatterns = [ path("admin/uwsgi/", include("django_uwsgi.urls")), path("data_management/", views.data_management, name="data_management"), path("status/", views.SystemStatus.as_view(), name="system_status"), + path("account/login/", views.LoginView.as_view(), name="login"), path("", include(tf_urls)), path("celery_progress/<str:task_id>/", views.CeleryProgressView.as_view(), name="task_status"), path("accounts/logout/", auth_views.LogoutView.as_view(), name="logout"), @@ -51,6 +63,7 @@ urlpatterns = [ path("person/<int:id_>/", views.person, name="person_by_id"), path("person/<int:pk>/edit/", views.EditPersonView.as_view(), name="edit_person_by_id"), path("person/<int:id_>/delete/", views.delete_person, name="delete_person_by_id"), + path("person/<int:id_>/invite/", views.InvitePersonByID.as_view(), name="invite_person_by_id"), path("groups", views.groups, name="groups"), path("groups/additional_fields", views.additional_fields, name="additional_fields"), path("groups/child_groups/", views.groups_child_groups, name="groups_child_groups"), @@ -121,6 +134,11 @@ urlpatterns = [ views.OAuth2EditView.as_view(), name="edit_oauth2_application", ), + path( + "oauth/authorize/", + views.CustomAuthorizationView.as_view(), + name="oauth2_provider:authorize", + ), path("oauth/", include("oauth2_provider.urls", namespace="oauth2_provider")), path("__i18n__/", include("django.conf.urls.i18n")), path( diff --git a/aleksis/core/util/core_helpers.py b/aleksis/core/util/core_helpers.py index 3dcebe4df7d97fa7fed8db4efda25362bee16210..3b3c934a85341e75092b6ef1e8df77bdc838687e 100644 --- a/aleksis/core/util/core_helpers.py +++ b/aleksis/core/util/core_helpers.py @@ -3,7 +3,7 @@ from datetime import datetime, timedelta from importlib import import_module, metadata from itertools import groupby from operator import itemgetter -from typing import Any, Callable, Optional, Sequence, Union +from typing import Any, Callable, Dict, Optional, Sequence, Union from warnings import warn from django.conf import settings @@ -13,7 +13,9 @@ from django.db.models import Model, QuerySet from django.http import HttpRequest from django.shortcuts import get_object_or_404 from django.utils import timezone +from django.utils.crypto import get_random_string from django.utils.functional import lazy +from django.utils.module_loading import import_string from cache_memoize import cache_memoize @@ -198,7 +200,7 @@ def has_person(obj: Union[HttpRequest, Model]) -> bool: return True -def custom_information_processor(request: HttpRequest) -> dict: +def custom_information_processor(request: Union[HttpRequest, None]) -> dict: """Provide custom information in all templates.""" from ..models import CustomMenu @@ -278,6 +280,11 @@ def queryset_rules_filter( return queryset.filter(pk__in=wanted_objects) +def generate_random_code(length, packet_size) -> str: + """Generate random code for e.g. invitations.""" + return get_random_string(packet_size * length).lower() + + def unread_notifications_badge(request: HttpRequest) -> int: """Generate badge content with the number of unread notifications.""" return request.user.person.unread_notifications_count @@ -316,3 +323,12 @@ def get_allowed_object_ids(request: HttpRequest, models: list) -> list: ] return allowed_object_ids + + +def process_custom_context_processors(context_processors: list) -> Dict[str, Any]: + """Process custom context processors.""" + context = {} + processors = tuple(import_string(path) for path in context_processors) + for processor in processors: + context.update(processor(None)) + return context diff --git a/aleksis/core/util/ldap.py b/aleksis/core/util/ldap.py index 96b058ac0060975cdd08281be94ba4df371aa7db..b60c9de98a48ca8b34a1cbd758301f0542cc9116 100644 --- a/aleksis/core/util/ldap.py +++ b/aleksis/core/util/ldap.py @@ -4,6 +4,8 @@ from django.core.exceptions import PermissionDenied from django_auth_ldap.backend import LDAPBackend as _LDAPBackend +from ..models import UserAdditionalAttributes + class LDAPBackend(_LDAPBackend): default_settings = {"SET_USABLE_PASSWORD": False} @@ -24,11 +26,28 @@ class LDAPBackend(_LDAPBackend): if self.settings.SET_USABLE_PASSWORD: if not user: - # Fail early and do not try other backends - raise PermissionDenied("LDAP failed to authenticate user") + # The user could not be authenticated against LDAP. + # We need to make sure to let other backends handle it, but also that + # we do not let actually deleted/locked LDAP users fall through to a + # backend that cached a valid password + if UserAdditionalAttributes.get_user_attribute( + ldap_user._username, "ldap_authenticated", False + ): + # User was LDAP-authenticated in the past, so we fail authentication now + # to not let other backends override a legitimate deletion + raise PermissionDenied("LDAP failed to authenticate user") + else: + # No note about LDAP authentication in the past + # The user can continue authentication like before if they exist + return user # Set a usable password so users can change their LDAP password user.set_password(password) user.save() + # Not that we LDAP-autenticated the user so we can check this in the future + UserAdditionalAttributes.set_user_attribute( + ldap_user._username, "ldap_authenticated", True + ) + return user diff --git a/aleksis/core/util/notifications.py b/aleksis/core/util/notifications.py index 38d27057033752d6ae7cdefce9c53b4728447b80..dac344b7a2e2877d65ff1bc80b580b860bf1067f 100644 --- a/aleksis/core/util/notifications.py +++ b/aleksis/core/util/notifications.py @@ -21,7 +21,7 @@ except ImportError: def send_templated_sms( template_name: str, from_number: str, recipient_list: Sequence[str], context: dict ) -> None: - """Render a plan-text template and send via SMS to all recipients.""" + """Render a plain-text template and send via SMS to all recipients.""" template = get_template(template_name) text = template.render(context) diff --git a/aleksis/core/util/pdf.py b/aleksis/core/util/pdf.py index 3f27680d9d8b3fc569a457ec78a2ce7c154c23d1..d65000811b123eab7ce6ad7e7ce29b02c3d73b06 100644 --- a/aleksis/core/util/pdf.py +++ b/aleksis/core/util/pdf.py @@ -1,7 +1,7 @@ import os import subprocess # noqa from tempfile import TemporaryDirectory -from typing import Optional, Tuple +from typing import Optional, Tuple, Union from urllib.parse import urljoin from django.conf import settings @@ -22,6 +22,7 @@ from celery_progress.backend import ProgressRecorder from aleksis.core.celery import app from aleksis.core.models import PDFFile from aleksis.core.util.celery_progress import recorded_task, render_progress_page +from aleksis.core.util.core_helpers import process_custom_context_processors @recorded_task @@ -71,7 +72,12 @@ def generate_pdf_from_template( template_name: str, context: Optional[dict] = None, request: Optional[HttpRequest] = None ) -> Tuple[PDFFile, AsyncResult]: """Start a PDF generation task and return the matching file object and Celery result.""" - html_template = render_to_string(template_name, context, request) + if not request: + processed_context = process_custom_context_processors(settings.PDF_CONTEXT_PROCESSORS) + processed_context.update(context) + else: + processed_context = context + html_template = render_to_string(template_name, processed_context, request) file_object = PDFFile.objects.create(html_file=ContentFile(html_template, name="source.html")) @@ -87,7 +93,9 @@ def generate_pdf_from_template( return file_object, result -def render_pdf(request: HttpRequest, template_name: str, context: dict = None) -> HttpResponse: +def render_pdf( + request: Union[HttpRequest, None], template_name: str, context: dict = None +) -> HttpResponse: """Start PDF generation and show progress page. The progress page will redirect to the PDF after completion. diff --git a/aleksis/core/util/sass_helpers.py b/aleksis/core/util/sass_helpers.py index 2579ed83a6f7d7f143456e227f1c662987ba3f55..21e3d0bacd0700dc7c0db74182e547e6c885172c 100644 --- a/aleksis/core/util/sass_helpers.py +++ b/aleksis/core/util/sass_helpers.py @@ -23,7 +23,7 @@ def get_preference(section: str, name: str) -> str: def clean_scss(*args, **kwargs) -> None: """Unlink compiled CSS (i.e. cache invalidation).""" sass_storage = SassFileStorage() - __, files = sass_storage.listdir("") + __, files = sass_storage.listdir("public") for source_map in filter(lambda x: x.endswith(".css.map"), files): - sass_storage.delete(source_map) + sass_storage.delete(f"public/{source_map}") diff --git a/aleksis/core/views.py b/aleksis/core/views.py index a1e1177150c11cb50f1012cebad1c1128dbc14da..49ef723df8d5fdb27d810c8668d9ec3559d9272e 100644 --- a/aleksis/core/views.py +++ b/aleksis/core/views.py @@ -1,5 +1,6 @@ +from textwrap import wrap from typing import Any, Dict, Optional, Type -from urllib.parse import urlencode +from urllib.parse import urlencode, urlparse, urlunparse from django.apps import apps from django.conf import settings @@ -14,27 +15,28 @@ from django.http import ( Http404, HttpRequest, HttpResponse, - HttpResponseNotFound, HttpResponseRedirect, HttpResponseServerError, JsonResponse, + QueryDict, ) from django.shortcuts import get_object_or_404, redirect, render from django.template import loader from django.urls import reverse, reverse_lazy +from django.utils import timezone from django.utils.decorators import method_decorator from django.utils.translation import get_language from django.utils.translation import gettext_lazy as _ from django.views.decorators.cache import never_cache from django.views.defaults import ERROR_500_TEMPLATE_NAME -from django.views.generic import FormView from django.views.generic.base import TemplateView, View from django.views.generic.detail import DetailView, SingleObjectMixin -from django.views.generic.edit import DeleteView +from django.views.generic.edit import DeleteView, FormView from django.views.generic.list import ListView import reversion -from allauth.account.views import PasswordChangeView +from allauth.account.utils import _has_verified_for_login, send_email_confirmation +from allauth.account.views import PasswordChangeView, SignupView from allauth.socialaccount.adapter import get_adapter from allauth.socialaccount.models import SocialAccount from celery_progress.views import get_progress @@ -48,9 +50,15 @@ from haystack.inputs import AutoQuery from haystack.query import SearchQuerySet from haystack.utils.loading import UnifiedIndex from health_check.views import MainView +from invitations.views import SendInvite, accept_invitation +from oauth2_provider.exceptions import OAuthToolkitError +from oauth2_provider.models import get_application_model +from oauth2_provider.views import AuthorizationView from reversion import set_user from reversion.views import RevisionMixin +from rules import test_rule from rules.contrib.views import PermissionRequiredMixin, permission_required +from two_factor.views.core import LoginView as AllAuthLoginView from aleksis.core.data_checks import DataCheckRegistry, check_data @@ -64,6 +72,7 @@ from .filters import ( UserObjectPermissionFilter, ) from .forms import ( + AccountRegisterForm, AnnouncementForm, AssignPermissionForm, ChildGroupsForm, @@ -72,6 +81,7 @@ from .forms import ( EditGroupForm, EditGroupTypeForm, GroupPreferenceForm, + InvitationCodeForm, OAuthApplicationForm, PersonForm, PersonPreferenceForm, @@ -93,6 +103,7 @@ from .models import ( OAuthApplication, PDFFile, Person, + PersonInvitation, SchoolTerm, TaskUserAssignment, ) @@ -108,6 +119,7 @@ from .tables import ( GroupObjectPermissionTable, GroupsTable, GroupTypesTable, + InvitationsTable, PersonsTable, SchoolTermTable, UserGlobalPermissionTable, @@ -117,6 +129,7 @@ from .util import messages from .util.apps import AppConfig from .util.celery_progress import render_progress_page from .util.core_helpers import ( + generate_random_code, get_allowed_object_ids, get_pwa_icons, get_site_preferences, @@ -288,9 +301,7 @@ def persons(request: HttpRequest) -> HttpResponse: context = {} # Get all persons - persons = get_objects_for_user( - request.user, "core.view_person", Person.objects.filter(is_active=True) - ) + persons = get_objects_for_user(request.user, "core.view_person", Person.objects.all()) # Get filter persons_filter = PersonFilter(request.GET, queryset=persons) @@ -337,7 +348,7 @@ def group(request: HttpRequest, id_: int) -> HttpResponse: group = Group.objects.get(pk=id_) # Get members - members = group.members.filter(is_active=True) + members = group.members.all() # Build table members_table = PersonsTable(members) @@ -345,7 +356,7 @@ def group(request: HttpRequest, id_: int) -> HttpResponse: context["members_table"] = members_table # Get owners - owners = group.owners.filter(is_active=True) + owners = group.owners.all() # Build table owners_table = PersonsTable(owners) @@ -663,11 +674,14 @@ def preferences( raise PermissionDenied() else: # Invalid registry name passed from URL - return HttpResponseNotFound() + raise Http404(_("The requested preference registry does not exist")) if not section and len(registry.sections()) > 0: default_section = list(registry.sections())[0] - return redirect(f"preferences_{registry_name}", default_section) + if instance: + return redirect(f"preferences_{registry_name}", instance.pk, default_section) + else: + return redirect(f"preferences_{registry_name}", default_section) # Build final form from dynamic-preferences form_class = preference_form_builder(form_class, instance=instance, section=section) @@ -900,7 +914,7 @@ class SolveDataCheckView(PermissionRequiredMixin, RevisionMixin, DetailView): messages.success(request, msg) return redirect("check_data") else: - return HttpResponseNotFound() + raise Http404(_("The requested solve option does not exist")) class DashboardWidgetListView(PermissionRequiredMixin, SingleTableView): @@ -1051,6 +1065,72 @@ class EditDashboardView(PermissionRequiredMixin, View): return render(request, "core/edit_dashboard.html", context=context) +class InvitePerson(PermissionRequiredMixin, SingleTableView, SendInvite): + """View to invite a person to register an account.""" + + template_name = "invitations/forms/_invite.html" + permission_required = "core.can_invite" + model = PersonInvitation + table_class = InvitationsTable + context = {} + + # Get queryset of invitations + def get_context_data(self, **kwargs): + queryset = kwargs.pop("object_list", None) + if queryset is None: + self.object_list = self.model.objects.all() + return super().get_context_data(**kwargs) + + +class EnterInvitationCode(FormView): + """View to enter an invitation code.""" + + template_name = "invitations/enter.html" + form_class = InvitationCodeForm + + def form_valid(self, form): + code = "".join(form.cleaned_data["code"].lower().split("-")) + # Check if valid invitations exists + if ( + PersonInvitation.objects.filter(key=code).exists() + and not PersonInvitation.objects.get(key=code).accepted + and not PersonInvitation.objects.get(key=code).key_expired() + ): + invitation = PersonInvitation.objects.get(key=code) + # Mark invitation as accepted and redirect to signup + accept_invitation( + invitation=invitation, request=self.request, signal_sender=self.request.user + ) + return redirect("account_signup") + return redirect("invitations:accept-invite", code) + + +class GenerateInvitationCode(View): + """View to generate an invitation code.""" + + def get(self, request): + # Build code + length = get_site_preferences()["auth__invite_code_length"] + packet_size = get_site_preferences()["auth__invite_code_packet_size"] + code = generate_random_code(length, packet_size) + + # Create invitation object + invitation = PersonInvitation.objects.create( + email="", inviter=request.user, key=code, sent=timezone.now() + ) + + # Make code more readable + code = "-".join(wrap(invitation.key, 5)) + + # Generate success message and print code + messages.success( + request, + _(f"The invitation was successfully created. The invitation code is {code}"), + ) + + return redirect("invite_person") + + class PermissionsListBaseView(PermissionRequiredMixin, SingleTableMixin, FilterView): """Base view for list of all permissions.""" @@ -1244,7 +1324,7 @@ class RedirectToPDFFile(SingleObjectMixin, View): def get(self, *args, **kwargs): file_object = self.get_object() if not file_object.file: - raise Http404() + raise Http404(_("The requested PDF file does not exist")) return redirect(file_object.file.url) @@ -1253,11 +1333,11 @@ class CeleryProgressView(View): def get(self, request: HttpRequest, task_id: str, *args, **kwargs) -> HttpResponse: if request.user.is_anonymous: - raise Http404() + raise Http404(_("The requested task does not exist or is not accessible")) if not TaskUserAssignment.objects.filter( task_result__task_id=task_id, user=request.user ).exists(): - raise Http404() + raise Http404(_("The requested task does not exist or is not accessible")) return get_progress(request, task_id, *args, **kwargs) @@ -1315,3 +1395,109 @@ def server_error( context = {"request": request} return HttpResponseServerError(template.render(context)) + + +class AccountRegisterView(SignupView): + """Custom view to register a user account. + + Rewrites dispatch function from allauth to check if signup is open or if the user + has a verified email address from an invitation; otherwise raises permission denied. + """ + + form_class = AccountRegisterForm + success_url = "index" + + def dispatch(self, request, *args, **kwargs): + if not test_rule("core.can_register") and not request.session.get("account_verified_email"): + raise PermissionDenied() + return super(AccountRegisterView, self).dispatch(request, *args, **kwargs) + + def get_form_kwargs(self): + kwargs = super(AccountRegisterView, self).get_form_kwargs() + kwargs["request"] = self.request + return kwargs + + +class InvitePersonByID(View): + """Custom view to invite person by their ID.""" + + success_url = reverse_lazy("persons") + + def get(self, request, *args, **kwargs): + self.object = self.get_object() + success_url = reverze_lazy("person_by_id", self.object.pk) + person = self.object + + if not PersonInvitation.objects.filter(email=person.email).exists(): + length = get_site_preferences()["auth__invite_code_length"] + packet_size = get_site_preferences()["auth__invite_code_packet_size"] + key = generate_random_code(length, packet_size) + invite = PersonInvitation.objects.create(person=person, key=key) + if person.email: + invite.email = person.email + invite.inviter = self.request.user + invite.save() + + invite.send_invitation(self.request) + messages.success(self.request, _("Person was invited successfully.")) + else: + messages.success(self.request, _("Person was already invited.")) + + return HttpResponseRedirect(success_url) + + +class LoginView(AllAuthLoginView): + """Custom login view covering e-mail verification if mandatory. + + Overrides view from allauth to check if email verification from django-invitations is + mandatory. If it i, checks if the user has a verified email address, if not, + it re-sends verification. + """ + + def done(self, form_list, **kwargs): + if settings.ACCOUNT_EMAIL_VERIFICATION == "mandatory": + user = self.get_user() + if not _has_verified_for_login(user, user.email): + send_email_confirmation(self.request, user, signup=False, email=user.email) + return render(self.request, "account/verification_sent.html") + + return super().done(form_list, **kwargs) + + def get_context_data(self, form, **kwargs): + """Override context data to hide side menu and include OAuth2 application if given.""" + context = super().get_context_data(form, **kwargs) + if self.request.GET.get("oauth"): + context["no_menu"] = True + + if self.request.GET.get("client_id"): + application = get_application_model().objects.get( + client_id=self.request.GET["client_id"] + ) + context["oauth_application"] = application + return context + + +class CustomAuthorizationView(AuthorizationView): + def handle_no_permission(self): + """Override handle_no_permission to provide OAuth2 information to login page.""" + redirect_obj = super().handle_no_permission() + + try: + scopes, credentials = self.validate_authorization_request(self.request) + except OAuthToolkitError as error: + # Application is not available at this time. + return self.error_response(error, application=None) + + login_url_parts = list(urlparse(redirect_obj.url)) + querystring = QueryDict(login_url_parts[4], mutable=True) + querystring["oauth"] = "yes" + querystring["client_id"] = credentials["client_id"] + login_url_parts[4] = querystring.urlencode(safe="/") + + return HttpResponseRedirect(urlunparse(login_url_parts)) + + def get_context_data(self, **kwargs): + """Override context data to hide side menu.""" + context = super().get_context_data(**kwargs) + context["no_menu"] = True + return context diff --git a/docs/_static/create_social_application.png b/docs/_static/create_social_application.png new file mode 100644 index 0000000000000000000000000000000000000000..c28c5c30a6d71f8aa0f1177b92048449c688d113 Binary files /dev/null and b/docs/_static/create_social_application.png differ diff --git a/docs/admin/01_install.rst b/docs/admin/01_install.rst index 5251a054be53d1e587fbadc0c9c4b848d25df249..6d1984b96e103d90d33496f4e520b7049e748a1a 100644 --- a/docs/admin/01_install.rst +++ b/docs/admin/01_install.rst @@ -164,6 +164,7 @@ First, you should get a TLS certificate, e.g. by using `Let's Encrypt`_. Then, create a virtual host in nginx, by editing `/etc/nginx/sites-available/aleksis.example.com`. .. code-block:: nginx + upstream aleksis { server unix:///run/uwsgi/app/aleksis/socket; } diff --git a/docs/admin/03_socialaccounts.rst b/docs/admin/03_socialaccounts.rst new file mode 100644 index 0000000000000000000000000000000000000000..97b023947a27768b825c693b7c5cd8bff938a49e --- /dev/null +++ b/docs/admin/03_socialaccounts.rst @@ -0,0 +1,34 @@ +Social accounts +=============== + +AlekSIS can authenticate users against third party applications using OAuth2 +or OpenID. + + +.. warning:: + Social accounts are **not** working with two factor authentication! If a user + authenticates with a social account, the two factor authentication is + ignored on login (but enforced for views that require two factor authentication later). + +Configuring social account provider +----------------------------------- + +For available providers, see documentation of `django-allauth +<https://django-allauth.readthedocs.io/en/latest/providers.html>`_. + +A new social account provider can be configured in your configuration file +(located in ``/etc/aleksis/``). + +Configuration example:: + + [auth.providers.gitlab] + GITLAB_URL = "https://gitlab.exmaple.com" + +After configuring a new auth provider, you have to restart AlekSIS and configure client id and secret in the Backend Admin interface. +Click "Social applications" and add a new application. Choose your +provider and enter client id and secret from your application and choose +your site: + +.. image:: ../_static/create_social_application.png + :width: 400 + :alt: Create social application diff --git a/docs/dev/01_setup.rst b/docs/dev/01_setup.rst index dd3121a822e53c603b21511b790f5ef6950f295a..24a64dbf7b7536193f7691538b2846409782519d 100644 --- a/docs/dev/01_setup.rst +++ b/docs/dev/01_setup.rst @@ -20,7 +20,7 @@ AlekSIS requires `PostgreSQL`_ (version 13 or newer) as database backend. To provide a database names `aleksis` with a user named `aleksis` on Debian:: - sudo apt install postgresql-13 + sudo apt install postgresql sudo -u postgres createuser -P aleksis sudo -u postgres createdb -O aleksis aleksis @@ -86,16 +86,15 @@ some maintenance tasks need to be done: 2. Collect static files 3. Run database migrations -All three steps can be done with the ``poetry run`` command and +All three steps can be done with the ``poetry shell`` command and ``aleksis-admin``:: - poetry run aleksis-admin yarn install - poetry run aleksis-admin collectstatic - poetry run aleksis-admin compilemessages - poetry run aleksis-admin migrate - poetry run aleksis-admin createinitialrevisions - -(You might need database settings for the `migrate` command; see below.) + ALEKSIS_maintenance__debug=true ALEKSIS_database__password=aleksis poetry shell + poetry run aleksis-admin yarn install + poetry run aleksis-admin collectstatic + poetry run aleksis-admin compilemessages + poetry run aleksis-admin migrate + poetry run aleksis-admin createinitialrevisions Running the development server ------------------------------ @@ -108,7 +107,7 @@ basic settings in as environment variable. Here is an example that runs the development server against a local PostgreSQL database with password `aleksis` (all else remains default) and with the `debug` setting enabled:: - ALEKSIS_debug=true ALEKSIS_database__password=aleksis poetry run aleksis-admin runuwsgi + ALEKSIS_maintenance__debug=true ALEKSIS_database__password=aleksis poetry run aleksis-admin runuwsgi .. figure:: /screenshots/index.png :scale: 50% diff --git a/docs/dev/04_materialize_templates.rst b/docs/dev/04_materialize_templates.rst index 3e7979cf1d39c317bb02832d43c84ab970b9d7a1..882604168d04ae6fd6085626305844a8648405e7 100644 --- a/docs/dev/04_materialize_templates.rst +++ b/docs/dev/04_materialize_templates.rst @@ -111,7 +111,6 @@ In your ``forms.py`` you can configure the layout of the fields like in the Edit _("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")), @@ -136,4 +135,4 @@ After you've loaded the template tag, you can simply generate the table like thi .. _MaterializeCSS: https://materializecss.com/ .. _django-material: https://pypi.org/project/django-material/ -.. _Extended Navbar with Tabs: https://materializecss.com/navbar.html#navbar-tabs \ No newline at end of file +.. _Extended Navbar with Tabs: https://materializecss.com/navbar.html#navbar-tabs diff --git a/poetry.lock b/poetry.lock deleted file mode 100644 index 0ba1edc825a78164060b6f3c280b9532ffd96d8b..0000000000000000000000000000000000000000 --- a/poetry.lock +++ /dev/null @@ -1,5578 +0,0 @@ -[[package]] -name = "alabaster" -version = "0.7.12" -description = "A configurable sidebar-enabled Sphinx theme" -category = "dev" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "aleksis-builddeps" -version = "5+20211130152626.23302bab" -description = "AlekSIS (School Information System) — Build/Dev dependencies for apps" -category = "dev" -optional = false -python-versions = ">=3.9,<4.0" - -[package.dependencies] -black = ">=21.10b0,<22.0" -curlylint = ">=0.13.0,<0.14.0" -django-stubs = ">=1.1,<2.0" -flake8 = ">=4.0.0,<5.0.0" -flake8-bandit = ">=2.1.2,<3.0.0" -flake8-black = ">=0.2.0,<0.3.0" -flake8-builtins = ">=1.4.1,<2.0.0" -flake8-django = ">=1.0.0,<2.0.0" -flake8-docstrings = ">=1.5.0,<2.0.0" -flake8-fixme = ">=1.1.1,<2.0.0" -flake8-isort = ">=4.0.0,<5.0.0" -flake8-mypy = ">=17.8.0,<18.0.0" -flake8-rst-docstrings = ">=0.2.0,<0.3.0" -freezegun = ">=1.1.0,<2.0.0" -isort = ">=5.0.0,<6.0.0" -pytest = ">=6.0,<7.0" -pytest-cov = ">=3.0.0,<4.0.0" -pytest-django = ">=4.1,<5.0" -pytest-django-testing-postgresql = ">=0.1,<0.2" -pytest-sugar = ">=0.9.2,<0.10.0" -safety = ">=1.8.5,<2.0.0" -selenium = ">=4.0.0,<5.0.0" -sphinx = ">=3.0,<4.0" -sphinx-autodoc-typehints = ">=1.7,<2.0" -sphinx_materialdesign_theme = ">=0.1.11,<0.2.0" -sphinxcontrib-django = ">=0.5.0,<0.6.0" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "amqp" -version = "5.0.6" -description = "Low-level AMQP client for Python (fork of amqplib)." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -vine = "5.0.0" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "appnope" -version = "0.1.2" -description = "Disable App Nap on macOS >= 10.9" -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "asgiref" -version = "3.4.1" -description = "ASGI specs, helper code, and adapters" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.extras] -tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "asn1crypto" -version = "1.4.0" -description = "Fast ASN.1 parser and serializer with definitions for private keys, public keys, certificates, CRL, OCSP, CMS, PKCS#3, PKCS#7, PKCS#8, PKCS#12, PKCS#5, X.509 and TSP" -category = "dev" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "async-generator" -version = "1.10" -description = "Async generators and context managers for Python 3.5+" -category = "dev" -optional = false -python-versions = ">=3.5" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "atomicwrites" -version = "1.4.0" -description = "Atomic file writes." -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "attrs" -version = "21.2.0" -description = "Classes Without Boilerplate" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"] -docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "babel" -version = "2.9.1" -description = "Internationalization utilities" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.dependencies] -pytz = ">=2015.7" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "backcall" -version = "0.2.0" -description = "Specifications for callback functions passed in to an API" -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "bandit" -version = "1.7.1" -description = "Security oriented static analyser for python code." -category = "dev" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} -GitPython = ">=1.0.1" -PyYAML = ">=5.3.1" -stevedore = ">=1.20.0" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "beautifulsoup4" -version = "4.10.0" -description = "Screen-scraping library" -category = "main" -optional = false -python-versions = ">3.0.0" - -[package.dependencies] -soupsieve = ">1.2" - -[package.extras] -html5lib = ["html5lib"] -lxml = ["lxml"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "billiard" -version = "3.6.4.0" -description = "Python multiprocessing fork with improvements and bugfixes" -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "black" -version = "21.11b1" -description = "The uncompromising code formatter." -category = "dev" -optional = false -python-versions = ">=3.6.2" - -[package.dependencies] -click = ">=7.1.2" -mypy-extensions = ">=0.4.3" -pathspec = ">=0.9.0,<1" -platformdirs = ">=2" -regex = ">=2021.4.4" -tomli = ">=0.2.6,<2.0.0" -typing-extensions = [ - {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}, - {version = "!=3.10.0.1", markers = "python_version >= \"3.10\""}, -] - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -python2 = ["typed-ast (>=1.4.3)"] -uvloop = ["uvloop (>=0.15.2)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "bleach" -version = "4.1.0" -description = "An easy safelist-based HTML-sanitizing tool." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -packaging = "*" -six = ">=1.9.0" -webencodings = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "boolean.py" -version = "3.8" -description = "Define boolean algebras, create and parse boolean expressions and create custom boolean DSL." -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "boto3" -version = "1.20.17" -description = "The AWS SDK for Python" -category = "main" -optional = true -python-versions = ">= 3.6" - -[package.dependencies] -botocore = ">=1.23.17,<1.24.0" -jmespath = ">=0.7.1,<1.0.0" -s3transfer = ">=0.5.0,<0.6.0" - -[package.extras] -crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "botocore" -version = "1.23.17" -description = "Low-level, data-driven core of boto 3." -category = "main" -optional = true -python-versions = ">= 3.6" - -[package.dependencies] -jmespath = ">=0.7.1,<1.0.0" -python-dateutil = ">=2.1,<3.0.0" -urllib3 = ">=1.25.4,<1.27" - -[package.extras] -crt = ["awscrt (==0.12.5)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "bs4" -version = "0.0.1" -description = "Screen-scraping library" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -beautifulsoup4 = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "calendarweek" -version = "0.5.0" -description = "Utilities for working with calendar weeks in Python and Django" -category = "main" -optional = false -python-versions = ">=3.7,<4.0" - -[package.extras] -django = ["Django (>=2.2,<4.0)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "celery" -version = "5.1.2" -description = "Distributed Task Queue." -category = "main" -optional = false -python-versions = ">=3.6," - -[package.dependencies] -billiard = ">=3.6.4.0,<4.0" -click = ">=7.0,<8.0" -click-didyoumean = ">=0.0.3" -click-plugins = ">=1.1.1" -click-repl = ">=0.1.6" -Django = {version = ">=1.11", optional = true, markers = "extra == \"django\""} -kombu = ">=5.1.0,<6.0" -pytz = ">0.0-dev" -redis = {version = ">=3.2.0", optional = true, markers = "extra == \"redis\""} -vine = ">=5.0.0,<6.0" - -[package.extras] -arangodb = ["pyArango (>=1.3.2)"] -auth = ["cryptography"] -azureblockblob = ["azure-storage-blob (==12.6.0)"] -brotli = ["brotli (>=1.0.0)", "brotlipy (>=0.7.0)"] -cassandra = ["cassandra-driver (<3.21.0)"] -consul = ["python-consul2"] -cosmosdbsql = ["pydocumentdb (==2.3.2)"] -couchbase = ["couchbase (>=3.0.0)"] -couchdb = ["pycouchdb"] -django = ["Django (>=1.11)"] -dynamodb = ["boto3 (>=1.9.178)"] -elasticsearch = ["elasticsearch"] -eventlet = ["eventlet (>=0.26.1)"] -gevent = ["gevent (>=1.0.0)"] -librabbitmq = ["librabbitmq (>=1.5.0)"] -memcache = ["pylibmc"] -mongodb = ["pymongo[srv] (>=3.3.0)"] -msgpack = ["msgpack"] -pymemcache = ["python-memcached"] -pyro = ["pyro4"] -pytest = ["pytest-celery"] -redis = ["redis (>=3.2.0)"] -s3 = ["boto3 (>=1.9.125)"] -slmq = ["softlayer-messaging (>=1.0.3)"] -solar = ["ephem"] -sqlalchemy = ["sqlalchemy"] -sqs = ["boto3 (>=1.9.125)", "pycurl (==7.43.0.5)"] -tblib = ["tblib (>=1.3.0)", "tblib (>=1.5.0)"] -yaml = ["PyYAML (>=3.10)"] -zookeeper = ["kazoo (>=1.3.1)"] -zstd = ["zstandard"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "celery-haystack-ng" -version = "0.20.post2" -description = "An app for integrating Celery with Haystack" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -celery = ">=4.0" -django-appconf = ">=0.4.1" -django-haystack = ">=2.0" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "celery-progress" -version = "0.1.1" -description = "Drop in, configurable, dependency-free progress bars for your Django/Celery applications." -category = "main" -optional = false -python-versions = "*" - -[package.extras] -rabbitmq = ["channels-rabbitmq"] -redis = ["channels-redis"] -websockets = ["channels"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "certifi" -version = "2021.10.8" -description = "Python package for providing Mozilla's CA Bundle." -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "cffi" -version = "1.15.0" -description = "Foreign Function Interface for Python calling C code." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -pycparser = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "charset-normalizer" -version = "2.0.8" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" -optional = false -python-versions = ">=3.5.0" - -[package.extras] -unicode_backport = ["unicodedata2"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "click" -version = "7.1.2" -description = "Composable command line interface toolkit" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "click-didyoumean" -version = "0.3.0" -description = "Enables git-like *did-you-mean* feature in click" -category = "main" -optional = false -python-versions = ">=3.6.2,<4.0.0" - -[package.dependencies] -click = ">=7" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "click-plugins" -version = "1.1.1" -description = "An extension module for click to enable registering CLI commands via setuptools entry-points." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -click = ">=4.0" - -[package.extras] -dev = ["pytest (>=3.6)", "pytest-cov", "wheel", "coveralls"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "click-repl" -version = "0.2.0" -description = "REPL plugin for Click" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -click = "*" -prompt-toolkit = "*" -six = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "colorama" -version = "0.4.4" -description = "Cross-platform colored terminal text." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "colour" -version = "0.1.5" -description = "converts and manipulates various color representation (HSL, RVB, web, X11, ...)" -category = "main" -optional = false -python-versions = "*" - -[package.extras] -test = ["nose"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "configobj" -version = "5.0.6" -description = "Config file reading, writing and validation." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -six = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "coverage" -version = "6.2" -description = "Code coverage measurement for Python" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -tomli = {version = "*", optional = true, markers = "extra == \"toml\""} - -[package.extras] -toml = ["tomli"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "cryptography" -version = "36.0.0" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -cffi = ">=1.12" - -[package.extras] -docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx-rtd-theme"] -docstest = ["pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] -pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"] -sdist = ["setuptools_rust (>=0.11.4)"] -ssh = ["bcrypt (>=3.1.5)"] -test = ["pytest (>=6.2.0)", "pytest-cov", "pytest-subtests", "pytest-xdist", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,!=3.79.2)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "cssselect2" -version = "0.4.1" -description = "cssselect2" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -tinycss2 = "*" -webencodings = "*" - -[package.extras] -doc = ["sphinx", "sphinx-rtd-theme"] -test = ["pytest", "pytest-cov", "pytest-flake8", "pytest-isort", "coverage"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "curlylint" -version = "0.13.0" -description = "{{ 🎀}} Experimental HTML templates linting for Jinja, Nunjucks, Django templates, Twig, Liquid" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -attrs = ">=17.2.0" -click = ">=6.5" -parsy = "1.1.0" -pathspec = ">=0.6,<1" -toml = ">=0.9.4" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "decorator" -version = "5.1.0" -description = "Decorators for Humans" -category = "main" -optional = false -python-versions = ">=3.5" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "defusedxml" -version = "0.7.1" -description = "XML bomb protection for Python stdlib modules" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "deprecated" -version = "1.2.13" -description = "Python @deprecated decorator to deprecate old python classes, functions or methods." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.dependencies] -wrapt = ">=1.10,<2" - -[package.extras] -dev = ["tox", "bump2version (<1)", "sphinx (<2)", "importlib-metadata (<3)", "importlib-resources (<4)", "configparser (<5)", "sphinxcontrib-websupport (<2)", "zipp (<2)", "PyTest (<5)", "PyTest-Cov (<2.6)", "pytest", "pytest-cov"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "dj-database-url" -version = "0.5.0" -description = "Use Database URLs in your Django Application." -category = "dev" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django" -version = "3.2.9" -description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -asgiref = ">=3.3.2,<4" -pytz = "*" -sqlparse = ">=0.2.2" - -[package.extras] -argon2 = ["argon2-cffi (>=19.1.0)"] -bcrypt = ["bcrypt"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-allauth" -version = "0.46.0" -description = "Integrated set of Django applications addressing authentication, registration, account management as well as 3rd party (social) account authentication." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -Django = ">=2.0" -pyjwt = {version = ">=1.7", extras = ["crypto"]} -python3-openid = ">=3.0.8" -requests = "*" -requests-oauthlib = ">=0.3.0" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-any-js" -version = "1.1" -description = "Include JavaScript/CSS libraries with readable template tags" -category = "main" -optional = false -python-versions = ">=3.7,<4.0" - -[package.dependencies] -Django = ">=2.2,<4.0" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-appconf" -version = "1.0.5" -description = "A helper class for handling configuration defaults of packaged apps gracefully." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -django = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-auth-ldap" -version = "3.0.0" -description = "Django LDAP authentication backend." -category = "main" -optional = true -python-versions = ">=3.6" - -[package.dependencies] -Django = ">=2.2" -python-ldap = ">=3.1" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-bleach" -version = "1.0.0" -description = "Easily use bleach with Django models and templates" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -bleach = ">=1.5.0" -Django = ">=1.11" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-cachalot" -version = "2.4.4" -description = "Caches your Django ORM queries and automatically invalidates them." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -Django = ">=2.2,<3.3" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-cache-memoize" -version = "0.1.10" -description = "Django utility for a memoization decorator that uses the Django cache framework." -category = "main" -optional = false -python-versions = ">=3.5" - -[package.extras] -dev = ["flake8", "tox", "twine", "therapist", "black"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-celery-beat" -version = "2.2.1" -description = "Database-backed Periodic Tasks." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -celery = ">=5.0,<6.0" -Django = ">=2.2,<4.0" -django-timezone-field = ">=4.1.0,<5.0" -python-crontab = ">=2.3.4" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-celery-email" -version = "3.0.0" -description = "An async Django email backend using celery" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -celery = ">=4.0" -django = ">=2.2" -django-appconf = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-celery-results" -version = "2.2.0" -description = "Celery result backends for Django." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -celery = ">=5.0,<6.0" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-ckeditor" -version = "6.2.0" -description = "Django admin CKEditor integration." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -django-js-asset = ">=1.2.2" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-cleanup" -version = "5.2.0" -description = "Deletes old files." -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-colorfield" -version = "0.5.0" -description = "simple color field for your models with a nice color-picker in the admin-interface." -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-dbbackup" -version = "3.3.0" -description = "Management commands to help backup and restore a project database and media" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -Django = ">=1.5" -pytz = "*" -six = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-debug-toolbar" -version = "3.2.2" -description = "A configurable set of panels that display various debug information about the current request/response." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -Django = ">=2.2" -sqlparse = ">=0.2.0" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-dynamic-preferences" -version = "1.11.0" -description = "Dynamic global and instance settings for your django project" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -django = ">=1.11" -persisting-theory = ">=0.2.1" -six = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-extensions" -version = "3.1.5" -description = "Extensions for Django" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -Django = ">=2.2" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-favicon-plus-reloaded" -version = "1.1.3" -description = "simple Django app which allows you to upload a image and it renders a wide variety for html link tags to display the favicon" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -django = "*" -pillow = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-filter" -version = "2.4.0" -description = "Django-filter is a reusable Django application for allowing users to filter querysets dynamically." -category = "main" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -Django = ">=2.2" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-formtools" -version = "2.3" -description = "A set of high-level abstractions for Django forms" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -Django = ">=2.2" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-guardian" -version = "2.4.0" -description = "Implementation of per object permissions for Django." -category = "main" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -Django = ">=2.2" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-haystack" -version = "3.1.1" -description = "Pluggable search for Django." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -Django = ">=2.2" - -[package.extras] -elasticsearch = ["elasticsearch (>=5,<6)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-health-check" -version = "3.16.4" -description = "Run checks on services like databases, queue servers, celery processes, etc." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -django = ">=2.2" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-image-cropping" -version = "1.6.1" -description = "A reusable app for cropping images easily and non-destructively in Django" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -django-appconf = ">=1.0.2" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-impersonate" -version = "1.7.3" -description = "Django app to allow superusers to impersonate other users." -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-ipware" -version = "4.0.0" -description = "A Django application to retrieve user's IP address" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-js-asset" -version = "1.2.2" -description = "script tag with additional attributes for django.forms.Media" -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-js-reverse" -version = "0.9.1" -description = "Javascript url handling for Django that doesn't hurt." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -Django = ">=1.5" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-jsonstore" -version = "0.5.0" -description = "Expose JSONField data as a virtual django model fields." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -Django = ">=1.11" -six = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-maintenance-mode" -version = "0.16.1" -description = "django-maintenance-mode shows a 503 error page when maintenance-mode is on." -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-material" -version = "1.10.0" -description = "Material design for django forms and admin" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -six = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-menu-generator-ng" -version = "1.2.3" -description = "A straightforward menu generator for Django" -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-model-utils" -version = "4.2.0" -description = "Django model mixins and utilities" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -Django = ">=2.0.1" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-oauth-toolkit" -version = "1.5.0" -description = "OAuth2 Provider for Django" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -django = ">=2.2" -jwcrypto = ">=0.8.0" -oauthlib = ">=3.1.0" -requests = ">=2.13.0" -six = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-otp" -version = "1.1.3" -description = "A pluggable framework for adding two-factor authentication to Django using one-time passwords." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -django = ">=2.2" - -[package.extras] -qrcode = ["qrcode"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-otp-yubikey" -version = "1.0.1" -description = "A django-otp plugin that verifies YubiKey OTP tokens." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -django-otp = ">=1.0.0" -YubiOTP = ">=0.2.2" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-phonenumber-field" -version = "5.2.0" -description = "An international phone number field for django models." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -Django = ">=2.2" -phonenumbers = {version = ">=7.0.2", optional = true, markers = "extra == \"phonenumbers\""} - -[package.extras] -phonenumbers = ["phonenumbers (>=7.0.2)"] -phonenumberslite = ["phonenumberslite (>=7.0.2)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-polymorphic" -version = "3.1.0" -description = "Seamless polymorphic inheritance for Django models" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -Django = ">=2.1" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-prometheus" -version = "2.1.0" -description = "Django middlewares to monitor your application with Prometheus.io." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -prometheus-client = ">=0.7" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-redis" -version = "5.1.0" -description = "Full featured redis cache backend for Django." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -Django = ">=2.2" -redis = ">=3,<4" - -[package.extras] -hiredis = ["redis[hiredis] (>=3,<4)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-render-block" -version = "0.8.1" -description = "Render a particular block from a template to a string." -category = "main" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -django = ">=2.2" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-reversion" -version = "4.0.1" -description = "An extension to the Django web framework that provides version control for model instances." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -django = ">=2.0" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-sass-processor" -version = "1.0.0" -description = "SASS processor to compile SCSS files into *.css, while rendering, or offline." -category = "main" -optional = false -python-versions = "*" - -[package.extras] -management_command = ["django-compressor (>=2.4)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-select2" -version = "7.9.0" -description = "Select2 option fields for Django" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -django = ">=2.2" -django-appconf = ">=0.6.0" - -[package.extras] -test = ["pytest", "pytest-cov", "pytest-django", "selenium"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-storages" -version = "1.12.3" -description = "Support for many storage backends in Django" -category = "main" -optional = true -python-versions = ">=3.5" - -[package.dependencies] -Django = ">=2.2" - -[package.extras] -azure = ["azure-storage-blob (>=12.0.0)"] -boto3 = ["boto3 (>=1.4.4)"] -dropbox = ["dropbox (>=7.2.1)"] -google = ["google-cloud-storage (>=1.27.0)"] -libcloud = ["apache-libcloud"] -sftp = ["paramiko"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-stubs" -version = "1.9.0" -description = "Mypy stubs for Django" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -django = "*" -django-stubs-ext = ">=0.3.0" -mypy = ">=0.910" -toml = "*" -types-pytz = "*" -types-PyYAML = "*" -typing-extensions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-stubs-ext" -version = "0.3.1" -description = "Monkey-patching and extensions for django-stubs" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -django = "*" -typing-extensions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-tables2" -version = "2.4.1" -description = "Table/data-grid framework for Django" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -Django = ">=1.11" - -[package.extras] -tablib = ["tablib"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-templated-email" -version = "3.0.0" -description = "A Django oriented templated / transaction email abstraction" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -django-render-block = ">=0.5" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-timezone-field" -version = "4.2.1" -description = "A Django app providing database and form fields for pytz timezone objects." -category = "main" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -django = ">=2.2" -pytz = "*" - -[package.extras] -rest_framework = ["djangorestframework (>=3.0.0)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-titofisto" -version = "0.2.0" -description = "Django Time-Token File Storage" -category = "main" -optional = false -python-versions = ">=3.9,<4.0" - -[package.dependencies] -Django = ">2.2,<4.0" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-two-factor-auth" -version = "1.13.1" -description = "Complete Two-Factor Authentication for Django" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -Django = ">=2.2" -django-formtools = "*" -django-otp = ">=0.8.0" -django-otp-yubikey = {version = "*", optional = true, markers = "extra == \"yubikey\""} -django-phonenumber-field = ">=1.1.0,<6" -phonenumbers = {version = ">=7.0.9,<8.99", optional = true, markers = "extra == \"phonenumbers\""} -qrcode = ">=4.0.0,<6.99" -twilio = {version = ">=6.0", optional = true, markers = "extra == \"call\""} - -[package.extras] -call = ["twilio (>=6.0)"] -phonenumbers = ["phonenumbers (>=7.0.9,<8.99)"] -phonenumberslite = ["phonenumberslite (>=7.0.9,<8.99)"] -sms = ["twilio (>=6.0)"] -yubikey = ["django-otp-yubikey"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-uwsgi-ng" -version = "1.1.2" -description = "uWSGI stuff for Django projects" -category = "main" -optional = false -python-versions = "*" - -[package.extras] -uwsgi = ["uwsgi"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-widget-tweaks" -version = "1.4.9" -description = "Tweak the form field rendering in templates, not in python-level form definitions." -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "django-yarnpkg" -version = "6.0.1" -description = "Integrate django with yarnpkg" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -django = "*" -six = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "djangorestframework" -version = "3.12.4" -description = "Web APIs for Django, made easy." -category = "main" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -django = ">=2.2" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "docutils" -version = "0.16" -description = "Docutils -- Python Documentation Utilities" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "dparse" -version = "0.5.1" -description = "A parser for Python dependency files" -category = "dev" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -packaging = "*" -pyyaml = "*" -toml = "*" - -[package.extras] -pipenv = ["pipenv"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "dynaconf" -version = "3.1.7" -description = "The dynamic configurator for your Python Project" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -configobj = {version = "*", optional = true, markers = "extra == \"ini\""} -"ruamel.yaml" = {version = "*", optional = true, markers = "extra == \"yaml\""} -toml = {version = "*", optional = true, markers = "extra == \"toml\""} - -[package.extras] -all = ["redis", "ruamel.yaml", "configobj", "hvac"] -configobj = ["configobj"] -ini = ["configobj"] -redis = ["redis"] -toml = ["toml"] -vault = ["hvac"] -yaml = ["ruamel.yaml"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "easy-thumbnails" -version = "2.8" -description = "Easy thumbnails for Django" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -django = ">=2.2,<4.0" -pillow = "*" -reportlab = "*" -svglib = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "flake8" -version = "4.0.1" -description = "the modular source code checker: pep8 pyflakes and co" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -mccabe = ">=0.6.0,<0.7.0" -pycodestyle = ">=2.8.0,<2.9.0" -pyflakes = ">=2.4.0,<2.5.0" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "flake8-bandit" -version = "2.1.2" -description = "Automated security testing with bandit and flake8." -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -bandit = "*" -flake8 = "*" -flake8-polyfill = "*" -pycodestyle = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "flake8-black" -version = "0.2.3" -description = "flake8 plugin to call black as a code style validator" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -black = "*" -flake8 = ">=3.0.0" -toml = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "flake8-builtins" -version = "1.5.3" -description = "Check for python builtins being used as variables or parameters." -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -flake8 = "*" - -[package.extras] -test = ["coverage", "coveralls", "mock", "pytest", "pytest-cov"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "flake8-django" -version = "1.1.1" -description = "Plugin to catch bad style specific to Django Projects" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -flake8 = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "flake8-docstrings" -version = "1.6.0" -description = "Extension for flake8 which uses pydocstyle to check docstrings" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -flake8 = ">=3" -pydocstyle = ">=2.1" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "flake8-fixme" -version = "1.1.1" -description = "Check for FIXME, TODO and other temporary developer notes. Plugin for flake8." -category = "dev" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "flake8-isort" -version = "4.1.1" -description = "flake8 plugin that integrates isort ." -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -flake8 = ">=3.2.1,<5" -isort = ">=4.3.5,<6" -testfixtures = ">=6.8.0,<7" - -[package.extras] -test = ["pytest-cov"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "flake8-mypy" -version = "17.8.0" -description = "A plugin for flake8 integrating mypy." -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -attrs = "*" -flake8 = ">=3.0.0" -mypy = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "flake8-polyfill" -version = "1.0.2" -description = "Polyfill package for Flake8 plugins" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -flake8 = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "flake8-rst-docstrings" -version = "0.2.3" -description = "Python docstring reStructuredText (RST) validator" -category = "dev" -optional = false -python-versions = ">=3.3" - -[package.dependencies] -flake8 = ">=3.0.0" -pygments = "*" -restructuredtext-lint = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "freezegun" -version = "1.1.0" -description = "Let your Python tests travel through time" -category = "dev" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -python-dateutil = ">=2.7" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "gitdb" -version = "4.0.9" -description = "Git Object Database" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -smmap = ">=3.0.1,<6" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "gitpython" -version = "3.1.24" -description = "GitPython is a python library used to interact with Git repositories" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -gitdb = ">=4.0.1,<5" -typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.10\""} - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "h11" -version = "0.12.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "haystack-redis" -version = "0.0.1" -description = "Use redis as a persistence layer for Whoosh and Haystack" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -django-haystack = "*" -redis = "*" -whoosh = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "html2text" -version = "2020.1.16" -description = "Turn HTML into equivalent Markdown-structured text." -category = "main" -optional = false -python-versions = ">=3.5" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "idna" -version = "3.3" -description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" -optional = false -python-versions = ">=3.5" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "imagesize" -version = "1.3.0" -description = "Getting image size from png/jpeg/jpeg2000/gif file" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "iniconfig" -version = "1.1.1" -description = "iniconfig: brain-dead simple config-ini parsing" -category = "dev" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "ipython" -version = "7.30.0" -description = "IPython: Productive Interactive Computing" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -appnope = {version = "*", markers = "sys_platform == \"darwin\""} -backcall = "*" -colorama = {version = "*", markers = "sys_platform == \"win32\""} -decorator = "*" -jedi = ">=0.16" -matplotlib-inline = "*" -pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} -pickleshare = "*" -prompt-toolkit = ">=2.0.0,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.1.0" -pygments = "*" -traitlets = ">=4.2" - -[package.extras] -all = ["Sphinx (>=1.3)", "ipykernel", "ipyparallel", "ipywidgets", "nbconvert", "nbformat", "nose (>=0.10.1)", "notebook", "numpy (>=1.17)", "pygments", "qtconsole", "requests", "testpath"] -doc = ["Sphinx (>=1.3)"] -kernel = ["ipykernel"] -nbconvert = ["nbconvert"] -nbformat = ["nbformat"] -notebook = ["notebook", "ipywidgets"] -parallel = ["ipyparallel"] -qtconsole = ["qtconsole"] -test = ["nose (>=0.10.1)", "requests", "testpath", "pygments", "nbformat", "ipykernel", "numpy (>=1.17)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "isort" -version = "5.10.1" -description = "A Python utility / library to sort Python imports." -category = "dev" -optional = false -python-versions = ">=3.6.1,<4.0" - -[package.extras] -colors = ["colorama (>=0.4.3,<0.5.0)"] -requirements_deprecated_finder = ["pip-api", "pipreqs"] -pipfile_deprecated_finder = ["pipreqs", "requirementslib"] -plugins = ["setuptools"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "jedi" -version = "0.18.1" -description = "An autocompletion tool for Python that can be used for text editors." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -parso = ">=0.8.0,<0.9.0" - -[package.extras] -qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] -testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<7.0.0)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "jinja2" -version = "3.0.3" -description = "A very fast and expressive template engine." -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "jmespath" -version = "0.10.0" -description = "JSON Matching Expressions" -category = "main" -optional = true -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "jwcrypto" -version = "1.0" -description = "Implementation of JOSE Web standards" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -cryptography = ">=2.3" -deprecated = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "kombu" -version = "5.2.2" -description = "Messaging library for Python." -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -amqp = ">=5.0.6,<6.0.0" -vine = "*" - -[package.extras] -azureservicebus = ["azure-servicebus (>=7.0.0)"] -azurestoragequeues = ["azure-storage-queue"] -consul = ["python-consul (>=0.6.0)"] -librabbitmq = ["librabbitmq (>=2.0.0)"] -mongodb = ["pymongo (>=3.3.0,<3.12.1)"] -msgpack = ["msgpack"] -pyro = ["pyro4"] -qpid = ["qpid-python (>=0.26)", "qpid-tools (>=0.26)"] -redis = ["redis (>=3.4.1,<4.0.0)"] -slmq = ["softlayer-messaging (>=1.0.3)"] -sqlalchemy = ["sqlalchemy"] -sqs = ["boto3 (>=1.9.12)", "pycurl (>=7.44.1,<7.45.0)", "urllib3 (>=1.26.7)"] -yaml = ["PyYAML (>=3.10)"] -zookeeper = ["kazoo (>=1.3.1)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "libsass" -version = "0.21.0" -description = "Sass for Python: A straightforward binding of libsass for Python." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -six = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "license-expression" -version = "21.6.14" -description = "license-expression is a comprehensive utility library to parse, compare, simplify and normalize license expressions (such as SPDX license expressions) using boolean logic." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -"boolean.py" = ">=3.6,<4.0.0" - -[package.extras] -docs = ["Sphinx (>=3.3.1)", "sphinx-rtd-theme (>=0.5.0)", "doc8 (>=0.8.1)"] -testing = ["pytest (>=6)", "pytest-xdist (>=2)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "lxml" -version = "4.6.4" -description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" - -[package.extras] -cssselect = ["cssselect (>=0.7)"] -html5 = ["html5lib"] -htmlsoup = ["beautifulsoup4"] -source = ["Cython (>=0.29.7)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "markupsafe" -version = "2.0.1" -description = "Safely add untrusted strings to HTML/XML markup." -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "matplotlib-inline" -version = "0.1.3" -description = "Inline Matplotlib backend for Jupyter" -category = "main" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -traitlets = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "mccabe" -version = "0.6.1" -description = "McCabe checker, plugin for flake8" -category = "dev" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "mypy" -version = "0.910" -description = "Optional static typing for Python" -category = "dev" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -mypy-extensions = ">=0.4.3,<0.5.0" -toml = "*" -typing-extensions = ">=3.7.4" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -python2 = ["typed-ast (>=1.4.0,<1.5.0)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "mypy-extensions" -version = "0.4.3" -description = "Experimental type system extensions for programs checked with the mypy typechecker." -category = "dev" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "oauthlib" -version = "3.1.1" -description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.extras] -rsa = ["cryptography (>=3.0.0,<4)"] -signals = ["blinker (>=1.4.0)"] -signedtoken = ["cryptography (>=3.0.0,<4)", "pyjwt (>=2.0.0,<3)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "outcome" -version = "1.1.0" -description = "Capture the outcome of Python function calls." -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -attrs = ">=19.2.0" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "packaging" -version = "21.3" -description = "Core utilities for Python packages" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "parso" -version = "0.8.3" -description = "A Python Parser" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.extras] -qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] -testing = ["docopt", "pytest (<6.0.0)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "parsy" -version = "1.1.0" -description = "easy-to-use parser combinators, for parsing in pure Python" -category = "dev" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pathspec" -version = "0.9.0" -description = "Utility library for gitignore style pattern matching of file paths." -category = "dev" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pbr" -version = "5.8.0" -description = "Python Build Reasonableness" -category = "dev" -optional = false -python-versions = ">=2.6" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "persisting-theory" -version = "0.2.1" -description = "Registries that can autodiscover values accross your project apps" -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pexpect" -version = "4.8.0" -description = "Pexpect allows easy control of interactive console applications." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -ptyprocess = ">=0.5" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pg8000" -version = "1.23.0" -description = "PostgreSQL interface library" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -scramp = ">=1.4.1" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "phonenumbers" -version = "8.12.38" -description = "Python version of Google's common library for parsing, formatting, storing and validating international phone numbers." -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pickleshare" -version = "0.7.5" -description = "Tiny 'shelve'-like database with concurrency support" -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pillow" -version = "8.4.0" -description = "Python Imaging Library (Fork)" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "platformdirs" -version = "2.4.0" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.extras] -docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] -test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pluggy" -version = "1.0.0" -description = "plugin and hook calling mechanisms for python" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "prometheus-client" -version = "0.12.0" -description = "Python client for the Prometheus monitoring system." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.extras] -twisted = ["twisted"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "prompt-toolkit" -version = "3.0.23" -description = "Library for building powerful interactive command lines in Python" -category = "main" -optional = false -python-versions = ">=3.6.2" - -[package.dependencies] -wcwidth = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "psutil" -version = "5.8.0" -description = "Cross-platform lib for process and system monitoring in Python." -category = "main" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.extras] -test = ["ipaddress", "mock", "unittest2", "enum34", "pywin32", "wmi"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "psycopg2" -version = "2.9.2" -description = "psycopg2 - Python-PostgreSQL Database Adapter" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "ptyprocess" -version = "0.7.0" -description = "Run a subprocess in a pseudo terminal" -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pyasn1" -version = "0.4.8" -description = "ASN.1 types and codecs" -category = "main" -optional = true -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pyasn1-modules" -version = "0.2.8" -description = "A collection of ASN.1-based protocols modules." -category = "main" -optional = true -python-versions = "*" - -[package.dependencies] -pyasn1 = ">=0.4.6,<0.5.0" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pycodestyle" -version = "2.8.0" -description = "Python style guide checker" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pycparser" -version = "2.21" -description = "C parser in Python" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pycryptodome" -version = "3.11.0" -description = "Cryptographic library for Python" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pydocstyle" -version = "6.1.1" -description = "Python docstring style checker" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -snowballstemmer = "*" - -[package.extras] -toml = ["toml"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pyflakes" -version = "2.4.0" -description = "passive checker of Python programs" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pygments" -version = "2.10.0" -description = "Pygments is a syntax highlighting package written in Python." -category = "main" -optional = false -python-versions = ">=3.5" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pyjwt" -version = "2.3.0" -description = "JSON Web Token implementation in Python" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -cryptography = {version = ">=3.3.1", optional = true, markers = "extra == \"crypto\""} - -[package.extras] -crypto = ["cryptography (>=3.3.1)"] -dev = ["sphinx", "sphinx-rtd-theme", "zope.interface", "cryptography (>=3.3.1)", "pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)", "mypy", "pre-commit"] -docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] -tests = ["pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pyopenssl" -version = "21.0.0" -description = "Python wrapper module around the OpenSSL library" -category = "dev" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*" - -[package.dependencies] -cryptography = ">=3.3" -six = ">=1.5.2" - -[package.extras] -docs = ["sphinx", "sphinx-rtd-theme"] -test = ["flaky", "pretend", "pytest (>=3.0.1)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pyparsing" -version = "3.0.6" -description = "Python parsing module" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.extras] -diagrams = ["jinja2", "railroad-diagrams"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pytest" -version = "6.2.5" -description = "pytest: simple powerful testing with Python" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} -attrs = ">=19.2.0" -colorama = {version = "*", markers = "sys_platform == \"win32\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=0.12,<2.0" -py = ">=1.8.2" -toml = "*" - -[package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pytest-cov" -version = "3.0.0" -description = "Pytest plugin for measuring coverage." -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -coverage = {version = ">=5.2.1", extras = ["toml"]} -pytest = ">=4.6" - -[package.extras] -testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pytest-django" -version = "4.5.0" -description = "A Django plugin for pytest." -category = "dev" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -pytest = ">=5.4.0" - -[package.extras] -docs = ["sphinx", "sphinx-rtd-theme"] -testing = ["django", "django-configurations (>=2.0)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pytest-django-testing-postgresql" -version = "0.1.post0" -description = "Use a temporary PostgreSQL database with pytest-django" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -dj-database-url = "*" -"testing.postgresql" = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pytest-sugar" -version = "0.9.4" -description = "pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly)." -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -packaging = ">=14.1" -pytest = ">=2.9" -termcolor = ">=1.1.0" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "python-crontab" -version = "2.6.0" -description = "Python Crontab API" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -python-dateutil = "*" - -[package.extras] -cron-description = ["cron-descriptor"] -cron-schedule = ["croniter"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "python-dateutil" -version = "2.8.2" -description = "Extensions to the standard Python datetime module" -category = "main" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" - -[package.dependencies] -six = ">=1.5" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "python-gnupg" -version = "0.4.8" -description = "A wrapper for the Gnu Privacy Guard (GPG or GnuPG)" -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "python-ldap" -version = "3.4.0" -description = "Python modules for implementing LDAP clients" -category = "main" -optional = true -python-versions = ">=3.6" - -[package.dependencies] -pyasn1 = ">=0.3.7" -pyasn1_modules = ">=0.1.5" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "python3-openid" -version = "3.2.0" -description = "OpenID support for modern servers and consumers." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -defusedxml = "*" - -[package.extras] -mysql = ["mysql-connector-python"] -postgresql = ["psycopg2"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pytz" -version = "2021.3" -description = "World timezone definitions, modern and historical" -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "pyyaml" -version = "6.0" -description = "YAML parser and emitter for Python" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "qrcode" -version = "6.1" -description = "QR Code image generator" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} -six = "*" - -[package.extras] -dev = ["tox", "pytest", "mock"] -maintainer = ["zest.releaser"] -pil = ["pillow"] -test = ["pytest", "pytest-cov", "mock"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "redis" -version = "3.5.3" -description = "Python client for Redis key-value store" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.extras] -hiredis = ["hiredis (>=0.1.3)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "regex" -version = "2021.11.10" -description = "Alternative regular expression module, to replace re." -category = "dev" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "reportlab" -version = "3.6.3" -description = "The Reportlab Toolkit" -category = "main" -optional = false -python-versions = ">=3.6, <4" - -[package.dependencies] -pillow = ">=4.0.0" - -[package.extras] -RLPYCAIRO = ["rlPyCairo (>=0.0.5)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "requests" -version = "2.26.0" -description = "Python HTTP for Humans." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} -idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} -urllib3 = ">=1.21.1,<1.27" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] -use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "requests-oauthlib" -version = "1.3.0" -description = "OAuthlib authentication support for Requests." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.dependencies] -oauthlib = ">=3.0.0" -requests = ">=2.0.0" - -[package.extras] -rsa = ["oauthlib[signedtoken] (>=3.0.0)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "restructuredtext-lint" -version = "1.3.2" -description = "reStructuredText linter" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -docutils = ">=0.11,<1.0" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "ruamel.yaml" -version = "0.17.17" -description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" -category = "main" -optional = false -python-versions = ">=3" - -[package.dependencies] -"ruamel.yaml.clib" = {version = ">=0.1.2", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.10\""} - -[package.extras] -docs = ["ryd"] -jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "ruamel.yaml.clib" -version = "0.2.6" -description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" -category = "main" -optional = false -python-versions = ">=3.5" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "rules" -version = "3.0" -description = "Awesome Django authorization, without the database" -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "s3transfer" -version = "0.5.0" -description = "An Amazon S3 Transfer Manager" -category = "main" -optional = true -python-versions = ">= 3.6" - -[package.dependencies] -botocore = ">=1.12.36,<2.0a.0" - -[package.extras] -crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "safety" -version = "1.10.3" -description = "Checks installed dependencies for known vulnerabilities." -category = "dev" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -Click = ">=6.0" -dparse = ">=0.5.1" -packaging = "*" -requests = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "scramp" -version = "1.4.1" -description = "An implementation of the SCRAM protocol." -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -asn1crypto = ">=1.4.0" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "selenium" -version = "4.1.0" -description = "" -category = "dev" -optional = false -python-versions = "~=3.7" - -[package.dependencies] -trio = ">=0.17,<1.0" -trio-websocket = ">=0.9,<1.0" -urllib3 = {version = ">=1.26,<2.0", extras = ["secure"]} - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "sentry-sdk" -version = "1.5.0" -description = "Python client for Sentry (https://sentry.io)" -category = "main" -optional = true -python-versions = "*" - -[package.dependencies] -certifi = "*" -urllib3 = ">=1.10.0" - -[package.extras] -aiohttp = ["aiohttp (>=3.5)"] -beam = ["apache-beam (>=2.12)"] -bottle = ["bottle (>=0.12.13)"] -celery = ["celery (>=3)"] -chalice = ["chalice (>=1.16.0)"] -django = ["django (>=1.8)"] -falcon = ["falcon (>=1.4)"] -flask = ["flask (>=0.11)", "blinker (>=1.1)"] -httpx = ["httpx (>=0.16.0)"] -pure_eval = ["pure-eval", "executing", "asttokens"] -pyspark = ["pyspark (>=2.4.4)"] -rq = ["rq (>=0.6)"] -sanic = ["sanic (>=0.8)"] -sqlalchemy = ["sqlalchemy (>=1.2)"] -tornado = ["tornado (>=5)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "six" -version = "1.16.0" -description = "Python 2 and 3 compatibility utilities" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "smmap" -version = "5.0.0" -description = "A pure Python implementation of a sliding window memory map manager" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "sniffio" -version = "1.2.0" -description = "Sniff out which async library your code is running under" -category = "dev" -optional = false -python-versions = ">=3.5" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "snowballstemmer" -version = "2.2.0" -description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." -category = "dev" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "sortedcontainers" -version = "2.4.0" -description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" -category = "dev" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "soupsieve" -version = "2.3.1" -description = "A modern CSS selector implementation for Beautiful Soup." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "spdx-license-list" -version = "0.5.2" -description = "A simple tool/library for working with SPDX license definitions." -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "sphinx" -version = "3.5.4" -description = "Python documentation generator" -category = "dev" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -alabaster = ">=0.7,<0.8" -babel = ">=1.3" -colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""} -docutils = ">=0.12,<0.17" -imagesize = "*" -Jinja2 = ">=2.3" -packaging = "*" -Pygments = ">=2.0" -requests = ">=2.5.0" -snowballstemmer = ">=1.1" -sphinxcontrib-applehelp = "*" -sphinxcontrib-devhelp = "*" -sphinxcontrib-htmlhelp = "*" -sphinxcontrib-jsmath = "*" -sphinxcontrib-qthelp = "*" -sphinxcontrib-serializinghtml = "*" - -[package.extras] -docs = ["sphinxcontrib-websupport"] -lint = ["flake8 (>=3.5.0)", "isort", "mypy (>=0.800)", "docutils-stubs"] -test = ["pytest", "pytest-cov", "html5lib", "cython", "typed-ast"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "sphinx-autodoc-typehints" -version = "1.12.0" -description = "Type hints (PEP 484) support for the Sphinx autodoc extension" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -Sphinx = ">=3.0" - -[package.extras] -test = ["pytest (>=3.1.0)", "typing-extensions (>=3.5)", "sphobjinv (>=2.0)", "Sphinx (>=3.2.0)", "dataclasses"] -type_comments = ["typed-ast (>=1.4.0)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "sphinx-materialdesign-theme" -version = "0.1.11" -description = "Sphinx Material Design Theme" -category = "dev" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "sphinxcontrib-applehelp" -version = "1.0.2" -description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" -category = "dev" -optional = false -python-versions = ">=3.5" - -[package.extras] -lint = ["flake8", "mypy", "docutils-stubs"] -test = ["pytest"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "sphinxcontrib-devhelp" -version = "1.0.2" -description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." -category = "dev" -optional = false -python-versions = ">=3.5" - -[package.extras] -lint = ["flake8", "mypy", "docutils-stubs"] -test = ["pytest"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "sphinxcontrib-django" -version = "0.5.1" -description = "Improve the Sphinx autodoc for Django classes." -category = "dev" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "sphinxcontrib-htmlhelp" -version = "2.0.0" -description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.extras] -lint = ["flake8", "mypy", "docutils-stubs"] -test = ["pytest", "html5lib"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "sphinxcontrib-jsmath" -version = "1.0.1" -description = "A sphinx extension which renders display math in HTML via JavaScript" -category = "dev" -optional = false -python-versions = ">=3.5" - -[package.extras] -test = ["pytest", "flake8", "mypy"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "sphinxcontrib-qthelp" -version = "1.0.3" -description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." -category = "dev" -optional = false -python-versions = ">=3.5" - -[package.extras] -lint = ["flake8", "mypy", "docutils-stubs"] -test = ["pytest"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "sphinxcontrib-serializinghtml" -version = "1.1.5" -description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." -category = "dev" -optional = false -python-versions = ">=3.5" - -[package.extras] -lint = ["flake8", "mypy", "docutils-stubs"] -test = ["pytest"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "sqlparse" -version = "0.4.2" -description = "A non-validating SQL parser." -category = "main" -optional = false -python-versions = ">=3.5" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "stevedore" -version = "3.5.0" -description = "Manage dynamic plugins for Python applications" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -pbr = ">=2.0.0,<2.1.0 || >2.1.0" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "svglib" -version = "1.1.0" -description = "A pure-Python library for reading and converting SVG" -category = "main" -optional = false -python-versions = ">=3" - -[package.dependencies] -cssselect2 = ">=0.2.0" -lxml = "*" -reportlab = "*" -tinycss2 = ">=0.6.0" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "termcolor" -version = "1.1.0" -description = "ANSII Color formatting for output in terminal." -category = "dev" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "testfixtures" -version = "6.18.3" -description = "A collection of helpers and mock objects for unit tests and doc tests." -category = "dev" -optional = false -python-versions = "*" - -[package.extras] -build = ["setuptools-git", "wheel", "twine"] -docs = ["sphinx", "zope.component", "sybil", "twisted", "mock", "django (<2)", "django"] -test = ["pytest (>=3.6)", "pytest-cov", "pytest-django", "zope.component", "sybil", "twisted", "mock", "django (<2)", "django"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "testing.common.database" -version = "2.0.3" -description = "utilities for testing.* packages" -category = "dev" -optional = false -python-versions = "*" - -[package.extras] -testing = ["nose"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "testing.postgresql" -version = "1.3.0" -description = "automatically setups a postgresql instance in a temporary directory, and destroys it after testing" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -pg8000 = ">=1.10" -"testing.common.database" = "*" - -[package.extras] -testing = ["sqlalchemy", "nose", "psycopg2"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "tinycss2" -version = "1.1.1" -description = "A tiny CSS parser" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -webencodings = ">=0.4" - -[package.extras] -doc = ["sphinx", "sphinx-rtd-theme"] -test = ["pytest", "pytest-cov", "pytest-flake8", "pytest-isort", "coverage"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -category = "main" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "tomli" -version = "1.2.2" -description = "A lil' TOML parser" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "traitlets" -version = "5.1.1" -description = "Traitlets Python configuration system" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.extras] -test = ["pytest"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "trio" -version = "0.19.0" -description = "A friendly Python library for async concurrency and I/O" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -async-generator = ">=1.9" -attrs = ">=19.2.0" -cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""} -idna = "*" -outcome = "*" -sniffio = "*" -sortedcontainers = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "trio-websocket" -version = "0.9.2" -description = "WebSocket library for Trio" -category = "dev" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -async-generator = ">=1.10" -trio = ">=0.11" -wsproto = ">=0.14" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "twilio" -version = "7.3.2" -description = "Twilio API client and TwiML generator" -category = "main" -optional = false -python-versions = ">=3.6.0" - -[package.dependencies] -PyJWT = ">=2.0.0,<3.0.0" -pytz = "*" -requests = ">=2.0.0" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "types-pytz" -version = "2021.3.1" -description = "Typing stubs for pytz" -category = "dev" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "types-pyyaml" -version = "6.0.1" -description = "Typing stubs for PyYAML" -category = "dev" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "typing-extensions" -version = "4.0.1" -description = "Backported and Experimental Type Hints for Python 3.6+" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "urllib3" -version = "1.26.7" -description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" - -[package.dependencies] -certifi = {version = "*", optional = true, markers = "extra == \"secure\""} -cryptography = {version = ">=1.3.4", optional = true, markers = "extra == \"secure\""} -idna = {version = ">=2.0.0", optional = true, markers = "extra == \"secure\""} -pyOpenSSL = {version = ">=0.14", optional = true, markers = "extra == \"secure\""} - -[package.extras] -brotli = ["brotlipy (>=0.6.0)"] -secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "uwsgi" -version = "2.0.20" -description = "The uWSGI server" -category = "dev" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "vine" -version = "5.0.0" -description = "Promises, promises, promises." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "wcwidth" -version = "0.2.5" -description = "Measures the displayed width of unicode strings in a terminal" -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "webencodings" -version = "0.5.1" -description = "Character encoding aliases for legacy web content" -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "whoosh" -version = "2.7.4" -description = "Fast, pure-Python full text indexing, search, and spell checking library." -category = "main" -optional = false -python-versions = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "wrapt" -version = "1.13.3" -description = "Module for decorators, wrappers and monkey patching." -category = "main" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "wsproto" -version = "1.0.0" -description = "WebSockets state-machine based protocol implementation" -category = "dev" -optional = false -python-versions = ">=3.6.1" - -[package.dependencies] -h11 = ">=0.9.0,<1" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[[package]] -name = "yubiotp" -version = "1.0.0.post1" -description = "A library for verifying YubiKey OTP tokens, both locally and through a Yubico web service." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -pycryptodome = "*" - -[package.source] -type = "legacy" -url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" -reference = "gitlab" - -[extras] -ldap = ["django-auth-ldap"] -s3 = ["boto3", "django-storages"] -sentry = [] - -[metadata] -lock-version = "1.1" -python-versions = "^3.9" -content-hash = "37b5a1b20cbd6d2770c44fe0287022c3278081c7da4f0c08b5f97982d78ead4c" - -[metadata.files] -alabaster = [ - {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"}, - {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, -] -aleksis-builddeps = [ - {file = "AlekSIS-Builddeps-5+20211130152626.23302bab.tar.gz", hash = "sha256:bed0e9a4d00cf45f8cd75fcf059402c4b81525785ba2cb3d89c4cd6df907b58c"}, - {file = "AlekSIS_Builddeps-5+20211130152626.23302bab-py3-none-any.whl", hash = "sha256:023f594eb06667f747059c8d69a2058e195d4644644a09d747197f152ece9741"}, -] -amqp = [ - {file = "amqp-5.0.6-py3-none-any.whl", hash = "sha256:493a2ac6788ce270a2f6a765b017299f60c1998f5a8617908ee9be082f7300fb"}, - {file = "amqp-5.0.6.tar.gz", hash = "sha256:03e16e94f2b34c31f8bf1206d8ddd3ccaa4c315f7f6a1879b7b1210d229568c2"}, -] -appnope = [ - {file = "appnope-0.1.2-py2.py3-none-any.whl", hash = "sha256:93aa393e9d6c54c5cd570ccadd8edad61ea0c4b9ea7a01409020c9aa019eb442"}, - {file = "appnope-0.1.2.tar.gz", hash = "sha256:dd83cd4b5b460958838f6eb3000c660b1f9caf2a5b1de4264e941512f603258a"}, -] -asgiref = [ - {file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"}, - {file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"}, -] -asn1crypto = [ - {file = "asn1crypto-1.4.0-py2.py3-none-any.whl", hash = "sha256:4bcdf33c861c7d40bdcd74d8e4dd7661aac320fcdf40b9a3f95b4ee12fde2fa8"}, - {file = "asn1crypto-1.4.0.tar.gz", hash = "sha256:f4f6e119474e58e04a2b1af817eb585b4fd72bdd89b998624712b5c99be7641c"}, -] -async-generator = [ - {file = "async_generator-1.10-py3-none-any.whl", hash = "sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b"}, - {file = "async_generator-1.10.tar.gz", hash = "sha256:6ebb3d106c12920aaae42ccb6f787ef5eefdcdd166ea3d628fa8476abe712144"}, -] -atomicwrites = [ - {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, - {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, -] -attrs = [ - {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, - {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, -] -babel = [ - {file = "Babel-2.9.1-py2.py3-none-any.whl", hash = "sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9"}, - {file = "Babel-2.9.1.tar.gz", hash = "sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0"}, -] -backcall = [ - {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, - {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, -] -bandit = [ - {file = "bandit-1.7.1-py3-none-any.whl", hash = "sha256:f5acd838e59c038a159b5c621cf0f8270b279e884eadd7b782d7491c02add0d4"}, - {file = "bandit-1.7.1.tar.gz", hash = "sha256:a81b00b5436e6880fa8ad6799bc830e02032047713cbb143a12939ac67eb756c"}, -] -beautifulsoup4 = [ - {file = "beautifulsoup4-4.10.0-py3-none-any.whl", hash = "sha256:9a315ce70049920ea4572a4055bc4bd700c940521d36fc858205ad4fcde149bf"}, - {file = "beautifulsoup4-4.10.0.tar.gz", hash = "sha256:c23ad23c521d818955a4151a67d81580319d4bf548d3d49f4223ae041ff98891"}, -] -billiard = [ - {file = "billiard-3.6.4.0-py3-none-any.whl", hash = "sha256:87103ea78fa6ab4d5c751c4909bcff74617d985de7fa8b672cf8618afd5a875b"}, - {file = "billiard-3.6.4.0.tar.gz", hash = "sha256:299de5a8da28a783d51b197d496bef4f1595dd023a93a4f59dde1886ae905547"}, -] -black = [ - {file = "black-21.11b1-py3-none-any.whl", hash = "sha256:802c6c30b637b28645b7fde282ed2569c0cd777dbe493a41b6a03c1d903f99ac"}, - {file = "black-21.11b1.tar.gz", hash = "sha256:a042adbb18b3262faad5aff4e834ff186bb893f95ba3a8013f09de1e5569def2"}, -] -bleach = [ - {file = "bleach-4.1.0-py2.py3-none-any.whl", hash = "sha256:4d2651ab93271d1129ac9cbc679f524565cc8a1b791909c4a51eac4446a15994"}, - {file = "bleach-4.1.0.tar.gz", hash = "sha256:0900d8b37eba61a802ee40ac0061f8c2b5dee29c1927dd1d233e075ebf5a71da"}, -] -"boolean.py" = [ - {file = "boolean.py-3.8-py2.py3-none-any.whl", hash = "sha256:d75da0fd0354425fa64f6bbc6cec6ae1485d0eec3447b73187ff8cbf9b572e26"}, - {file = "boolean.py-3.8.tar.gz", hash = "sha256:cc24e20f985d60cd4a3a5a1c0956dd12611159d32a75081dabd0c9ab981acaa4"}, -] -boto3 = [ - {file = "boto3-1.20.17-py3-none-any.whl", hash = "sha256:b832c75386a4c5b7194acea1ae82dc309fddd69e660731350235d19cf70d8014"}, - {file = "boto3-1.20.17.tar.gz", hash = "sha256:41ea196ff71ee0255ad164790319ec158fd5048de915173e8b21226650a0512f"}, -] -botocore = [ - {file = "botocore-1.23.17-py3-none-any.whl", hash = "sha256:54240370476d8e67a97664d2c47df451f0e1d30e9d50ea0a88da4c2c27981159"}, - {file = "botocore-1.23.17.tar.gz", hash = "sha256:a9753b5220b5cc1bb8078086dc8ee10aa7da482b279dd0347965e9145a557003"}, -] -bs4 = [ - {file = "bs4-0.0.1.tar.gz", hash = "sha256:36ecea1fd7cc5c0c6e4a1ff075df26d50da647b75376626cc186e2212886dd3a"}, -] -calendarweek = [ - {file = "calendarweek-0.5.0-py3-none-any.whl", hash = "sha256:f2003e6e0264d3d1320fc99ae6d70e60174c2664e5640c6aa31ad38e229d942d"}, - {file = "calendarweek-0.5.0.tar.gz", hash = "sha256:32f5c8663799a2f5a0b8909976c7a3ae77397acd7e7c31d1456ece5b452988a5"}, -] -celery = [ - {file = "celery-5.1.2-py3-none-any.whl", hash = "sha256:9dab2170b4038f7bf10ef2861dbf486ddf1d20592290a1040f7b7a1259705d42"}, - {file = "celery-5.1.2.tar.gz", hash = "sha256:8d9a3de9162965e97f8e8cc584c67aad83b3f7a267584fa47701ed11c3e0d4b0"}, -] -celery-haystack-ng = [ - {file = "celery-haystack-ng-0.20.post2.tar.gz", hash = "sha256:d2e077851f13dddc36fc86134c7c8a937e46ae75e576eb8e77e03b03977fc7bb"}, - {file = "celery_haystack_ng-0.20.post2-py2.py3-none-any.whl", hash = "sha256:a13e00f2c29411b06c6cdf59ad6a90b6c158e3384e7ec6d6d64f6a69e8ff299a"}, -] -celery-progress = [ - {file = "celery-progress-0.1.1.tar.gz", hash = "sha256:b2622d1b410a763412810f0293153c984f4a0220b76769bd701b5b45e583ddad"}, - {file = "celery_progress-0.1.1-py3-none-any.whl", hash = "sha256:36a1e58b4408c9bf6aa63908204b50960b005db8e13f3c94ce6f8d6a2a4d4a6c"}, -] -certifi = [ - {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, - {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, -] -cffi = [ - {file = "cffi-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962"}, - {file = "cffi-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0"}, - {file = "cffi-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14"}, - {file = "cffi-1.15.0-cp27-cp27m-win32.whl", hash = "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474"}, - {file = "cffi-1.15.0-cp27-cp27m-win_amd64.whl", hash = "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6"}, - {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27"}, - {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023"}, - {file = "cffi-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2"}, - {file = "cffi-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382"}, - {file = "cffi-1.15.0-cp310-cp310-win32.whl", hash = "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55"}, - {file = "cffi-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0"}, - {file = "cffi-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605"}, - {file = "cffi-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e"}, - {file = "cffi-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc"}, - {file = "cffi-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7"}, - {file = "cffi-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66"}, - {file = "cffi-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029"}, - {file = "cffi-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6"}, - {file = "cffi-1.15.0-cp38-cp38-win32.whl", hash = "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c"}, - {file = "cffi-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443"}, - {file = "cffi-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a"}, - {file = "cffi-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8"}, - {file = "cffi-1.15.0-cp39-cp39-win32.whl", hash = "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a"}, - {file = "cffi-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139"}, - {file = "cffi-1.15.0.tar.gz", hash = "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954"}, -] -charset-normalizer = [ - {file = "charset-normalizer-2.0.8.tar.gz", hash = "sha256:735e240d9a8506778cd7a453d97e817e536bb1fc29f4f6961ce297b9c7a917b0"}, - {file = "charset_normalizer-2.0.8-py3-none-any.whl", hash = "sha256:83fcdeb225499d6344c8f7f34684c2981270beacc32ede2e669e94f7fa544405"}, -] -click = [ - {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, - {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, -] -click-didyoumean = [ - {file = "click-didyoumean-0.3.0.tar.gz", hash = "sha256:f184f0d851d96b6d29297354ed981b7dd71df7ff500d82fa6d11f0856bee8035"}, - {file = "click_didyoumean-0.3.0-py3-none-any.whl", hash = "sha256:a0713dc7a1de3f06bc0df5a9567ad19ead2d3d5689b434768a6145bff77c0667"}, -] -click-plugins = [ - {file = "click-plugins-1.1.1.tar.gz", hash = "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b"}, - {file = "click_plugins-1.1.1-py2.py3-none-any.whl", hash = "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8"}, -] -click-repl = [ - {file = "click-repl-0.2.0.tar.gz", hash = "sha256:cd12f68d745bf6151210790540b4cb064c7b13e571bc64b6957d98d120dacfd8"}, - {file = "click_repl-0.2.0-py3-none-any.whl", hash = "sha256:94b3fbbc9406a236f176e0506524b2937e4b23b6f4c0c0b2a0a83f8a64e9194b"}, -] -colorama = [ - {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, - {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, -] -colour = [ - {file = "colour-0.1.5-py2.py3-none-any.whl", hash = "sha256:33f6db9d564fadc16e59921a56999b79571160ce09916303d35346dddc17978c"}, - {file = "colour-0.1.5.tar.gz", hash = "sha256:af20120fefd2afede8b001fbef2ea9da70ad7d49fafdb6489025dae8745c3aee"}, -] -configobj = [ - {file = "configobj-5.0.6.tar.gz", hash = "sha256:a2f5650770e1c87fb335af19a9b7eb73fc05ccf22144eb68db7d00cd2bcb0902"}, -] -coverage = [ - {file = "coverage-6.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6dbc1536e105adda7a6312c778f15aaabe583b0e9a0b0a324990334fd458c94b"}, - {file = "coverage-6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:174cf9b4bef0db2e8244f82059a5a72bd47e1d40e71c68ab055425172b16b7d0"}, - {file = "coverage-6.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:92b8c845527eae547a2a6617d336adc56394050c3ed8a6918683646328fbb6da"}, - {file = "coverage-6.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c7912d1526299cb04c88288e148c6c87c0df600eca76efd99d84396cfe00ef1d"}, - {file = "coverage-6.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5d2033d5db1d58ae2d62f095e1aefb6988af65b4b12cb8987af409587cc0739"}, - {file = "coverage-6.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3feac4084291642165c3a0d9eaebedf19ffa505016c4d3db15bfe235718d4971"}, - {file = "coverage-6.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:276651978c94a8c5672ea60a2656e95a3cce2a3f31e9fb2d5ebd4c215d095840"}, - {file = "coverage-6.2-cp310-cp310-win32.whl", hash = "sha256:f506af4f27def639ba45789fa6fde45f9a217da0be05f8910458e4557eed020c"}, - {file = "coverage-6.2-cp310-cp310-win_amd64.whl", hash = "sha256:3f7c17209eef285c86f819ff04a6d4cbee9b33ef05cbcaae4c0b4e8e06b3ec8f"}, - {file = "coverage-6.2-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:13362889b2d46e8d9f97c421539c97c963e34031ab0cb89e8ca83a10cc71ac76"}, - {file = "coverage-6.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:22e60a3ca5acba37d1d4a2ee66e051f5b0e1b9ac950b5b0cf4aa5366eda41d47"}, - {file = "coverage-6.2-cp311-cp311-win_amd64.whl", hash = "sha256:b637c57fdb8be84e91fac60d9325a66a5981f8086c954ea2772efe28425eaf64"}, - {file = "coverage-6.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f467bbb837691ab5a8ca359199d3429a11a01e6dfb3d9dcc676dc035ca93c0a9"}, - {file = "coverage-6.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2641f803ee9f95b1f387f3e8f3bf28d83d9b69a39e9911e5bfee832bea75240d"}, - {file = "coverage-6.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1219d760ccfafc03c0822ae2e06e3b1248a8e6d1a70928966bafc6838d3c9e48"}, - {file = "coverage-6.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9a2b5b52be0a8626fcbffd7e689781bf8c2ac01613e77feda93d96184949a98e"}, - {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8e2c35a4c1f269704e90888e56f794e2d9c0262fb0c1b1c8c4ee44d9b9e77b5d"}, - {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:5d6b09c972ce9200264c35a1d53d43ca55ef61836d9ec60f0d44273a31aa9f17"}, - {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e3db840a4dee542e37e09f30859f1612da90e1c5239a6a2498c473183a50e781"}, - {file = "coverage-6.2-cp36-cp36m-win32.whl", hash = "sha256:4e547122ca2d244f7c090fe3f4b5a5861255ff66b7ab6d98f44a0222aaf8671a"}, - {file = "coverage-6.2-cp36-cp36m-win_amd64.whl", hash = "sha256:01774a2c2c729619760320270e42cd9e797427ecfddd32c2a7b639cdc481f3c0"}, - {file = "coverage-6.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fb8b8ee99b3fffe4fd86f4c81b35a6bf7e4462cba019997af2fe679365db0c49"}, - {file = "coverage-6.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:619346d57c7126ae49ac95b11b0dc8e36c1dd49d148477461bb66c8cf13bb521"}, - {file = "coverage-6.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0a7726f74ff63f41e95ed3a89fef002916c828bb5fcae83b505b49d81a066884"}, - {file = "coverage-6.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cfd9386c1d6f13b37e05a91a8583e802f8059bebfccde61a418c5808dea6bbfa"}, - {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:17e6c11038d4ed6e8af1407d9e89a2904d573be29d51515f14262d7f10ef0a64"}, - {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c254b03032d5a06de049ce8bca8338a5185f07fb76600afff3c161e053d88617"}, - {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dca38a21e4423f3edb821292e97cec7ad38086f84313462098568baedf4331f8"}, - {file = "coverage-6.2-cp37-cp37m-win32.whl", hash = "sha256:600617008aa82032ddeace2535626d1bc212dfff32b43989539deda63b3f36e4"}, - {file = "coverage-6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:bf154ba7ee2fd613eb541c2bc03d3d9ac667080a737449d1a3fb342740eb1a74"}, - {file = "coverage-6.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f9afb5b746781fc2abce26193d1c817b7eb0e11459510fba65d2bd77fe161d9e"}, - {file = "coverage-6.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edcada2e24ed68f019175c2b2af2a8b481d3d084798b8c20d15d34f5c733fa58"}, - {file = "coverage-6.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a9c8c4283e17690ff1a7427123ffb428ad6a52ed720d550e299e8291e33184dc"}, - {file = "coverage-6.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f614fc9956d76d8a88a88bb41ddc12709caa755666f580af3a688899721efecd"}, - {file = "coverage-6.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9365ed5cce5d0cf2c10afc6add145c5037d3148585b8ae0e77cc1efdd6aa2953"}, - {file = "coverage-6.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8bdfe9ff3a4ea37d17f172ac0dff1e1c383aec17a636b9b35906babc9f0f5475"}, - {file = "coverage-6.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:63c424e6f5b4ab1cf1e23a43b12f542b0ec2e54f99ec9f11b75382152981df57"}, - {file = "coverage-6.2-cp38-cp38-win32.whl", hash = "sha256:49dbff64961bc9bdd2289a2bda6a3a5a331964ba5497f694e2cbd540d656dc1c"}, - {file = "coverage-6.2-cp38-cp38-win_amd64.whl", hash = "sha256:9a29311bd6429be317c1f3fe4bc06c4c5ee45e2fa61b2a19d4d1d6111cb94af2"}, - {file = "coverage-6.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03b20e52b7d31be571c9c06b74746746d4eb82fc260e594dc662ed48145e9efd"}, - {file = "coverage-6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:215f8afcc02a24c2d9a10d3790b21054b58d71f4b3c6f055d4bb1b15cecce685"}, - {file = "coverage-6.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a4bdeb0a52d1d04123b41d90a4390b096f3ef38eee35e11f0b22c2d031222c6c"}, - {file = "coverage-6.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c332d8f8d448ded473b97fefe4a0983265af21917d8b0cdcb8bb06b2afe632c3"}, - {file = "coverage-6.2-cp39-cp39-win32.whl", hash = "sha256:6e1394d24d5938e561fbeaa0cd3d356207579c28bd1792f25a068743f2d5b282"}, - {file = "coverage-6.2-cp39-cp39-win_amd64.whl", hash = "sha256:86f2e78b1eff847609b1ca8050c9e1fa3bd44ce755b2ec30e70f2d3ba3844644"}, - {file = "coverage-6.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:5829192582c0ec8ca4a2532407bc14c2f338d9878a10442f5d03804a95fac9de"}, - {file = "coverage-6.2.tar.gz", hash = "sha256:e2cad8093172b7d1595b4ad66f24270808658e11acf43a8f95b41276162eb5b8"}, -] -cryptography = [ - {file = "cryptography-36.0.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:9511416e85e449fe1de73f7f99b21b3aa04fba4c4d335d30c486ba3756e3a2a6"}, - {file = "cryptography-36.0.0-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:97199a13b772e74cdcdb03760c32109c808aff7cd49c29e9cf4b7754bb725d1d"}, - {file = "cryptography-36.0.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:494106e9cd945c2cadfce5374fa44c94cfadf01d4566a3b13bb487d2e6c7959e"}, - {file = "cryptography-36.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6fbbbb8aab4053fa018984bb0e95a16faeb051dd8cca15add2a27e267ba02b58"}, - {file = "cryptography-36.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:684993ff6f67000a56454b41bdc7e015429732d65a52d06385b6e9de6181c71e"}, - {file = "cryptography-36.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c702855cd3174666ef0d2d13dcc879090aa9c6c38f5578896407a7028f75b9f"}, - {file = "cryptography-36.0.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d91bc9f535599bed58f6d2e21a2724cb0c3895bf41c6403fe881391d29096f1d"}, - {file = "cryptography-36.0.0-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:b17d83b3d1610e571fedac21b2eb36b816654d6f7496004d6a0d32f99d1d8120"}, - {file = "cryptography-36.0.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:8982c19bb90a4fa2aad3d635c6d71814e38b643649b4000a8419f8691f20ac44"}, - {file = "cryptography-36.0.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:24469d9d33217ffd0ce4582dfcf2a76671af115663a95328f63c99ec7ece61a4"}, - {file = "cryptography-36.0.0-cp36-abi3-win32.whl", hash = "sha256:f6a5a85beb33e57998dc605b9dbe7deaa806385fdf5c4810fb849fcd04640c81"}, - {file = "cryptography-36.0.0-cp36-abi3-win_amd64.whl", hash = "sha256:2deab5ec05d83ddcf9b0916319674d3dae88b0e7ee18f8962642d3cde0496568"}, - {file = "cryptography-36.0.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2049f8b87f449fc6190350de443ee0c1dd631f2ce4fa99efad2984de81031681"}, - {file = "cryptography-36.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a776bae1629c8d7198396fd93ec0265f8dd2341c553dc32b976168aaf0e6a636"}, - {file = "cryptography-36.0.0-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:aa94d617a4cd4cdf4af9b5af65100c036bce22280ebb15d8b5262e8273ebc6ba"}, - {file = "cryptography-36.0.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:5c49c9e8fb26a567a2b3fa0343c89f5d325447956cc2fc7231c943b29a973712"}, - {file = "cryptography-36.0.0-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ef216d13ac8d24d9cd851776662f75f8d29c9f2d05cdcc2d34a18d32463a9b0b"}, - {file = "cryptography-36.0.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:231c4a69b11f6af79c1495a0e5a85909686ea8db946935224b7825cfb53827ed"}, - {file = "cryptography-36.0.0-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:f92556f94e476c1b616e6daec5f7ddded2c082efa7cee7f31c7aeda615906ed8"}, - {file = "cryptography-36.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d73e3a96c38173e0aa5646c31bf8473bc3564837977dd480f5cbeacf1d7ef3a3"}, - {file = "cryptography-36.0.0.tar.gz", hash = "sha256:52f769ecb4ef39865719aedc67b4b7eae167bafa48dbc2a26dd36fa56460507f"}, -] -cssselect2 = [ - {file = "cssselect2-0.4.1-py3-none-any.whl", hash = "sha256:2f4a9f20965367bae459e3bb42561f7927e0cfe5b7ea1692757cf67ef5d7dace"}, - {file = "cssselect2-0.4.1.tar.gz", hash = "sha256:93fbb9af860e95dd40bf18c3b2b6ed99189a07c0f29ba76f9c5be71344664ec8"}, -] -curlylint = [ - {file = "curlylint-0.13.0-py3-none-any.whl", hash = "sha256:63e5fc98f99c7b0eab0c4e3390356ad569b7bb3eecb6da115e6cb9ee98eb738f"}, - {file = "curlylint-0.13.0.tar.gz", hash = "sha256:0d38839f126b3fdd2561a7efa65d15a1c842aac98e555b2381f7c79478e1ff25"}, -] -decorator = [ - {file = "decorator-5.1.0-py3-none-any.whl", hash = "sha256:7b12e7c3c6ab203a29e157335e9122cb03de9ab7264b137594103fd4a683b374"}, - {file = "decorator-5.1.0.tar.gz", hash = "sha256:e59913af105b9860aa2c8d3272d9de5a56a4e608db9a2f167a8480b323d529a7"}, -] -defusedxml = [ - {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, - {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, -] -deprecated = [ - {file = "Deprecated-1.2.13-py2.py3-none-any.whl", hash = "sha256:64756e3e14c8c5eea9795d93c524551432a0be75629f8f29e67ab8caf076c76d"}, - {file = "Deprecated-1.2.13.tar.gz", hash = "sha256:43ac5335da90c31c24ba028af536a91d41d53f9e6901ddb021bcc572ce44e38d"}, -] -dj-database-url = [ - {file = "dj-database-url-0.5.0.tar.gz", hash = "sha256:4aeaeb1f573c74835b0686a2b46b85990571159ffc21aa57ecd4d1e1cb334163"}, - {file = "dj_database_url-0.5.0-py2.py3-none-any.whl", hash = "sha256:851785365761ebe4994a921b433062309eb882fedd318e1b0fcecc607ed02da9"}, -] -django = [ - {file = "Django-3.2.9-py3-none-any.whl", hash = "sha256:e22c9266da3eec7827737cde57694d7db801fedac938d252bf27377cec06ed1b"}, - {file = "Django-3.2.9.tar.gz", hash = "sha256:51284300f1522ffcdb07ccbdf676a307c6678659e1284f0618e5a774127a6a08"}, -] -django-allauth = [ - {file = "django-allauth-0.46.0.tar.gz", hash = "sha256:8217b8dc46f85812ff209fc542f4bf378f1751cdbe867008169d4c85685df50d"}, -] -django-any-js = [ - {file = "django-any-js-1.1.tar.gz", hash = "sha256:2972946902ba049f73bf8bb87e0a0118f77a8c9dca89438f193598bff758422f"}, - {file = "django_any_js-1.1-py3-none-any.whl", hash = "sha256:1499934e293bbcaad29b8edaaefca87dda79eb3df1faeaaea67b80e2866ae1f8"}, -] -django-appconf = [ - {file = "django-appconf-1.0.5.tar.gz", hash = "sha256:be3db0be6c81fa84742000b89a81c016d70ae66a7ccb620cdef592b1f1a6aaa4"}, - {file = "django_appconf-1.0.5-py3-none-any.whl", hash = "sha256:ae9f864ee1958c815a965ed63b3fba4874eec13de10236ba063a788f9a17389d"}, -] -django-auth-ldap = [ - {file = "django-auth-ldap-3.0.0.tar.gz", hash = "sha256:1f2d5c562d9ba9a5e9a64099ae9798e1a63840a11afe4d1c4a9c74121f066eaa"}, - {file = "django_auth_ldap-3.0.0-py3-none-any.whl", hash = "sha256:19ee19034f344d9efd07ed88d3187e256ec33ae39d6a47222083b89f7d35c5f6"}, -] -django-bleach = [ - {file = "django-bleach-1.0.0.tar.gz", hash = "sha256:2586b90d641d4d7e70ee353570ad33d3625ed4b97036a3ea5b03ea1bb5bbeccd"}, - {file = "django_bleach-1.0.0-py2.py3-none-any.whl", hash = "sha256:60074a4f4bc8d5200fdb2e03dce16fb4913427698b64570bc3e1a7ea1b8c3cf7"}, -] -django-cachalot = [ - {file = "django-cachalot-2.4.4.tar.gz", hash = "sha256:8489a74e9a689437f81fa61705b154a4be3cac1b62b61f68215d79668c9ac037"}, - {file = "django_cachalot-2.4.4-py3-none-any.whl", hash = "sha256:f8995a85197ac290e63a2f97c577cc9825000fe081b08d5c7d35079e7f1daa43"}, -] -django-cache-memoize = [ - {file = "django-cache-memoize-0.1.10.tar.gz", hash = "sha256:63e8faa245a41c0dbad843807e9f21a6e59eba8e6e50df310fdf6485a6749843"}, - {file = "django_cache_memoize-0.1.10-py3-none-any.whl", hash = "sha256:676299313079cde9242ae84db0160e80b1d44e8dd6bc9b1f4f1247e11b30c9e0"}, -] -django-celery-beat = [ - {file = "django-celery-beat-2.2.1.tar.gz", hash = "sha256:97ae5eb309541551bdb07bf60cc57cadacf42a74287560ced2d2c06298620234"}, - {file = "django_celery_beat-2.2.1-py2.py3-none-any.whl", hash = "sha256:ab43049634fd18dc037927d7c2c7d5f67f95283a20ebbda55f42f8606412e66c"}, -] -django-celery-email = [ - {file = "django-celery-email-3.0.0.tar.gz", hash = "sha256:5546cbba80952cc3b8a0ffa4206ce90a4a996a7ffd1c385a2bdb65903ca18ece"}, - {file = "django_celery_email-3.0.0-py2.py3-none-any.whl", hash = "sha256:0f72da39cb2ea83c69440566e87f27cd72f68f247f98ce99fb29889fcf329406"}, -] -django-celery-results = [ - {file = "django_celery_results-2.2.0-py2.py3-none-any.whl", hash = "sha256:d5f83fad9091e52cd6dbb3ca80632153ad14b6cdac4d73258e040f92717237cb"}, - {file = "django_celery_results-2.2.0.tar.gz", hash = "sha256:cc0285090a306f97f1d4b7929ed98af0475bf6db2568976b3387de4fbe812edc"}, -] -django-ckeditor = [ - {file = "django-ckeditor-6.2.0.tar.gz", hash = "sha256:df64dc9e62790ef824f609605d31be847bdbce1cc7aa94e49bd5ca60d7aa79bb"}, - {file = "django_ckeditor-6.2.0-py2.py3-none-any.whl", hash = "sha256:9f66420907e41f5b4e698fa5671a00a86995776735f2c4696174aed4640fcbd8"}, -] -django-cleanup = [ - {file = "django-cleanup-5.2.0.tar.gz", hash = "sha256:909d10ff574f5ce1a40fa63bd5c94c9ed866fd7ae770994c46cdf66c3db3e846"}, - {file = "django_cleanup-5.2.0-py2.py3-none-any.whl", hash = "sha256:193cf69de54b9fc0a0f4547edbb3a63bbe01728cb029f9f4b7912098cc1bced7"}, -] -django-colorfield = [ - {file = "django-colorfield-0.5.0.tar.gz", hash = "sha256:670ef72ded093360c9781fedd33d9ead267b34481139d4ab240dfacea5cf0abf"}, - {file = "django_colorfield-0.5.0-py3-none-any.whl", hash = "sha256:aba49684ba1fce80af15237b49ca4a504e49e525c2897db2cce5705b2fa51f3b"}, -] -django-dbbackup = [ - {file = "django-dbbackup-3.3.0.tar.gz", hash = "sha256:bb109735cae98b64ad084e5b461b7aca2d7b39992f10c9ed9435e3ebb6fb76c8"}, -] -django-debug-toolbar = [ - {file = "django-debug-toolbar-3.2.2.tar.gz", hash = "sha256:8c5b13795d4040008ee69ba82dcdd259c49db346cf7d0de6e561a49d191f0860"}, - {file = "django_debug_toolbar-3.2.2-py3-none-any.whl", hash = "sha256:d7bab7573fab35b0fd029163371b7182f5826c13da69734beb675c761d06a4d3"}, -] -django-dynamic-preferences = [ - {file = "django-dynamic-preferences-1.11.0.tar.gz", hash = "sha256:f214c938b5872a17647e2b2ccfd9ad00a90a3c6c4aa83fa65d3c5c446e7a66c7"}, - {file = "django_dynamic_preferences-1.11.0-py2.py3-none-any.whl", hash = "sha256:31aecebcbfcfb970b78cfa3e5f8cc9f77638efe8e7c90f205a48b01c45ee5002"}, -] -django-extensions = [ - {file = "django-extensions-3.1.5.tar.gz", hash = "sha256:28e1e1bf49f0e00307ba574d645b0af3564c981a6dfc87209d48cb98f77d0b1a"}, - {file = "django_extensions-3.1.5-py3-none-any.whl", hash = "sha256:9238b9e016bb0009d621e05cf56ea8ce5cce9b32e91ad2026996a7377ca28069"}, -] -django-favicon-plus-reloaded = [ - {file = "django-favicon-plus-reloaded-1.1.3.tar.gz", hash = "sha256:36c2a1cefc201df8bd132492e2440ccdc3d9ceb8e421b2ca181a4704ebacd190"}, - {file = "django_favicon_plus_reloaded-1.1.3-py3-none-any.whl", hash = "sha256:a60b438360e82bf7075b856ff6a80bae20c825373a58deac627810e478c42be3"}, -] -django-filter = [ - {file = "django-filter-2.4.0.tar.gz", hash = "sha256:84e9d5bb93f237e451db814ed422a3a625751cbc9968b484ecc74964a8696b06"}, - {file = "django_filter-2.4.0-py3-none-any.whl", hash = "sha256:e00d32cebdb3d54273c48f4f878f898dced8d5dfaad009438fe61ebdf535ace1"}, -] -django-formtools = [ - {file = "django-formtools-2.3.tar.gz", hash = "sha256:9663b6eca64777b68d6d4142efad8597fe9a685924673b25aa8a1dcff4db00c3"}, - {file = "django_formtools-2.3-py3-none-any.whl", hash = "sha256:4699937e19ee041d803943714fe0c1c7ad4cab802600eb64bbf4cdd0a1bfe7d9"}, -] -django-guardian = [ - {file = "django-guardian-2.4.0.tar.gz", hash = "sha256:c58a68ae76922d33e6bdc0e69af1892097838de56e93e78a8361090bcd9f89a0"}, - {file = "django_guardian-2.4.0-py3-none-any.whl", hash = "sha256:440ca61358427e575323648b25f8384739e54c38b3d655c81d75e0cd0d61b697"}, -] -django-haystack = [ - {file = "django-haystack-3.1.1.tar.gz", hash = "sha256:6d05756b95d7d5ec1dbd4668eb999ced1504b47f588e2e54be53b1404c516a82"}, - {file = "django_haystack-3.1.1-py3-none-any.whl", hash = "sha256:970ebc6362f3f84861209154ec34b57f3e87d2d7922f948df80177f0e2e3ced7"}, -] -django-health-check = [ - {file = "django-health-check-3.16.4.tar.gz", hash = "sha256:334bcbbb9273a6dbd9c928e78474306e623dfb38cc442281cb9fd230a20a7fdb"}, - {file = "django_health_check-3.16.4-py2.py3-none-any.whl", hash = "sha256:86a8869d67e72394a1dd73e37819a7d2cfd915588b96927fda611d7451fd4735"}, -] -django-image-cropping = [ - {file = "django-image-cropping-1.6.1.tar.gz", hash = "sha256:bc5e34c3cbc28a79034a8ce20921e83b399ede087c99e3a1c699652b4214dc01"}, - {file = "django_image_cropping-1.6.1-py3-none-any.whl", hash = "sha256:da5c1c8cf0d83017a6e53d24eefd0e98cfcb84a61adb0154295827c88a37eb2a"}, -] -django-impersonate = [ - {file = "django-impersonate-1.7.3.tar.gz", hash = "sha256:282003957577c7143fe31e5861f8fffdf6fe0c25557aedb28fcf8b11474eaa23"}, -] -django-ipware = [ - {file = "django-ipware-4.0.0.tar.gz", hash = "sha256:1294f916f3b3475e40e1b0ec1bd320aa2397978eae672721c81cbc2ed517e9ee"}, - {file = "django_ipware-4.0.0-py2.py3-none-any.whl", hash = "sha256:116bd0d7940f09bf7ffd465943992e23d87e772a9d6c0d3a57b74040589a383b"}, -] -django-js-asset = [ - {file = "django-js-asset-1.2.2.tar.gz", hash = "sha256:c163ae80d2e0b22d8fb598047cd0dcef31f81830e127cfecae278ad574167260"}, - {file = "django_js_asset-1.2.2-py2.py3-none-any.whl", hash = "sha256:8ec12017f26eec524cab436c64ae73033368a372970af4cf42d9354fcb166bdd"}, -] -django-js-reverse = [ - {file = "django-js-reverse-0.9.1.tar.gz", hash = "sha256:2a392d169f44e30b883c30dfcfd917a14167ce8fe196c99d2385b31c90d77aa0"}, - {file = "django_js_reverse-0.9.1-py2.py3-none-any.whl", hash = "sha256:8134c2ab6307c945edfa90671ca65e85d6c1754d48566bdd6464be259cc80c30"}, -] -django-jsonstore = [ - {file = "django-jsonstore-0.5.0.tar.gz", hash = "sha256:896dc10b08f59807eda1c6cebf43cd26e50d0db29d13495c027dc31e464be3c3"}, - {file = "django_jsonstore-0.5.0-py2-none-any.whl", hash = "sha256:9630c1fb43ae9f8e32733c5cf7d4c3775ba6f08532f517c64025053352d72844"}, -] -django-maintenance-mode = [ - {file = "django-maintenance-mode-0.16.1.tar.gz", hash = "sha256:da1f77f431ab5c55913459adb3c259e091f783ffc72de701690826aaaccce4ca"}, - {file = "django_maintenance_mode-0.16.1-py3-none-any.whl", hash = "sha256:1bfac0b34429a9f6dbb0db169fb753f49f24ca155ae148d7526ff395303c158d"}, -] -django-material = [ - {file = "django-material-1.10.0.tar.gz", hash = "sha256:3cc015500939a63606c1522119fddc4c86facb6d1bbfa8fc76bdc8878e8252f5"}, - {file = "django_material-1.10.0-py2.py3-none-any.whl", hash = "sha256:50e4764fa0cb504cf1f6d497f86c6294ff3fbf43bdbf0e4c612e3681fa9000a0"}, -] -django-menu-generator-ng = [ - {file = "django-menu-generator-ng-1.2.3.tar.gz", hash = "sha256:0c21a094b094add909655728b6b2d4a8baa5a2047da8f649be52589bea0e3ba2"}, -] -django-model-utils = [ - {file = "django-model-utils-4.2.0.tar.gz", hash = "sha256:e7a95e102f9c9653427eadab980d5d59e1dea972913b9c9e01ac37f86bba0ddf"}, - {file = "django_model_utils-4.2.0-py3-none-any.whl", hash = "sha256:a768a25c80514e0ad4e4a6f9c02c44498985f36c5dfdea47b5b1e8cf994beba6"}, -] -django-oauth-toolkit = [ - {file = "django-oauth-toolkit-1.5.0.tar.gz", hash = "sha256:650e5ef2244d1d8db8f507137e0d1e8b8aad1f4086a4a610526e8851f9a38308"}, - {file = "django_oauth_toolkit-1.5.0-py3-none-any.whl", hash = "sha256:b2e346a7c1e222774bfb370f21b556b92b408395b4c23914e2d1b241b2e5376a"}, -] -django-otp = [ - {file = "django-otp-1.1.3.tar.gz", hash = "sha256:f002c71d4ea7f514590be00492980d3c87397b73dc20542e1c4fc00b66f2dda1"}, - {file = "django_otp-1.1.3-py3-none-any.whl", hash = "sha256:8637be826c0465d0fd1710e4472efe9fc83883853a2141fefdbace9358d20003"}, -] -django-otp-yubikey = [ - {file = "django-otp-yubikey-1.0.1.tar.gz", hash = "sha256:5917b9134fa408d12b94bdb4d3cac23e4586ae99c3a42fcb1d2c287c182e6c77"}, - {file = "django_otp_yubikey-1.0.1-py2.py3-none-any.whl", hash = "sha256:5a1b59be47088a3eccf376ca27d708bdcccfeb30324bb5ca01ed2d669b73756c"}, -] -django-phonenumber-field = [ - {file = "django-phonenumber-field-5.2.0.tar.gz", hash = "sha256:52b2e5970133ec5ab701218b802f7ab237229854dc95fd239b7e9e77dc43731d"}, - {file = "django_phonenumber_field-5.2.0-py3-none-any.whl", hash = "sha256:5547fb2b2cc690a306ba77a5038419afc8fa8298a486fb7895008e9067cc7e75"}, -] -django-polymorphic = [ - {file = "django-polymorphic-3.1.0.tar.gz", hash = "sha256:d6955b5308bf6e41dcb22ba7c96f00b51dfa497a8a5ab1e9c06c7951bf417bf8"}, - {file = "django_polymorphic-3.1.0-py3-none-any.whl", hash = "sha256:08bc4f4f4a773a19b2deced5a56deddd1ef56ebd15207bf4052e2901c25ef57e"}, -] -django-prometheus = [ - {file = "django-prometheus-2.1.0.tar.gz", hash = "sha256:dd3f8da1399140fbef5c00d1526a23d1ade286b144281c325f8e409a781643f2"}, - {file = "django_prometheus-2.1.0-py2.py3-none-any.whl", hash = "sha256:c338d6efde1ca336e90c540b5e87afe9287d7bcc82d651a778f302b0be17a933"}, -] -django-redis = [ - {file = "django-redis-5.1.0.tar.gz", hash = "sha256:98fb3d31633a1addea1aeb558a647359908bbcf78c0833f99496c5348fe3c1b4"}, - {file = "django_redis-5.1.0-py3-none-any.whl", hash = "sha256:bf75bce0d6f65c3a6165dd6789506c8d22238f3bfaf7c4ad447e55afbc5b68cb"}, -] -django-render-block = [ - {file = "django-render-block-0.8.1.tar.gz", hash = "sha256:edbc5d444cc50f3eb3387cf17f6f1014bf19d6018f680861cdeae9e0306003fa"}, - {file = "django_render_block-0.8.1-py3-none-any.whl", hash = "sha256:903969efd0949f750c5fe71affe6e6b1ea66d03005c102a67fda36d5b9f4e1e1"}, -] -django-reversion = [ - {file = "django-reversion-4.0.1.tar.gz", hash = "sha256:6991f16e5d3a972912db3d56e3a714d10b07becd566ab87f85f2e9b671981339"}, - {file = "django_reversion-4.0.1-py3-none-any.whl", hash = "sha256:2e40ed41e08cdd83a05dc70a1974feface52a61ba7d289727117163052081ae6"}, -] -django-sass-processor = [ - {file = "django-sass-processor-1.0.0.tar.gz", hash = "sha256:cb90efee38cd7b0fe727c78d8993ad7804de33f40328200dfc1a481307ef0466"}, -] -django-select2 = [ - {file = "django-select2-7.9.0.tar.gz", hash = "sha256:4494cf5fa13333ddbd34e4dbeca4b44a22ed6367342cccd24f6f122f6ef4a20b"}, - {file = "django_select2-7.9.0-py2.py3-none-any.whl", hash = "sha256:40d42643b459f79c31598fa5645f5f7e8edda8350a78761ab6c06105ca588872"}, -] -django-storages = [ - {file = "django-storages-1.12.3.tar.gz", hash = "sha256:a475edb2f0f04c4f7e548919a751ecd50117270833956ed5bd585c0575d2a5e7"}, - {file = "django_storages-1.12.3-py3-none-any.whl", hash = "sha256:204a99f218b747c46edbfeeb1310d357f83f90fa6a6024d8d0a3f422570cee84"}, -] -django-stubs = [ - {file = "django-stubs-1.9.0.tar.gz", hash = "sha256:664843091636a917faf5256d028476559dc360fdef9050b6df87ab61b21607bf"}, - {file = "django_stubs-1.9.0-py3-none-any.whl", hash = "sha256:59c9f81af64d214b1954eaf90f037778c8d2b9c2de946a3cda177fefcf588fbd"}, -] -django-stubs-ext = [ - {file = "django-stubs-ext-0.3.1.tar.gz", hash = "sha256:783c198d7e39a41be0b90fd843fa2770243a642922af679be4b19e03b82c8c28"}, - {file = "django_stubs_ext-0.3.1-py3-none-any.whl", hash = "sha256:a51a3e9e844d4e1cacaaedbb33bf3def78a3956eed5d9575a640bd97ccd99cec"}, -] -django-tables2 = [ - {file = "django-tables2-2.4.1.tar.gz", hash = "sha256:6c72dd208358539e789e4c0efd7d151e43283a4aa4093a35f44c43489e7ddeaa"}, - {file = "django_tables2-2.4.1-py2.py3-none-any.whl", hash = "sha256:50762bf3d7c61a4eb70e763c3e278650d7266bb78d0497fc8fafcf4e507c9a64"}, -] -django-templated-email = [ - {file = "django-templated-email-3.0.0.tar.gz", hash = "sha256:49d61840ec551e640adaf341146e94d6f9058ae01df964480850bf988046e5eb"}, - {file = "django_templated_email-3.0.0-py3-none-any.whl", hash = "sha256:bf1b68ffe6c8794c0c50e2ce20e3a166c6d511b3879abbd3cf059a3fc2fe2e60"}, -] -django-timezone-field = [ - {file = "django-timezone-field-4.2.1.tar.gz", hash = "sha256:97780cde658daa5094ae515bb55ca97c1352928ab554041207ad515dee3fe971"}, - {file = "django_timezone_field-4.2.1-py3-none-any.whl", hash = "sha256:6dc782e31036a58da35b553bd00c70f112d794700025270d8a6a4c1d2e5b26c6"}, -] -django-titofisto = [ - {file = "django-titofisto-0.2.0.tar.gz", hash = "sha256:e181081a8c9c5c8da9f15458d996624f9e19c98d2882a5d4f199b39dd0787ad6"}, - {file = "django_titofisto-0.2.0-py3-none-any.whl", hash = "sha256:38d5298fe64d3c12a3a48767d8f1af4bd86cfc12787af0faaf3e141a29a12bb8"}, -] -django-two-factor-auth = [ - {file = "django-two-factor-auth-1.13.1.tar.gz", hash = "sha256:a20e03d256fd9fd668988545f052cedcc47e5a981888562e5e27d0bb83deae89"}, - {file = "django_two_factor_auth-1.13.1-py2.py3-none-any.whl", hash = "sha256:d270d4288731233621a9462a89a8dfed2dcb86fa354125c816a89772d55f9e29"}, -] -django-uwsgi-ng = [ - {file = "django-uwsgi-ng-1.1.2.tar.gz", hash = "sha256:1df2ffa642f7a831bd8d7f7e459f7b0821113b37174ccf4bf977e4467d45d9b3"}, - {file = "django_uwsgi_ng-1.1.2-py3-none-any.whl", hash = "sha256:8b1a489a1ed9e56da0efadfa86ec306b532e5cd953fe34b234aaefc26898c649"}, -] -django-widget-tweaks = [ - {file = "django-widget-tweaks-1.4.9.tar.gz", hash = "sha256:19bcb66a4a9e68493ced04e7124882d753c5be517ed001556f9e35a40147f545"}, - {file = "django_widget_tweaks-1.4.9-py2.py3-none-any.whl", hash = "sha256:d6c64fbf92cd2df9031f597c1374982233c05a1190d295c39d1c57ce007569c7"}, -] -django-yarnpkg = [ - {file = "django-yarnpkg-6.0.1.tar.gz", hash = "sha256:aa059347b246c6f242401581d2c129bdcb45aa726be59fe2f288762a9843348a"}, -] -djangorestframework = [ - {file = "djangorestframework-3.12.4-py3-none-any.whl", hash = "sha256:6d1d59f623a5ad0509fe0d6bfe93cbdfe17b8116ebc8eda86d45f6e16e819aaf"}, - {file = "djangorestframework-3.12.4.tar.gz", hash = "sha256:f747949a8ddac876e879190df194b925c177cdeb725a099db1460872f7c0a7f2"}, -] -docutils = [ - {file = "docutils-0.16-py2.py3-none-any.whl", hash = "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af"}, - {file = "docutils-0.16.tar.gz", hash = "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc"}, -] -dparse = [ - {file = "dparse-0.5.1-py3-none-any.whl", hash = "sha256:e953a25e44ebb60a5c6efc2add4420c177f1d8404509da88da9729202f306994"}, - {file = "dparse-0.5.1.tar.gz", hash = "sha256:a1b5f169102e1c894f9a7d5ccf6f9402a836a5d24be80a986c7ce9eaed78f367"}, -] -dynaconf = [ - {file = "dynaconf-3.1.7-py2.py3-none-any.whl", hash = "sha256:f52fe5db7622da56a552275e8f64e4df46e3b4ae11158831b042e8ba2f6d1c96"}, - {file = "dynaconf-3.1.7.tar.gz", hash = "sha256:e9d80b46ba4d9372f2f40c812594c963f74178140c0b596e57f2881001fc4d35"}, -] -easy-thumbnails = [ - {file = "easy-thumbnails-2.8.tar.gz", hash = "sha256:fd2249d936671847fc54a2d6c8c87bcca8f803001967dd03bab6b8bcb7590825"}, - {file = "easy_thumbnails-2.8-py3-none-any.whl", hash = "sha256:f2a9b82b9ddd1b4342ef92009589d76e1dc61082970302b9bbb7510f054b4d77"}, -] -flake8 = [ - {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, - {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, -] -flake8-bandit = [ - {file = "flake8_bandit-2.1.2.tar.gz", hash = "sha256:687fc8da2e4a239b206af2e54a90093572a60d0954f3054e23690739b0b0de3b"}, -] -flake8-black = [ - {file = "flake8-black-0.2.3.tar.gz", hash = "sha256:c199844bc1b559d91195ebe8620216f21ed67f2cc1ff6884294c91a0d2492684"}, - {file = "flake8_black-0.2.3-py3-none-any.whl", hash = "sha256:cc080ba5b3773b69ba102b6617a00cc4ecbad8914109690cfda4d565ea435d96"}, -] -flake8-builtins = [ - {file = "flake8-builtins-1.5.3.tar.gz", hash = "sha256:09998853b2405e98e61d2ff3027c47033adbdc17f9fe44ca58443d876eb00f3b"}, - {file = "flake8_builtins-1.5.3-py2.py3-none-any.whl", hash = "sha256:7706babee43879320376861897e5d1468e396a40b8918ed7bccf70e5f90b8687"}, -] -flake8-django = [ - {file = "flake8-django-1.1.1.tar.gz", hash = "sha256:fb4e8f669d3cf44297bb6e1c5d0a358ab0aba373cd4c69268cf2798de6bcbd9b"}, - {file = "flake8_django-1.1.1-py3-none-any.whl", hash = "sha256:c71da0e61b6119dae91cbffdbdb00f1d6ebe3f5d0c43f5bf136929997ab0b72d"}, -] -flake8-docstrings = [ - {file = "flake8-docstrings-1.6.0.tar.gz", hash = "sha256:9fe7c6a306064af8e62a055c2f61e9eb1da55f84bb39caef2b84ce53708ac34b"}, - {file = "flake8_docstrings-1.6.0-py2.py3-none-any.whl", hash = "sha256:99cac583d6c7e32dd28bbfbef120a7c0d1b6dde4adb5a9fd441c4227a6534bde"}, -] -flake8-fixme = [ - {file = "flake8-fixme-1.1.1.tar.gz", hash = "sha256:50cade07d27a4c30d4f12351478df87339e67640c83041b664724bda6d16f33a"}, - {file = "flake8_fixme-1.1.1-py2.py3-none-any.whl", hash = "sha256:226a6f2ef916730899f29ac140bed5d4a17e5aba79f00a0e3ae1eff1997cb1ac"}, -] -flake8-isort = [ - {file = "flake8-isort-4.1.1.tar.gz", hash = "sha256:d814304ab70e6e58859bc5c3e221e2e6e71c958e7005239202fee19c24f82717"}, - {file = "flake8_isort-4.1.1-py3-none-any.whl", hash = "sha256:c4e8b6dcb7be9b71a02e6e5d4196cefcef0f3447be51e82730fb336fff164949"}, -] -flake8-mypy = [ - {file = "flake8-mypy-17.8.0.tar.gz", hash = "sha256:47120db63aff631ee1f84bac6fe8e64731dc66da3efc1c51f85e15ade4a3ba18"}, - {file = "flake8_mypy-17.8.0-py35.py36-none-any.whl", hash = "sha256:cff009f4250e8391bf48990093cff85802778c345c8449d6498b62efefeebcbc"}, -] -flake8-polyfill = [ - {file = "flake8-polyfill-1.0.2.tar.gz", hash = "sha256:e44b087597f6da52ec6393a709e7108b2905317d0c0b744cdca6208e670d8eda"}, - {file = "flake8_polyfill-1.0.2-py2.py3-none-any.whl", hash = "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9"}, -] -flake8-rst-docstrings = [ - {file = "flake8-rst-docstrings-0.2.3.tar.gz", hash = "sha256:3045794e1c8467fba33aaea5c246b8369efc9c44ef8b0b20199bb6df7a4bd47b"}, - {file = "flake8_rst_docstrings-0.2.3-py3-none-any.whl", hash = "sha256:565bbb391d7e4d0042924102221e9857ad72929cdd305b26501736ec22c1451a"}, -] -freezegun = [ - {file = "freezegun-1.1.0-py2.py3-none-any.whl", hash = "sha256:2ae695f7eb96c62529f03a038461afe3c692db3465e215355e1bb4b0ab408712"}, - {file = "freezegun-1.1.0.tar.gz", hash = "sha256:177f9dd59861d871e27a484c3332f35a6e3f5d14626f2bf91be37891f18927f3"}, -] -gitdb = [ - {file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"}, - {file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"}, -] -gitpython = [ - {file = "GitPython-3.1.24-py3-none-any.whl", hash = "sha256:dc0a7f2f697657acc8d7f89033e8b1ea94dd90356b2983bca89dc8d2ab3cc647"}, - {file = "GitPython-3.1.24.tar.gz", hash = "sha256:df83fdf5e684fef7c6ee2c02fc68a5ceb7e7e759d08b694088d0cacb4eba59e5"}, -] -h11 = [ - {file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"}, - {file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"}, -] -haystack-redis = [ - {file = "haystack-redis-0.0.1.tar.gz", hash = "sha256:ccfea88bdc1387c9f7f6f19e9bc062a3612039ef94cfd3e78cf59a96ddd269b2"}, - {file = "haystack_redis-0.0.1-py3-none-any.whl", hash = "sha256:4fdeee5a9d8daadb1fed4584fd2ffbb25b1ed2315dacb97b53093756d6b54467"}, -] -html2text = [ - {file = "html2text-2020.1.16-py3-none-any.whl", hash = "sha256:c7c629882da0cf377d66f073329ccf34a12ed2adf0169b9285ae4e63ef54c82b"}, - {file = "html2text-2020.1.16.tar.gz", hash = "sha256:e296318e16b059ddb97f7a8a1d6a5c1d7af4544049a01e261731d2d5cc277bbb"}, -] -idna = [ - {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, - {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, -] -imagesize = [ - {file = "imagesize-1.3.0-py2.py3-none-any.whl", hash = "sha256:1db2f82529e53c3e929e8926a1fa9235aa82d0bd0c580359c67ec31b2fddaa8c"}, - {file = "imagesize-1.3.0.tar.gz", hash = "sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d"}, -] -iniconfig = [ - {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, - {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, -] -ipython = [ - {file = "ipython-7.30.0-py3-none-any.whl", hash = "sha256:c8f3e07aefb9cf9e067f39686f035ce09b27a1ee602116a3030b91b6fc138ee4"}, - {file = "ipython-7.30.0.tar.gz", hash = "sha256:d41f8e80b99690122400f9b2069b12f670246a1b4cc5d332bd6c4e2500e6d6fb"}, -] -isort = [ - {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, - {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, -] -jedi = [ - {file = "jedi-0.18.1-py2.py3-none-any.whl", hash = "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d"}, - {file = "jedi-0.18.1.tar.gz", hash = "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab"}, -] -jinja2 = [ - {file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"}, - {file = "Jinja2-3.0.3.tar.gz", hash = "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"}, -] -jmespath = [ - {file = "jmespath-0.10.0-py2.py3-none-any.whl", hash = "sha256:cdf6525904cc597730141d61b36f2e4b8ecc257c420fa2f4549bac2c2d0cb72f"}, - {file = "jmespath-0.10.0.tar.gz", hash = "sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9"}, -] -jwcrypto = [ - {file = "jwcrypto-1.0-py2.py3-none-any.whl", hash = "sha256:db93a656d9a7a35dda5a68deb5c9f301f4e60507d8aef1559e0637b9ac497137"}, - {file = "jwcrypto-1.0.tar.gz", hash = "sha256:f88816eb0a41b8f006af978ced5f171f33782525006cdb055b536a40f4d46ac9"}, -] -kombu = [ - {file = "kombu-5.2.2-py3-none-any.whl", hash = "sha256:d36f0cde6a18d9eb7b6b3aa62a59bfdff7f5724689850e447eca5be8efc9d501"}, - {file = "kombu-5.2.2.tar.gz", hash = "sha256:0f5d0763fb916808f617b886697b2be28e6bc35026f08e679697fc814b48a608"}, -] -libsass = [ - {file = "libsass-0.21.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:06c8776417fe930714bdc930a3d7e795ae3d72be6ac883ff72a1b8f7c49e5ffb"}, - {file = "libsass-0.21.0-cp27-cp27m-win32.whl", hash = "sha256:a005f298f64624f313a3ac618ab03f844c71d84ae4f4a4aec4b68d2a4ffe75eb"}, - {file = "libsass-0.21.0-cp27-cp27m-win_amd64.whl", hash = "sha256:6b984510ed94993708c0d697b4fef2d118929bbfffc3b90037be0f5ccadf55e7"}, - {file = "libsass-0.21.0-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1e25dd9047a9392d3c59a0b869e0404f2b325a03871ee45285ee33b3664f5613"}, - {file = "libsass-0.21.0-cp36-abi3-macosx_10_14_x86_64.whl", hash = "sha256:12f39712de38689a8b785b7db41d3ba2ea1d46f9379d81ea4595802d91fa6529"}, - {file = "libsass-0.21.0-cp36-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e2b1a7d093f2e76dc694c17c0c285e846d0b0deb0e8b21dc852ba1a3a4e2f1d6"}, - {file = "libsass-0.21.0-cp36-abi3-win32.whl", hash = "sha256:abc29357ee540849faf1383e1746d40d69ed5cb6d4c346df276b258f5aa8977a"}, - {file = "libsass-0.21.0-cp36-abi3-win_amd64.whl", hash = "sha256:659ae41af8708681fa3ec73f47b9735a6725e71c3b66ff570bfce78952f2314e"}, - {file = "libsass-0.21.0.tar.gz", hash = "sha256:d5ba529d9ce668be9380563279f3ffe988f27bc5b299c5a28453df2e0b0fbaf2"}, -] -license-expression = [ - {file = "license-expression-21.6.14.tar.gz", hash = "sha256:9de87a427c9a449eee7913472fb9ed03b63036295547369fdbf95f76a8b924b2"}, - {file = "license_expression-21.6.14-py3-none-any.whl", hash = "sha256:324246eed8e138b4139fefdc0e9dc4161d5075e3929e56983966d37298dca30e"}, -] -lxml = [ - {file = "lxml-4.6.4-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:bbf2dc330bd44bfc0254ab37677ec60f7c7ecea55ad8ba1b8b2ea7bf20c265f5"}, - {file = "lxml-4.6.4-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b667c51682fe9b9788c69465956baa8b6999531876ccedcafc895c74ad716cd8"}, - {file = "lxml-4.6.4-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:72e730d33fe2e302fd07285f14624fca5e5e2fb2bb4fb2c3941e318c41c443d1"}, - {file = "lxml-4.6.4-cp27-cp27m-win32.whl", hash = "sha256:433df8c7dde0f9e41cbf4f36b0829d50a378116ef5e962ba3881f2f5f025c7be"}, - {file = "lxml-4.6.4-cp27-cp27m-win_amd64.whl", hash = "sha256:35752ee40f7bbf6adc9ff4e1f4b84794a3593736dcce80db32e3c2aa85e294ac"}, - {file = "lxml-4.6.4-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ff5bb2a198ea67403bb6818705e9a4f90e0313f2215428ec51001ce56d939fb"}, - {file = "lxml-4.6.4-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:9b87727561c1150c0cc91c5d9d389448b37a7d15f0ba939ed3d1acb2f11bf6c5"}, - {file = "lxml-4.6.4-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:45fdb2899c755138722797161547a40b3e2a06feda620cc41195ee7e97806d81"}, - {file = "lxml-4.6.4-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:38b9de0de3aa689fe9fb9877ae1be1e83b8cf9621f7e62049d0436b9ecf4ad64"}, - {file = "lxml-4.6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:662523cd2a0246740225c7e32531f2e766544122e58bee70e700a024cfc0cf81"}, - {file = "lxml-4.6.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:4aa349c5567651f34d4eaae7de6ed5b523f6d70a288f9c6fbac22d13a0784e04"}, - {file = "lxml-4.6.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:08eb9200d88b376a8ed5e50f1dc1d1a45b49305169674002a3b5929943390591"}, - {file = "lxml-4.6.4-cp310-cp310-win32.whl", hash = "sha256:bdc224f216ead849e902151112efef6e96c41ee1322e15d4e5f7c8a826929aee"}, - {file = "lxml-4.6.4-cp310-cp310-win_amd64.whl", hash = "sha256:ab6db93a2b6b66cbf62b4e4a7135f476e708e8c5c990d186584142c77d7f975a"}, - {file = "lxml-4.6.4-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:50790313df028aa05cf22be9a8da033b86c42fa32523e4fd944827b482b17bf0"}, - {file = "lxml-4.6.4-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6764998345552b1dfc9326a932d2bad6367c6b37a176bb73ada6b9486bf602f7"}, - {file = "lxml-4.6.4-cp35-cp35m-win32.whl", hash = "sha256:543b239b191bb3b6d9bef5f09f1fb2be5b7eb09ab4d386aa655e4d53fbe9ff47"}, - {file = "lxml-4.6.4-cp35-cp35m-win_amd64.whl", hash = "sha256:a75c1ad05eedb1a3ff2a34a52a4f0836cfaa892e12796ba39a7732c82701eff4"}, - {file = "lxml-4.6.4-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:47e955112ce64241fdb357acf0216081f9f3255b3ac9c502ca4b3323ec1ca558"}, - {file = "lxml-4.6.4-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:20d7c8d90d449c6a353b15ee0459abae8395dbe59ad01e406ccbf30cd81c6f98"}, - {file = "lxml-4.6.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:240db6f3228d26e3c6f4fad914b9ddaaf8707254e8b3efd564dc680c8ec3c264"}, - {file = "lxml-4.6.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:351482da8dd028834028537f08724b1de22d40dcf3bb723b469446564f409074"}, - {file = "lxml-4.6.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e678a643177c0e5ec947b645fa7bc84260dfb9b6bf8fb1fdd83008dfc2ca5928"}, - {file = "lxml-4.6.4-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:15d0381feb56f08f78c5cc4fc385ddfe0bde1456e37f54a9322833371aec4060"}, - {file = "lxml-4.6.4-cp36-cp36m-win32.whl", hash = "sha256:4ba74afe5ee5cb5e28d83b513a6e8f0875fda1dc1a9aea42cc0065f029160d2a"}, - {file = "lxml-4.6.4-cp36-cp36m-win_amd64.whl", hash = "sha256:9c91a73971a922c13070fd8fa5a114c858251791ba2122a941e6aa781c713e44"}, - {file = "lxml-4.6.4-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:6020c70ff695106bf80651953a23e37718ef1fee9abd060dcad8e32ab2dc13f3"}, - {file = "lxml-4.6.4-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:f5dd358536b8a964bf6bd48de038754c1609e72e5f17f5d21efe2dda17594dbf"}, - {file = "lxml-4.6.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:7ae7089d81fc502df4b217ad77f03c54039fe90dac0acbe70448d7e53bfbc57e"}, - {file = "lxml-4.6.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:80d10d53d3184837445ff8562021bdd37f57c4cadacbf9d8726cc16220a00d54"}, - {file = "lxml-4.6.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e95da348d57eb448d226a44b868ff2ca5786fbcbe417ac99ff62d0a7d724b9c7"}, - {file = "lxml-4.6.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ffd65cfa33fed01735c82aca640fde4cc63f0414775cba11e06f84fae2085a6e"}, - {file = "lxml-4.6.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:877666418598f6cb289546c77ff87590cfd212f903b522b0afa0b9fb73b3ccfb"}, - {file = "lxml-4.6.4-cp37-cp37m-win32.whl", hash = "sha256:e91d24623e747eeb2d8121f4a94c6a7ad27dc48e747e2dc95bfe88632bd028a2"}, - {file = "lxml-4.6.4-cp37-cp37m-win_amd64.whl", hash = "sha256:4ec9a80dd5704ecfde54319b6964368daf02848c8954d3bacb9b64d1c7659159"}, - {file = "lxml-4.6.4-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:2901625f4a878a055d275beedc20ba9cb359cefc4386a967222fee29eb236038"}, - {file = "lxml-4.6.4-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:b567178a74a2261345890eac66fbf394692a6e002709d329f28a673ca6042473"}, - {file = "lxml-4.6.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:4717123f7c11c81e0da69989e5a64079c3f402b0efeb4c6241db6c369d657bd8"}, - {file = "lxml-4.6.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:cf201bf5594d1aab139fe53e3fca457e4f8204a5bbd65d48ab3b82a16f517868"}, - {file = "lxml-4.6.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a77a3470ba37e11872c75ca95baf9b3312133a3d5a5dc720803b23098c653976"}, - {file = "lxml-4.6.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:619c6d2b552bba00491e96c0518aad94002651c108a0f7364ff2d7798812c00e"}, - {file = "lxml-4.6.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:601f0ab75538b280aaf1e720eb9d68d4fa104ac274e1e9e6971df488f4dcdb0f"}, - {file = "lxml-4.6.4-cp38-cp38-win32.whl", hash = "sha256:75d3c5bbc0ddbad03bb68b9be638599f67e4b98ed3dcd0fec9f6f39e41ee96cb"}, - {file = "lxml-4.6.4-cp38-cp38-win_amd64.whl", hash = "sha256:4341d135f5660db10184963d9c3418c3e28d7f868aaf8b11a323ebf85813f7f4"}, - {file = "lxml-4.6.4-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:9db24803fa71e3305fe4a7812782b708da21a0b774b130dd1860cf40a6d7a3ee"}, - {file = "lxml-4.6.4-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:afd60230ad9d8bcba005945ec3a343722f09e0b7f8ae804246e5d2cfc6bd71a6"}, - {file = "lxml-4.6.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:0c15e1cd55055956e77b0732270f1c6005850696bc3ef3e03d01e78af84eaa42"}, - {file = "lxml-4.6.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:6d422b3c729737d8a39279a25fa156c983a56458f8b2f97661ee6fb22b80b1d6"}, - {file = "lxml-4.6.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2eb90f6ec3c236ef2f1bb38aee7c0d23e77d423d395af6326e7cca637519a4cb"}, - {file = "lxml-4.6.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:51a0e5d243687596f46e24e464121d4b232ad772e2d1785b2a2c0eb413c285d4"}, - {file = "lxml-4.6.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d43bd68714049c84e297c005456a15ecdec818f7b5aa5868c8b0a865cfb78a44"}, - {file = "lxml-4.6.4-cp39-cp39-win32.whl", hash = "sha256:ee9e4b07b0eba4b6a521509e9e1877476729c1243246b6959de697ebea739643"}, - {file = "lxml-4.6.4-cp39-cp39-win_amd64.whl", hash = "sha256:48eaac2991b3036175b42ee8d3c23f4cca13f2be8426bf29401a690ab58c88f4"}, - {file = "lxml-4.6.4-pp37-pypy37_pp73-macosx_10_14_x86_64.whl", hash = "sha256:2b06a91cf7b8acea7793006e4ae50646cef0fe35ce5acd4f5cb1c77eb228e4a1"}, - {file = "lxml-4.6.4-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:523f195948a1ba4f9f5b7294d83c6cd876547dc741820750a7e5e893a24bbe38"}, - {file = "lxml-4.6.4-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:b0ca0ada9d3bc18bd6f611bd001a28abdd49ab9698bd6d717f7f5394c8e94628"}, - {file = "lxml-4.6.4-pp38-pypy38_pp73-macosx_10_14_x86_64.whl", hash = "sha256:197b7cb7a753cf553a45115739afd8458464a28913da00f5c525063f94cd3f48"}, - {file = "lxml-4.6.4-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:6298f5b42a26581206ef63fffa97c754245d329414108707c525512a5197f2ba"}, - {file = "lxml-4.6.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0b12c95542f04d10cba46b3ff28ea52ea56995b78cf918f0b11b05e75812bb79"}, - {file = "lxml-4.6.4.tar.gz", hash = "sha256:daf9bd1fee31f1c7a5928b3e1059e09a8d683ea58fb3ffc773b6c88cb8d1399c"}, -] -markupsafe = [ - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, - {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, -] -matplotlib-inline = [ - {file = "matplotlib-inline-0.1.3.tar.gz", hash = "sha256:a04bfba22e0d1395479f866853ec1ee28eea1485c1d69a6faf00dc3e24ff34ee"}, - {file = "matplotlib_inline-0.1.3-py3-none-any.whl", hash = "sha256:aed605ba3b72462d64d475a21a9296f400a19c4f74a31b59103d2a99ffd5aa5c"}, -] -mccabe = [ - {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, - {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, -] -mypy = [ - {file = "mypy-0.910-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:a155d80ea6cee511a3694b108c4494a39f42de11ee4e61e72bc424c490e46457"}, - {file = "mypy-0.910-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b94e4b785e304a04ea0828759172a15add27088520dc7e49ceade7834275bedb"}, - {file = "mypy-0.910-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:088cd9c7904b4ad80bec811053272986611b84221835e079be5bcad029e79dd9"}, - {file = "mypy-0.910-cp35-cp35m-win_amd64.whl", hash = "sha256:adaeee09bfde366d2c13fe6093a7df5df83c9a2ba98638c7d76b010694db760e"}, - {file = "mypy-0.910-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ecd2c3fe726758037234c93df7e98deb257fd15c24c9180dacf1ef829da5f921"}, - {file = "mypy-0.910-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d9dd839eb0dc1bbe866a288ba3c1afc33a202015d2ad83b31e875b5905a079b6"}, - {file = "mypy-0.910-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:3e382b29f8e0ccf19a2df2b29a167591245df90c0b5a2542249873b5c1d78212"}, - {file = "mypy-0.910-cp36-cp36m-win_amd64.whl", hash = "sha256:53fd2eb27a8ee2892614370896956af2ff61254c275aaee4c230ae771cadd885"}, - {file = "mypy-0.910-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b6fb13123aeef4a3abbcfd7e71773ff3ff1526a7d3dc538f3929a49b42be03f0"}, - {file = "mypy-0.910-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e4dab234478e3bd3ce83bac4193b2ecd9cf94e720ddd95ce69840273bf44f6de"}, - {file = "mypy-0.910-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:7df1ead20c81371ccd6091fa3e2878559b5c4d4caadaf1a484cf88d93ca06703"}, - {file = "mypy-0.910-cp37-cp37m-win_amd64.whl", hash = "sha256:0aadfb2d3935988ec3815952e44058a3100499f5be5b28c34ac9d79f002a4a9a"}, - {file = "mypy-0.910-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ec4e0cd079db280b6bdabdc807047ff3e199f334050db5cbb91ba3e959a67504"}, - {file = "mypy-0.910-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:119bed3832d961f3a880787bf621634ba042cb8dc850a7429f643508eeac97b9"}, - {file = "mypy-0.910-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:866c41f28cee548475f146aa4d39a51cf3b6a84246969f3759cb3e9c742fc072"}, - {file = "mypy-0.910-cp38-cp38-win_amd64.whl", hash = "sha256:ceb6e0a6e27fb364fb3853389607cf7eb3a126ad335790fa1e14ed02fba50811"}, - {file = "mypy-0.910-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a85e280d4d217150ce8cb1a6dddffd14e753a4e0c3cf90baabb32cefa41b59e"}, - {file = "mypy-0.910-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:42c266ced41b65ed40a282c575705325fa7991af370036d3f134518336636f5b"}, - {file = "mypy-0.910-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:3c4b8ca36877fc75339253721f69603a9c7fdb5d4d5a95a1a1b899d8b86a4de2"}, - {file = "mypy-0.910-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:c0df2d30ed496a08de5daed2a9ea807d07c21ae0ab23acf541ab88c24b26ab97"}, - {file = "mypy-0.910-cp39-cp39-win_amd64.whl", hash = "sha256:c6c2602dffb74867498f86e6129fd52a2770c48b7cd3ece77ada4fa38f94eba8"}, - {file = "mypy-0.910-py3-none-any.whl", hash = "sha256:ef565033fa5a958e62796867b1df10c40263ea9ded87164d67572834e57a174d"}, - {file = "mypy-0.910.tar.gz", hash = "sha256:704098302473cb31a218f1775a873b376b30b4c18229421e9e9dc8916fd16150"}, -] -mypy-extensions = [ - {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, - {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, -] -oauthlib = [ - {file = "oauthlib-3.1.1-py2.py3-none-any.whl", hash = "sha256:42bf6354c2ed8c6acb54d971fce6f88193d97297e18602a3a886603f9d7730cc"}, - {file = "oauthlib-3.1.1.tar.gz", hash = "sha256:8f0215fcc533dd8dd1bee6f4c412d4f0cd7297307d43ac61666389e3bc3198a3"}, -] -outcome = [ - {file = "outcome-1.1.0-py2.py3-none-any.whl", hash = "sha256:c7dd9375cfd3c12db9801d080a3b63d4b0a261aa996c4c13152380587288d958"}, - {file = "outcome-1.1.0.tar.gz", hash = "sha256:e862f01d4e626e63e8f92c38d1f8d5546d3f9cce989263c521b2e7990d186967"}, -] -packaging = [ - {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, - {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, -] -parso = [ - {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, - {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, -] -parsy = [ - {file = "parsy-1.1.0-py3-none-any.whl", hash = "sha256:25bd5cea2954950ebbfdf71f8bdaf7fd45a5df5325fd36a1064be2204d9d4c94"}, - {file = "parsy-1.1.0.tar.gz", hash = "sha256:36173ba01a5372c7a1b32352cc73a279a49198f52252adf1c8c1ed41d1f94e8d"}, -] -pathspec = [ - {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, - {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, -] -pbr = [ - {file = "pbr-5.8.0-py2.py3-none-any.whl", hash = "sha256:176e8560eaf61e127817ef93d8a844803abb27a4d4637f0ff3bb783129be2e0a"}, - {file = "pbr-5.8.0.tar.gz", hash = "sha256:672d8ebee84921862110f23fcec2acea191ef58543d34dfe9ef3d9f13c31cddf"}, -] -persisting-theory = [ - {file = "persisting-theory-0.2.1.tar.gz", hash = "sha256:00ff7dcc8f481ff75c770ca5797d968e8725b6df1f77fe0cf7d20fa1e5790c0a"}, -] -pexpect = [ - {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, - {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, -] -pg8000 = [ - {file = "pg8000-1.23.0-py3-none-any.whl", hash = "sha256:e339f09f676629c0806c8dcc6fdc89ca6dba817e20702448c5172e85d133419d"}, - {file = "pg8000-1.23.0.tar.gz", hash = "sha256:a413e00141342813a2ca47e8b7b0549ff338cca02bc819076b6d70f12d755c79"}, -] -phonenumbers = [ - {file = "phonenumbers-8.12.38-py2.py3-none-any.whl", hash = "sha256:95c8a30157323a73a4f9207792e3ed69b626b4c74d8fc44064f25e7fb56cfc94"}, - {file = "phonenumbers-8.12.38.tar.gz", hash = "sha256:3cda1d1cea9a6801babf825e6c0f6a9776ea6d8a68b81b256178f8e5aa813344"}, -] -pickleshare = [ - {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, - {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, -] -pillow = [ - {file = "Pillow-8.4.0-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:81f8d5c81e483a9442d72d182e1fb6dcb9723f289a57e8030811bac9ea3fef8d"}, - {file = "Pillow-8.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3f97cfb1e5a392d75dd8b9fd274d205404729923840ca94ca45a0af57e13dbe6"}, - {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb9fc393f3c61f9054e1ed26e6fe912c7321af2f41ff49d3f83d05bacf22cc78"}, - {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d82cdb63100ef5eedb8391732375e6d05993b765f72cb34311fab92103314649"}, - {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62cc1afda735a8d109007164714e73771b499768b9bb5afcbbee9d0ff374b43f"}, - {file = "Pillow-8.4.0-cp310-cp310-win32.whl", hash = "sha256:e3dacecfbeec9a33e932f00c6cd7996e62f53ad46fbe677577394aaa90ee419a"}, - {file = "Pillow-8.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:620582db2a85b2df5f8a82ddeb52116560d7e5e6b055095f04ad828d1b0baa39"}, - {file = "Pillow-8.4.0-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:1bc723b434fbc4ab50bb68e11e93ce5fb69866ad621e3c2c9bdb0cd70e345f55"}, - {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72cbcfd54df6caf85cc35264c77ede902452d6df41166010262374155947460c"}, - {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70ad9e5c6cb9b8487280a02c0ad8a51581dcbbe8484ce058477692a27c151c0a"}, - {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25a49dc2e2f74e65efaa32b153527fc5ac98508d502fa46e74fa4fd678ed6645"}, - {file = "Pillow-8.4.0-cp36-cp36m-win32.whl", hash = "sha256:93ce9e955cc95959df98505e4608ad98281fff037350d8c2671c9aa86bcf10a9"}, - {file = "Pillow-8.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2e4440b8f00f504ee4b53fe30f4e381aae30b0568193be305256b1462216feff"}, - {file = "Pillow-8.4.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:8c803ac3c28bbc53763e6825746f05cc407b20e4a69d0122e526a582e3b5e153"}, - {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8a17b5d948f4ceeceb66384727dde11b240736fddeda54ca740b9b8b1556b29"}, - {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1394a6ad5abc838c5cd8a92c5a07535648cdf6d09e8e2d6df916dfa9ea86ead8"}, - {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:792e5c12376594bfcb986ebf3855aa4b7c225754e9a9521298e460e92fb4a488"}, - {file = "Pillow-8.4.0-cp37-cp37m-win32.whl", hash = "sha256:d99ec152570e4196772e7a8e4ba5320d2d27bf22fdf11743dd882936ed64305b"}, - {file = "Pillow-8.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:7b7017b61bbcdd7f6363aeceb881e23c46583739cb69a3ab39cb384f6ec82e5b"}, - {file = "Pillow-8.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:d89363f02658e253dbd171f7c3716a5d340a24ee82d38aab9183f7fdf0cdca49"}, - {file = "Pillow-8.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0a0956fdc5defc34462bb1c765ee88d933239f9a94bc37d132004775241a7585"}, - {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b7bb9de00197fb4261825c15551adf7605cf14a80badf1761d61e59da347779"}, - {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72b9e656e340447f827885b8d7a15fc8c4e68d410dc2297ef6787eec0f0ea409"}, - {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5a4532a12314149d8b4e4ad8ff09dde7427731fcfa5917ff16d0291f13609df"}, - {file = "Pillow-8.4.0-cp38-cp38-win32.whl", hash = "sha256:82aafa8d5eb68c8463b6e9baeb4f19043bb31fefc03eb7b216b51e6a9981ae09"}, - {file = "Pillow-8.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:066f3999cb3b070a95c3652712cffa1a748cd02d60ad7b4e485c3748a04d9d76"}, - {file = "Pillow-8.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:5503c86916d27c2e101b7f71c2ae2cddba01a2cf55b8395b0255fd33fa4d1f1a"}, - {file = "Pillow-8.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4acc0985ddf39d1bc969a9220b51d94ed51695d455c228d8ac29fcdb25810e6e"}, - {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b052a619a8bfcf26bd8b3f48f45283f9e977890263e4571f2393ed8898d331b"}, - {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:493cb4e415f44cd601fcec11c99836f707bb714ab03f5ed46ac25713baf0ff20"}, - {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8831cb7332eda5dc89b21a7bce7ef6ad305548820595033a4b03cf3091235ed"}, - {file = "Pillow-8.4.0-cp39-cp39-win32.whl", hash = "sha256:5e9ac5f66616b87d4da618a20ab0a38324dbe88d8a39b55be8964eb520021e02"}, - {file = "Pillow-8.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:3eb1ce5f65908556c2d8685a8f0a6e989d887ec4057326f6c22b24e8a172c66b"}, - {file = "Pillow-8.4.0-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:ddc4d832a0f0b4c52fff973a0d44b6c99839a9d016fe4e6a1cb8f3eea96479c2"}, - {file = "Pillow-8.4.0-pp36-pypy36_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a3e5ddc44c14042f0844b8cf7d2cd455f6cc80fd7f5eefbe657292cf601d9ad"}, - {file = "Pillow-8.4.0-pp36-pypy36_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c70e94281588ef053ae8998039610dbd71bc509e4acbc77ab59d7d2937b10698"}, - {file = "Pillow-8.4.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:3862b7256046fcd950618ed22d1d60b842e3a40a48236a5498746f21189afbbc"}, - {file = "Pillow-8.4.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4901622493f88b1a29bd30ec1a2f683782e57c3c16a2dbc7f2595ba01f639df"}, - {file = "Pillow-8.4.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84c471a734240653a0ec91dec0996696eea227eafe72a33bd06c92697728046b"}, - {file = "Pillow-8.4.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:244cf3b97802c34c41905d22810846802a3329ddcb93ccc432870243211c79fc"}, - {file = "Pillow-8.4.0.tar.gz", hash = "sha256:b8e2f83c56e141920c39464b852de3719dfbfb6e3c99a2d8da0edf4fb33176ed"}, -] -platformdirs = [ - {file = "platformdirs-2.4.0-py3-none-any.whl", hash = "sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d"}, - {file = "platformdirs-2.4.0.tar.gz", hash = "sha256:367a5e80b3d04d2428ffa76d33f124cf11e8fff2acdaa9b43d545f5c7d661ef2"}, -] -pluggy = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, -] -prometheus-client = [ - {file = "prometheus_client-0.12.0-py2.py3-none-any.whl", hash = "sha256:317453ebabff0a1b02df7f708efbab21e3489e7072b61cb6957230dd004a0af0"}, - {file = "prometheus_client-0.12.0.tar.gz", hash = "sha256:1b12ba48cee33b9b0b9de64a1047cbd3c5f2d0ab6ebcead7ddda613a750ec3c5"}, -] -prompt-toolkit = [ - {file = "prompt_toolkit-3.0.23-py3-none-any.whl", hash = "sha256:5f29d62cb7a0ecacfa3d8ceea05a63cd22500543472d64298fc06ddda906b25d"}, - {file = "prompt_toolkit-3.0.23.tar.gz", hash = "sha256:7053aba00895473cb357819358ef33f11aa97e4ac83d38efb123e5649ceeecaf"}, -] -psutil = [ - {file = "psutil-5.8.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64"}, - {file = "psutil-5.8.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c"}, - {file = "psutil-5.8.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:12d844996d6c2b1d3881cfa6fa201fd635971869a9da945cf6756105af73d2df"}, - {file = "psutil-5.8.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:02b8292609b1f7fcb34173b25e48d0da8667bc85f81d7476584d889c6e0f2131"}, - {file = "psutil-5.8.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:6ffe81843131ee0ffa02c317186ed1e759a145267d54fdef1bc4ea5f5931ab60"}, - {file = "psutil-5.8.0-cp27-none-win32.whl", hash = "sha256:ea313bb02e5e25224e518e4352af4bf5e062755160f77e4b1767dd5ccb65f876"}, - {file = "psutil-5.8.0-cp27-none-win_amd64.whl", hash = "sha256:5da29e394bdedd9144c7331192e20c1f79283fb03b06e6abd3a8ae45ffecee65"}, - {file = "psutil-5.8.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:74fb2557d1430fff18ff0d72613c5ca30c45cdbfcddd6a5773e9fc1fe9364be8"}, - {file = "psutil-5.8.0-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:74f2d0be88db96ada78756cb3a3e1b107ce8ab79f65aa885f76d7664e56928f6"}, - {file = "psutil-5.8.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:99de3e8739258b3c3e8669cb9757c9a861b2a25ad0955f8e53ac662d66de61ac"}, - {file = "psutil-5.8.0-cp36-cp36m-win32.whl", hash = "sha256:36b3b6c9e2a34b7d7fbae330a85bf72c30b1c827a4366a07443fc4b6270449e2"}, - {file = "psutil-5.8.0-cp36-cp36m-win_amd64.whl", hash = "sha256:52de075468cd394ac98c66f9ca33b2f54ae1d9bff1ef6b67a212ee8f639ec06d"}, - {file = "psutil-5.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c6a5fd10ce6b6344e616cf01cc5b849fa8103fbb5ba507b6b2dee4c11e84c935"}, - {file = "psutil-5.8.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:61f05864b42fedc0771d6d8e49c35f07efd209ade09a5afe6a5059e7bb7bf83d"}, - {file = "psutil-5.8.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:0dd4465a039d343925cdc29023bb6960ccf4e74a65ad53e768403746a9207023"}, - {file = "psutil-5.8.0-cp37-cp37m-win32.whl", hash = "sha256:1bff0d07e76114ec24ee32e7f7f8d0c4b0514b3fae93e3d2aaafd65d22502394"}, - {file = "psutil-5.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563"}, - {file = "psutil-5.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6223d07a1ae93f86451d0198a0c361032c4c93ebd4bf6d25e2fb3edfad9571ef"}, - {file = "psutil-5.8.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d225cd8319aa1d3c85bf195c4e07d17d3cd68636b8fc97e6cf198f782f99af28"}, - {file = "psutil-5.8.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:28ff7c95293ae74bf1ca1a79e8805fcde005c18a122ca983abf676ea3466362b"}, - {file = "psutil-5.8.0-cp38-cp38-win32.whl", hash = "sha256:ce8b867423291cb65cfc6d9c4955ee9bfc1e21fe03bb50e177f2b957f1c2469d"}, - {file = "psutil-5.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:90f31c34d25b1b3ed6c40cdd34ff122b1887a825297c017e4cbd6796dd8b672d"}, - {file = "psutil-5.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6323d5d845c2785efb20aded4726636546b26d3b577aded22492908f7c1bdda7"}, - {file = "psutil-5.8.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:245b5509968ac0bd179287d91210cd3f37add77dad385ef238b275bad35fa1c4"}, - {file = "psutil-5.8.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:90d4091c2d30ddd0a03e0b97e6a33a48628469b99585e2ad6bf21f17423b112b"}, - {file = "psutil-5.8.0-cp39-cp39-win32.whl", hash = "sha256:ea372bcc129394485824ae3e3ddabe67dc0b118d262c568b4d2602a7070afdb0"}, - {file = "psutil-5.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3"}, - {file = "psutil-5.8.0.tar.gz", hash = "sha256:0c9ccb99ab76025f2f0bbecf341d4656e9c1351db8cc8a03ccd62e318ab4b5c6"}, -] -psycopg2 = [ - {file = "psycopg2-2.9.2-cp310-cp310-win32.whl", hash = "sha256:6796ac614412ce374587147150e56d03b7845c9e031b88aacdcadc880e81bb38"}, - {file = "psycopg2-2.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:dfc32db6ce9ecc35a131320888b547199f79822b028934bb5b332f4169393e15"}, - {file = "psycopg2-2.9.2-cp36-cp36m-win32.whl", hash = "sha256:77d09a79f9739b97099d2952bbbf18eaa4eaf825362387acbb9552ec1b3fa228"}, - {file = "psycopg2-2.9.2-cp36-cp36m-win_amd64.whl", hash = "sha256:f65cba7924363e0d2f416041b48ff69d559548f2cb168ff972c54e09e1e64db8"}, - {file = "psycopg2-2.9.2-cp37-cp37m-win32.whl", hash = "sha256:b8816c6410fa08d2a022e4e38d128bae97c1855e176a00493d6ec62ccd606d57"}, - {file = "psycopg2-2.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:26322c3f114de1f60c1b0febf8fdd595c221b4f624524178f515d07350a71bd1"}, - {file = "psycopg2-2.9.2-cp38-cp38-win32.whl", hash = "sha256:77b9105ef37bc005b8ffbcb1ed6d8685bb0e8ce84773738aa56421a007ec5a7a"}, - {file = "psycopg2-2.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:91c7fd0fe9e6c118e8ff5b665bc3445781d3615fa78e131d0b4f8c85e8ca9ec8"}, - {file = "psycopg2-2.9.2-cp39-cp39-win32.whl", hash = "sha256:a761b60da0ecaf6a9866985bcde26327883ac3cdb90535ab68b8d784f02b05ef"}, - {file = "psycopg2-2.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:fd7ddab7d6afee4e21c03c648c8b667b197104713e57ec404d5b74097af21e31"}, - {file = "psycopg2-2.9.2.tar.gz", hash = "sha256:a84da9fa891848e0270e8e04dcca073bc9046441eeb47069f5c0e36783debbea"}, -] -ptyprocess = [ - {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, - {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, -] -py = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, -] -pyasn1 = [ - {file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"}, - {file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"}, -] -pyasn1-modules = [ - {file = "pyasn1-modules-0.2.8.tar.gz", hash = "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e"}, - {file = "pyasn1_modules-0.2.8-py2.py3-none-any.whl", hash = "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74"}, -] -pycodestyle = [ - {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, - {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, -] -pycparser = [ - {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, - {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, -] -pycryptodome = [ - {file = "pycryptodome-3.11.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ffd0cac13ff41f2d15ed39dc6ba1d2ad88dd2905d656c33d8235852f5d6151fd"}, - {file = "pycryptodome-3.11.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:ead516e03dfe062aefeafe4a29445a6449b0fc43bc8cb30194b2754917a63798"}, - {file = "pycryptodome-3.11.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:4ce6b09547bf2c7cede3a017f79502eaed3e819c13cdb3cb357aea1b004e4cc6"}, - {file = "pycryptodome-3.11.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:014c758af7fa38cab85b357a496b76f4fc9dda1f731eb28358d66fef7ad4a3e1"}, - {file = "pycryptodome-3.11.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:a843350d08c3d22f6c09c2f17f020d8dcfa59496165d7425a3fba0045543dda7"}, - {file = "pycryptodome-3.11.0-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:53989477044be41fa4a63da09d5038c2a34b2f4554cfea2e3933b17186ee9e19"}, - {file = "pycryptodome-3.11.0-cp27-cp27m-win32.whl", hash = "sha256:f9bad2220b80b4ed74f089db012ab5ab5419143a33fad6c8aedcc2a9341eac70"}, - {file = "pycryptodome-3.11.0-cp27-cp27m-win_amd64.whl", hash = "sha256:3c7ed5b07274535979c730daf5817db5e983ea80b04c22579eee8da4ca3ae4f8"}, - {file = "pycryptodome-3.11.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:8f3a60926be78422e662b0d0b18351b426ce27657101c8a50bad80300de6a701"}, - {file = "pycryptodome-3.11.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:fce7e22d96030b35345637c563246c24d4513bd3b413e1c40293114837ab8912"}, - {file = "pycryptodome-3.11.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:bc3c61ff92efdcc14af4a7b81da71d849c9acee51d8fd8ac9841a7620140d6c6"}, - {file = "pycryptodome-3.11.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:b33c9b3d1327d821e28e9cc3a6512c14f8b17570ddb4cfb9a52247ed0fcc5d8b"}, - {file = "pycryptodome-3.11.0-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:75e78360d1dd6d02eb288fd8275bb4d147d6e3f5337935c096d11dba1fa84748"}, - {file = "pycryptodome-3.11.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:621a90147a5e255fdc2a0fec2d56626b76b5d72ea9e60164c9a5a8976d45b0c9"}, - {file = "pycryptodome-3.11.0-cp35-abi3-manylinux1_i686.whl", hash = "sha256:0ca7a6b4fc1f9fafe990b95c8cda89099797e2cfbf40e55607f2f2f5a3355dcb"}, - {file = "pycryptodome-3.11.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:b59bf823cfafde8ef1105d8984f26d1694dff165adb7198b12e3e068d7999b15"}, - {file = "pycryptodome-3.11.0-cp35-abi3-manylinux2010_i686.whl", hash = "sha256:ce81b9c6aaa0f920e2ab05eb2b9f4ccd102e3016b2f37125593b16a83a4b0cc2"}, - {file = "pycryptodome-3.11.0-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:ae29fcd56152f417bfba50a36a56a7a5f9fb74ff80bab98704cac704de6568ab"}, - {file = "pycryptodome-3.11.0-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:ae31cb874f6f0cedbed457c6374e7e54d7ed45c1a4e11a65a9c80968da90a650"}, - {file = "pycryptodome-3.11.0-cp35-abi3-win32.whl", hash = "sha256:6db1f9fa1f52226621905f004278ce7bd90c8f5363ffd5d7ab3755363d98549a"}, - {file = "pycryptodome-3.11.0-cp35-abi3-win_amd64.whl", hash = "sha256:d7e5f6f692421e5219aa3b545eb0cffd832cd589a4b9dcd4a5eb4260e2c0d68a"}, - {file = "pycryptodome-3.11.0-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:da796e9221dda61a0019d01742337eb8a322de8598b678a4344ca0a436380315"}, - {file = "pycryptodome-3.11.0-pp27-pypy_73-manylinux1_x86_64.whl", hash = "sha256:ed45ef92d21db33685b789de2c015e9d9a18a74760a8df1fc152faee88cdf741"}, - {file = "pycryptodome-3.11.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:4169ed515742425ff21e4bd3fabbb6994ffb64434472fb72230019bdfa36b939"}, - {file = "pycryptodome-3.11.0-pp27-pypy_73-win32.whl", hash = "sha256:f19edd42368e9057c39492947bb99570dc927123e210008f2af7cf9b505c6892"}, - {file = "pycryptodome-3.11.0-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:06162fcfed2f9deee8383fd59eaeabc7b7ffc3af50d3fad4000032deb8f700b0"}, - {file = "pycryptodome-3.11.0-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:6eda8a3157c91ba60b26a07bedd6c44ab8bda6cd79b6b5ea9744ba62c39b7b1e"}, - {file = "pycryptodome-3.11.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:7ff701fc283412e651eaab4319b3cd4eaa0827e94569cd37ee9075d5c05fe655"}, - {file = "pycryptodome-3.11.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:2a4bcc8a9977fee0979079cd33a9e9f0d3ddba5660d35ffe874cf84f1dd399d2"}, - {file = "pycryptodome-3.11.0.tar.gz", hash = "sha256:428096bbf7a77e207f418dfd4d7c284df8ade81d2dc80f010e92753a3e406ad0"}, -] -pydocstyle = [ - {file = "pydocstyle-6.1.1-py3-none-any.whl", hash = "sha256:6987826d6775056839940041beef5c08cc7e3d71d63149b48e36727f70144dc4"}, - {file = "pydocstyle-6.1.1.tar.gz", hash = "sha256:1d41b7c459ba0ee6c345f2eb9ae827cab14a7533a88c5c6f7e94923f72df92dc"}, -] -pyflakes = [ - {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, - {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, -] -pygments = [ - {file = "Pygments-2.10.0-py3-none-any.whl", hash = "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380"}, - {file = "Pygments-2.10.0.tar.gz", hash = "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"}, -] -pyjwt = [ - {file = "PyJWT-2.3.0-py3-none-any.whl", hash = "sha256:e0c4bb8d9f0af0c7f5b1ec4c5036309617d03d56932877f2f7a0beeb5318322f"}, - {file = "PyJWT-2.3.0.tar.gz", hash = "sha256:b888b4d56f06f6dcd777210c334e69c737be74755d3e5e9ee3fe67dc18a0ee41"}, -] -pyopenssl = [ - {file = "pyOpenSSL-21.0.0-py2.py3-none-any.whl", hash = "sha256:8935bd4920ab9abfebb07c41a4f58296407ed77f04bd1a92914044b848ba1ed6"}, - {file = "pyOpenSSL-21.0.0.tar.gz", hash = "sha256:5e2d8c5e46d0d865ae933bef5230090bdaf5506281e9eec60fa250ee80600cb3"}, -] -pyparsing = [ - {file = "pyparsing-3.0.6-py3-none-any.whl", hash = "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4"}, - {file = "pyparsing-3.0.6.tar.gz", hash = "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"}, -] -pytest = [ - {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, - {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, -] -pytest-cov = [ - {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, - {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, -] -pytest-django = [ - {file = "pytest-django-4.5.0.tar.gz", hash = "sha256:4b1120c364404cfa9f54e2229b5c39151821bb17819e4bcf357e0f62a3e925a0"}, - {file = "pytest_django-4.5.0-py3-none-any.whl", hash = "sha256:10cb6e5baacd56ca1f0134ce448b050c31824ba4e480eb7e0fa3832f3a0f8b4c"}, -] -pytest-django-testing-postgresql = [ - {file = "pytest-django-testing-postgresql-0.1.post0.tar.gz", hash = "sha256:78b0c58930084cb4393407b2e5a2a3b8734c627b841ecef7d62d39bbfb8e8a45"}, - {file = "pytest_django_testing_postgresql-0.1.post0-py3-none-any.whl", hash = "sha256:78e52e3d1b0ef5f906d5d69247dd6ac7dfb10d840bd81abab92f3f8c30872cd3"}, -] -pytest-sugar = [ - {file = "pytest-sugar-0.9.4.tar.gz", hash = "sha256:b1b2186b0a72aada6859bea2a5764145e3aaa2c1cfbb23c3a19b5f7b697563d3"}, -] -python-crontab = [ - {file = "python-crontab-2.6.0.tar.gz", hash = "sha256:1e35ed7a3cdc3100545b43e196d34754e6551e7f95e4caebbe0e1c0ca41c2f1b"}, -] -python-dateutil = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, -] -python-gnupg = [ - {file = "python-gnupg-0.4.8.tar.gz", hash = "sha256:b64de1ae5cedf872b437201a566fa2c62ce0c95ea2e30177eb53aee1258507d7"}, - {file = "python_gnupg-0.4.8-py2.py3-none-any.whl", hash = "sha256:93a521501d6c2785d96b190aec7125ba89c1c2fe708b0c98af3fb32b59026ab8"}, -] -python-ldap = [ - {file = "python-ldap-3.4.0.tar.gz", hash = "sha256:60464c8fc25e71e0fd40449a24eae482dcd0fb7fcf823e7de627a6525b3e0d12"}, -] -python3-openid = [ - {file = "python3-openid-3.2.0.tar.gz", hash = "sha256:33fbf6928f401e0b790151ed2b5290b02545e8775f982485205a066f874aaeaf"}, - {file = "python3_openid-3.2.0-py3-none-any.whl", hash = "sha256:6626f771e0417486701e0b4daff762e7212e820ca5b29fcc0d05f6f8736dfa6b"}, -] -pytz = [ - {file = "pytz-2021.3-py2.py3-none-any.whl", hash = "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c"}, - {file = "pytz-2021.3.tar.gz", hash = "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"}, -] -pyyaml = [ - {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, - {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, - {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, - {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, - {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, - {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, - {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, - {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, - {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, - {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, - {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, - {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, - {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, - {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, - {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, - {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, -] -qrcode = [ - {file = "qrcode-6.1-py2.py3-none-any.whl", hash = "sha256:3996ee560fc39532910603704c82980ff6d4d5d629f9c3f25f34174ce8606cf5"}, - {file = "qrcode-6.1.tar.gz", hash = "sha256:505253854f607f2abf4d16092c61d4e9d511a3b4392e60bff957a68592b04369"}, -] -redis = [ - {file = "redis-3.5.3-py2.py3-none-any.whl", hash = "sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24"}, - {file = "redis-3.5.3.tar.gz", hash = "sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2"}, -] -regex = [ - {file = "regex-2021.11.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9345b6f7ee578bad8e475129ed40123d265464c4cfead6c261fd60fc9de00bcf"}, - {file = "regex-2021.11.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:416c5f1a188c91e3eb41e9c8787288e707f7d2ebe66e0a6563af280d9b68478f"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0538c43565ee6e703d3a7c3bdfe4037a5209250e8502c98f20fea6f5fdf2965"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee1227cf08b6716c85504aebc49ac827eb88fcc6e51564f010f11a406c0a667"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6650f16365f1924d6014d2ea770bde8555b4a39dc9576abb95e3cd1ff0263b36"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30ab804ea73972049b7a2a5c62d97687d69b5a60a67adca07eb73a0ddbc9e29f"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68a067c11463de2a37157930d8b153005085e42bcb7ad9ca562d77ba7d1404e0"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:162abfd74e88001d20cb73ceaffbfe601469923e875caf9118333b1a4aaafdc4"}, - {file = "regex-2021.11.10-cp310-cp310-win32.whl", hash = "sha256:98ba568e8ae26beb726aeea2273053c717641933836568c2a0278a84987b2a1a"}, - {file = "regex-2021.11.10-cp310-cp310-win_amd64.whl", hash = "sha256:780b48456a0f0ba4d390e8b5f7c661fdd218934388cde1a974010a965e200e12"}, - {file = "regex-2021.11.10-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:dba70f30fd81f8ce6d32ddeef37d91c8948e5d5a4c63242d16a2b2df8143aafc"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1f54b9b4b6c53369f40028d2dd07a8c374583417ee6ec0ea304e710a20f80a0"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fbb9dc00e39f3e6c0ef48edee202f9520dafb233e8b51b06b8428cfcb92abd30"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666abff54e474d28ff42756d94544cdfd42e2ee97065857413b72e8a2d6a6345"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5537f71b6d646f7f5f340562ec4c77b6e1c915f8baae822ea0b7e46c1f09b733"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2e07c6a26ed4bea91b897ee2b0835c21716d9a469a96c3e878dc5f8c55bb23"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ca5f18a75e1256ce07494e245cdb146f5a9267d3c702ebf9b65c7f8bd843431e"}, - {file = "regex-2021.11.10-cp36-cp36m-win32.whl", hash = "sha256:93a5051fcf5fad72de73b96f07d30bc29665697fb8ecdfbc474f3452c78adcf4"}, - {file = "regex-2021.11.10-cp36-cp36m-win_amd64.whl", hash = "sha256:b483c9d00a565633c87abd0aaf27eb5016de23fed952e054ecc19ce32f6a9e7e"}, - {file = "regex-2021.11.10-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fff55f3ce50a3ff63ec8e2a8d3dd924f1941b250b0aac3d3d42b687eeff07a8e"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32d2a2b02ccbef10145df9135751abea1f9f076e67a4e261b05f24b94219e36"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53db2c6be8a2710b359bfd3d3aa17ba38f8aa72a82309a12ae99d3c0c3dcd74d"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2207ae4f64ad3af399e2d30dde66f0b36ae5c3129b52885f1bffc2f05ec505c8"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5ca078bb666c4a9d1287a379fe617a6dccd18c3e8a7e6c7e1eb8974330c626a"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd33eb9bdcfbabab3459c9ee651d94c842bc8a05fabc95edf4ee0c15a072495e"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05b7d6d7e64efe309972adab77fc2af8907bb93217ec60aa9fe12a0dad35874f"}, - {file = "regex-2021.11.10-cp37-cp37m-win32.whl", hash = "sha256:e71255ba42567d34a13c03968736c5d39bb4a97ce98188fafb27ce981115beec"}, - {file = "regex-2021.11.10-cp37-cp37m-win_amd64.whl", hash = "sha256:07856afef5ffcc052e7eccf3213317fbb94e4a5cd8177a2caa69c980657b3cb4"}, - {file = "regex-2021.11.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba05430e819e58544e840a68b03b28b6d328aff2e41579037e8bab7653b37d83"}, - {file = "regex-2021.11.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7f301b11b9d214f83ddaf689181051e7f48905568b0c7017c04c06dfd065e244"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aaa4e0705ef2b73dd8e36eeb4c868f80f8393f5f4d855e94025ce7ad8525f50"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:788aef3549f1924d5c38263104dae7395bf020a42776d5ec5ea2b0d3d85d6646"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f8af619e3be812a2059b212064ea7a640aff0568d972cd1b9e920837469eb3cb"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85bfa6a5413be0ee6c5c4a663668a2cad2cbecdee367630d097d7823041bdeec"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f23222527b307970e383433daec128d769ff778d9b29343fb3496472dc20dabe"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:da1a90c1ddb7531b1d5ff1e171b4ee61f6345119be7351104b67ff413843fe94"}, - {file = "regex-2021.11.10-cp38-cp38-win32.whl", hash = "sha256:0617383e2fe465732af4509e61648b77cbe3aee68b6ac8c0b6fe934db90be5cc"}, - {file = "regex-2021.11.10-cp38-cp38-win_amd64.whl", hash = "sha256:a3feefd5e95871872673b08636f96b61ebef62971eab044f5124fb4dea39919d"}, - {file = "regex-2021.11.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f7f325be2804246a75a4f45c72d4ce80d2443ab815063cdf70ee8fb2ca59ee1b"}, - {file = "regex-2021.11.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:537ca6a3586931b16a85ac38c08cc48f10fc870a5b25e51794c74df843e9966d"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eef2afb0fd1747f33f1ee3e209bce1ed582d1896b240ccc5e2697e3275f037c7"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:432bd15d40ed835a51617521d60d0125867f7b88acf653e4ed994a1f8e4995dc"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b43c2b8a330a490daaef5a47ab114935002b13b3f9dc5da56d5322ff218eeadb"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:962b9a917dd7ceacbe5cd424556914cb0d636001e393b43dc886ba31d2a1e449"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fa8c626d6441e2d04b6ee703ef2d1e17608ad44c7cb75258c09dd42bacdfc64b"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3c5fb32cc6077abad3bbf0323067636d93307c9fa93e072771cf9a64d1c0f3ef"}, - {file = "regex-2021.11.10-cp39-cp39-win32.whl", hash = "sha256:3b5df18db1fccd66de15aa59c41e4f853b5df7550723d26aa6cb7f40e5d9da5a"}, - {file = "regex-2021.11.10-cp39-cp39-win_amd64.whl", hash = "sha256:83ee89483672b11f8952b158640d0c0ff02dc43d9cb1b70c1564b49abe92ce29"}, - {file = "regex-2021.11.10.tar.gz", hash = "sha256:f341ee2df0999bfdf7a95e448075effe0db212a59387de1a70690e4acb03d4c6"}, -] -reportlab = [ - {file = "reportlab-3.6.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:169d7017687c60ddf7690cb349e24ae10d51480d93babc6f81d851aea8a01a25"}, - {file = "reportlab-3.6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:af350308e8b8720ca6db7763b56e96b37976576c1f8b0069764074dc41a19254"}, - {file = "reportlab-3.6.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0cc8308678a8136481572463e5ac92a145d2fb487aa22c842347af8a063d50a"}, - {file = "reportlab-3.6.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d7145d010d561c502e51795adb2e4f7534f28f12e32db0b0694081c6173c8b27"}, - {file = "reportlab-3.6.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae3959094b48bdae729e838d84156d31691f0bd17c640b8b10ff0fdbbc11c031"}, - {file = "reportlab-3.6.3-cp310-cp310-win32.whl", hash = "sha256:2fa30756c2d5d5e11321114636b0cbeffdf59ffdbcf705b902057ad3801d0d37"}, - {file = "reportlab-3.6.3-cp310-cp310-win_amd64.whl", hash = "sha256:7e51f0195e602c207edcf3a768a6005a10b3db786539b74eb99afe6c9fd5656a"}, - {file = "reportlab-3.6.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:7cb6a4ea5cfc08669c0ba66e900cf5c598c33fdb0e3e4ebadf892ff703d594f6"}, - {file = "reportlab-3.6.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b214321e2e16209a68a4cdbe3391379845cd0da434362cf3c6d2d1053146fe"}, - {file = "reportlab-3.6.3-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68de7f3d3511ea45b9af6e9e4a6b6d89a86d1fe59f41583fb55e6c810ebf23d9"}, - {file = "reportlab-3.6.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c79f89c277f49dfd2829b9a046b20c12cd46fe69f474e4dca349e731a2397021"}, - {file = "reportlab-3.6.3-cp36-cp36m-win32.whl", hash = "sha256:c29e7cde992c56687c6f68053dea4aa3beb0d406df28738e95950d88deb38109"}, - {file = "reportlab-3.6.3-cp36-cp36m-win_amd64.whl", hash = "sha256:1055380b2dc73d5143a62451f81b2a739f605dae0e107a764efc0618293837c1"}, - {file = "reportlab-3.6.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d851fecf4bb6484d4038a402430f30294911aa116686624d1e79b9e3cdb1ed2c"}, - {file = "reportlab-3.6.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4e0abfa0daf0c48a6bffc46c51b2e5f6272a1d57593c51e7bc855272f763130"}, - {file = "reportlab-3.6.3-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d94a20b7f2aad166ffe74a77bff02d82a82c514dba6d3e431fdb14675db5c383"}, - {file = "reportlab-3.6.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b75a4f634e8ba89cc22ff58b9bdfd01a239b2e2fc85d086d1a2d70d08167c443"}, - {file = "reportlab-3.6.3-cp37-cp37m-win32.whl", hash = "sha256:27ce3e8869c3f22d9d7a8092858649601e76b86e2f3032df39566343b908d929"}, - {file = "reportlab-3.6.3-cp37-cp37m-win_amd64.whl", hash = "sha256:5785aab3b57fe4794147da8908d411c3abf900ac2bc5b0c39782205a1d8c5b51"}, - {file = "reportlab-3.6.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d35cc6ae73a25b2e75b23e60d3dca0e5153dff97d9e22b28ac82712c79656fd9"}, - {file = "reportlab-3.6.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:720335d2462ed8ad5ad6ea5da509a9289fab7a78b0cdcdfd56fef5398435119d"}, - {file = "reportlab-3.6.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcbf4bcf0917cb50964a9c47198e802791eae2581e7788f43da8f50ed5744d8a"}, - {file = "reportlab-3.6.3-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50e62429a3487722b4d7621453efc4cbeed80f3b608cad98ef8f06d191a8d0a9"}, - {file = "reportlab-3.6.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d57b5374a44aab9f3898c57ed3c2e6ba159878a2a37f36ddd154adf6f4b3a5c0"}, - {file = "reportlab-3.6.3-cp38-cp38-win32.whl", hash = "sha256:3b85b7172b9b4ab0ae74fe0e99d9186ff04104d9158c980391f4e0a54b67f3a8"}, - {file = "reportlab-3.6.3-cp38-cp38-win_amd64.whl", hash = "sha256:f2c0977a39bea423f6a0b53faaabef3b2f8602b1d3e09c57f6952d60ad363119"}, - {file = "reportlab-3.6.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3d5d9997b91ec7f2d1a2b9928ab20503cf70e8c056b445d0bc7ae29946c13623"}, - {file = "reportlab-3.6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5d1280c9df17a5d36213b88d66f45a9475005ab39d79b6e9e98893a02a5a033d"}, - {file = "reportlab-3.6.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5b56d9912f148cca4fdc0d6c805a56931bb1a4e59e899db92a3531e78f2a9de"}, - {file = "reportlab-3.6.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c166a6c168232948e9b100dcab1b88a4b21efe0aa14c5c18bafd28fffffb4576"}, - {file = "reportlab-3.6.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2efdb2999e1b19a16d5535aa70b5ec5f3ad003e1d366da566f23231ff81400aa"}, - {file = "reportlab-3.6.3-cp39-cp39-win32.whl", hash = "sha256:0c2f479df4eb447ea0757bf60b1ac0d7ddb9980335f4f94975ee6d95bda5b8f8"}, - {file = "reportlab-3.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:bb8c380bceb3623f39a96b6bc8cf8db75857fea3f67900391763b5caee23ffa3"}, - {file = "reportlab-3.6.3.tar.gz", hash = "sha256:be4f05230eb17b9c9c61a180ab0c89c30112da2823c77807a2a5ddba19365865"}, -] -requests = [ - {file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"}, - {file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"}, -] -requests-oauthlib = [ - {file = "requests-oauthlib-1.3.0.tar.gz", hash = "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a"}, - {file = "requests_oauthlib-1.3.0-py2.py3-none-any.whl", hash = "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d"}, -] -restructuredtext-lint = [ - {file = "restructuredtext_lint-1.3.2.tar.gz", hash = "sha256:d3b10a1fe2ecac537e51ae6d151b223b78de9fafdd50e5eb6b08c243df173c80"}, -] -"ruamel.yaml" = [ - {file = "ruamel.yaml-0.17.17-py3-none-any.whl", hash = "sha256:9af3ec5d7f8065582f3aa841305465025d0afd26c5fb54e15b964e11838fc74f"}, - {file = "ruamel.yaml-0.17.17.tar.gz", hash = "sha256:9751de4cbb57d4bfbf8fc394e125ed4a2f170fbff3dc3d78abf50be85924f8be"}, -] -"ruamel.yaml.clib" = [ - {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:cfdb9389d888c5b74af297e51ce357b800dd844898af9d4a547ffc143fa56751"}, - {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7b2927e92feb51d830f531de4ccb11b320255ee95e791022555971c466af4527"}, - {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win32.whl", hash = "sha256:ada3f400d9923a190ea8b59c8f60680c4ef8a4b0dfae134d2f2ff68429adfab5"}, - {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win_amd64.whl", hash = "sha256:de9c6b8a1ba52919ae919f3ae96abb72b994dd0350226e28f3686cb4f142165c"}, - {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d67f273097c368265a7b81e152e07fb90ed395df6e552b9fa858c6d2c9f42502"}, - {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:72a2b8b2ff0a627496aad76f37a652bcef400fd861721744201ef1b45199ab78"}, - {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win32.whl", hash = "sha256:9efef4aab5353387b07f6b22ace0867032b900d8e91674b5d8ea9150db5cae94"}, - {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win_amd64.whl", hash = "sha256:846fc8336443106fe23f9b6d6b8c14a53d38cef9a375149d61f99d78782ea468"}, - {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0847201b767447fc33b9c235780d3aa90357d20dd6108b92be544427bea197dd"}, - {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:78988ed190206672da0f5d50c61afef8f67daa718d614377dcd5e3ed85ab4a99"}, - {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win32.whl", hash = "sha256:a49e0161897901d1ac9c4a79984b8410f450565bbad64dbfcbf76152743a0cdb"}, - {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win_amd64.whl", hash = "sha256:bf75d28fa071645c529b5474a550a44686821decebdd00e21127ef1fd566eabe"}, - {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a32f8d81ea0c6173ab1b3da956869114cae53ba1e9f72374032e33ba3118c233"}, - {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7f7ecb53ae6848f959db6ae93bdff1740e651809780822270eab111500842a84"}, - {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win32.whl", hash = "sha256:89221ec6d6026f8ae859c09b9718799fea22c0e8da8b766b0b2c9a9ba2db326b"}, - {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win_amd64.whl", hash = "sha256:31ea73e564a7b5fbbe8188ab8b334393e06d997914a4e184975348f204790277"}, - {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dc6a613d6c74eef5a14a214d433d06291526145431c3b964f5e16529b1842bed"}, - {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:1866cf2c284a03b9524a5cc00daca56d80057c5ce3cdc86a52020f4c720856f0"}, - {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win32.whl", hash = "sha256:3fb9575a5acd13031c57a62cc7823e5d2ff8bc3835ba4d94b921b4e6ee664104"}, - {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win_amd64.whl", hash = "sha256:825d5fccef6da42f3c8eccd4281af399f21c02b32d98e113dbc631ea6a6ecbc7"}, - {file = "ruamel.yaml.clib-0.2.6.tar.gz", hash = "sha256:4ff604ce439abb20794f05613c374759ce10e3595d1867764dd1ae675b85acbd"}, -] -rules = [ - {file = "rules-3.0-py2.py3-none-any.whl", hash = "sha256:8194937b537c8a384eafe21750f1d396e1aecdc833e7d06808a5b805ae42a852"}, - {file = "rules-3.0.tar.gz", hash = "sha256:9141e2fdb7f300fcb59f2f06619fe4ff52bb846eb112ba8c30444f971d6af05e"}, -] -s3transfer = [ - {file = "s3transfer-0.5.0-py3-none-any.whl", hash = "sha256:9c1dc369814391a6bda20ebbf4b70a0f34630592c9aa520856bf384916af2803"}, - {file = "s3transfer-0.5.0.tar.gz", hash = "sha256:50ed823e1dc5868ad40c8dc92072f757aa0e653a192845c94a3b676f4a62da4c"}, -] -safety = [ - {file = "safety-1.10.3-py2.py3-none-any.whl", hash = "sha256:5f802ad5df5614f9622d8d71fedec2757099705c2356f862847c58c6dfe13e84"}, - {file = "safety-1.10.3.tar.gz", hash = "sha256:30e394d02a20ac49b7f65292d19d38fa927a8f9582cdfd3ad1adbbc66c641ad5"}, -] -scramp = [ - {file = "scramp-1.4.1-py3-none-any.whl", hash = "sha256:93c9cc2ffe54a451e02981c07a5a23cbd830701102789939cfb4ff91efd6ca8c"}, - {file = "scramp-1.4.1.tar.gz", hash = "sha256:f964801077be9be2a1416ffe255d2d78834b3d9d5c8ce5d28f76a856f209f70e"}, -] -selenium = [ - {file = "selenium-4.1.0-py3-none-any.whl", hash = "sha256:27e7b64df961d609f3d57237caa0df123abbbe22d038f2ec9e332fb90ec1a939"}, -] -sentry-sdk = [ - {file = "sentry-sdk-1.5.0.tar.gz", hash = "sha256:789a11a87ca02491896e121efdd64e8fd93327b69e8f2f7d42f03e2569648e88"}, - {file = "sentry_sdk-1.5.0-py2.py3-none-any.whl", hash = "sha256:0db297ab32e095705c20f742c3a5dac62fe15c4318681884053d0898e5abb2f6"}, -] -six = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] -smmap = [ - {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, - {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, -] -sniffio = [ - {file = "sniffio-1.2.0-py3-none-any.whl", hash = "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663"}, - {file = "sniffio-1.2.0.tar.gz", hash = "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"}, -] -snowballstemmer = [ - {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, - {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, -] -sortedcontainers = [ - {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, - {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, -] -soupsieve = [ - {file = "soupsieve-2.3.1-py3-none-any.whl", hash = "sha256:1a3cca2617c6b38c0343ed661b1fa5de5637f257d4fe22bd9f1338010a1efefb"}, - {file = "soupsieve-2.3.1.tar.gz", hash = "sha256:b8d49b1cd4f037c7082a9683dfa1801aa2597fb11c3a1155b7a5b94829b4f1f9"}, -] -spdx-license-list = [ - {file = "spdx_license_list-0.5.2-py3-none-any.whl", hash = "sha256:1b338470c7b403dbecceca563a316382c7977516128ca6c1e8f7078e3ed6e7b0"}, - {file = "spdx_license_list-0.5.2.tar.gz", hash = "sha256:952996f72ab807972dc2278bb9b91e5294767211e51f09aad9c0e2ff5b82a31b"}, -] -sphinx = [ - {file = "Sphinx-3.5.4-py3-none-any.whl", hash = "sha256:2320d4e994a191f4b4be27da514e46b3d6b420f2ff895d064f52415d342461e8"}, - {file = "Sphinx-3.5.4.tar.gz", hash = "sha256:19010b7b9fa0dc7756a6e105b2aacd3a80f798af3c25c273be64d7beeb482cb1"}, -] -sphinx-autodoc-typehints = [ - {file = "sphinx-autodoc-typehints-1.12.0.tar.gz", hash = "sha256:193617d9dbe0847281b1399d369e74e34cd959c82e02c7efde077fca908a9f52"}, - {file = "sphinx_autodoc_typehints-1.12.0-py3-none-any.whl", hash = "sha256:5e81776ec422dd168d688ab60f034fccfafbcd94329e9537712c93003bddc04a"}, -] -sphinx-materialdesign-theme = [ - {file = "sphinx_materialdesign_theme-0.1.11.tar.gz", hash = "sha256:6e9dae4c6e5ba23c0657a94c1cf65f64be9c8bc1594a6fb41815f7daa3326aa9"}, -] -sphinxcontrib-applehelp = [ - {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, - {file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"}, -] -sphinxcontrib-devhelp = [ - {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, - {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, -] -sphinxcontrib-django = [ - {file = "sphinxcontrib-django-0.5.1.tar.gz", hash = "sha256:3b48a9067d8db4713d47e3a4160af10288d02d448c866d1b44b001adbe74cc1e"}, - {file = "sphinxcontrib_django-0.5.1-py2.py3-none-any.whl", hash = "sha256:73ef7fdbf2ed6d4f35b7ae709032bd5ac493d93cedd0624ea7b51bf5fce41267"}, -] -sphinxcontrib-htmlhelp = [ - {file = "sphinxcontrib-htmlhelp-2.0.0.tar.gz", hash = "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"}, - {file = "sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", hash = "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07"}, -] -sphinxcontrib-jsmath = [ - {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, - {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, -] -sphinxcontrib-qthelp = [ - {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, - {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, -] -sphinxcontrib-serializinghtml = [ - {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, - {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, -] -sqlparse = [ - {file = "sqlparse-0.4.2-py3-none-any.whl", hash = "sha256:48719e356bb8b42991bdbb1e8b83223757b93789c00910a616a071910ca4a64d"}, - {file = "sqlparse-0.4.2.tar.gz", hash = "sha256:0c00730c74263a94e5a9919ade150dfc3b19c574389985446148402998287dae"}, -] -stevedore = [ - {file = "stevedore-3.5.0-py3-none-any.whl", hash = "sha256:a547de73308fd7e90075bb4d301405bebf705292fa90a90fc3bcf9133f58616c"}, - {file = "stevedore-3.5.0.tar.gz", hash = "sha256:f40253887d8712eaa2bb0ea3830374416736dc8ec0e22f5a65092c1174c44335"}, -] -svglib = [ - {file = "svglib-1.1.0.tar.gz", hash = "sha256:520ee5290ee2ebeebd20ca0d7d995c08c903b364fcf515826bab43a1288d422e"}, -] -termcolor = [ - {file = "termcolor-1.1.0.tar.gz", hash = "sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b"}, -] -testfixtures = [ - {file = "testfixtures-6.18.3-py2.py3-none-any.whl", hash = "sha256:6ddb7f56a123e1a9339f130a200359092bd0a6455e31838d6c477e8729bb7763"}, - {file = "testfixtures-6.18.3.tar.gz", hash = "sha256:2600100ae96ffd082334b378e355550fef8b4a529a6fa4c34f47130905c7426d"}, -] -"testing.common.database" = [ - {file = "testing.common.database-2.0.3-py2.py3-none-any.whl", hash = "sha256:e3ed492bf480a87f271f74c53b262caf5d85c8bc09989a8f534fa2283ec52492"}, - {file = "testing.common.database-2.0.3.tar.gz", hash = "sha256:965d80b2985315325dc358c3061b174a712f4d4d5bf6a80b58b11f9a1dd86d73"}, -] -"testing.postgresql" = [ - {file = "testing.postgresql-1.3.0-py2.py3-none-any.whl", hash = "sha256:1b41daeb98dfc8cd4a584bb91e8f5f4ab182993870f95257afe5f1ba6151a598"}, - {file = "testing.postgresql-1.3.0.tar.gz", hash = "sha256:8e1a69760369a7a8ffe63a66b6d95a5cd82db2fb976e4a8f85ffd24fbfc447d8"}, -] -tinycss2 = [ - {file = "tinycss2-1.1.1-py3-none-any.whl", hash = "sha256:fe794ceaadfe3cf3e686b22155d0da5780dd0e273471a51846d0a02bc204fec8"}, - {file = "tinycss2-1.1.1.tar.gz", hash = "sha256:b2e44dd8883c360c35dd0d1b5aad0b610e5156c2cb3b33434634e539ead9d8bf"}, -] -toml = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] -tomli = [ - {file = "tomli-1.2.2-py3-none-any.whl", hash = "sha256:f04066f68f5554911363063a30b108d2b5a5b1a010aa8b6132af78489fe3aade"}, - {file = "tomli-1.2.2.tar.gz", hash = "sha256:c6ce0015eb38820eaf32b5db832dbc26deb3dd427bd5f6556cf0acac2c214fee"}, -] -traitlets = [ - {file = "traitlets-5.1.1-py3-none-any.whl", hash = "sha256:2d313cc50a42cd6c277e7d7dc8d4d7fedd06a2c215f78766ae7b1a66277e0033"}, - {file = "traitlets-5.1.1.tar.gz", hash = "sha256:059f456c5a7c1c82b98c2e8c799f39c9b8128f6d0d46941ee118daace9eb70c7"}, -] -trio = [ - {file = "trio-0.19.0-py3-none-any.whl", hash = "sha256:c27c231e66336183c484fbfe080fa6cc954149366c15dc21db8b7290081ec7b8"}, - {file = "trio-0.19.0.tar.gz", hash = "sha256:895e318e5ec5e8cea9f60b473b6edb95b215e82d99556a03eb2d20c5e027efe1"}, -] -trio-websocket = [ - {file = "trio-websocket-0.9.2.tar.gz", hash = "sha256:a3d34de8fac26023eee701ed1e7bf4da9a8326b61a62934ec9e53b64970fd8fe"}, - {file = "trio_websocket-0.9.2-py3-none-any.whl", hash = "sha256:5b558f6e83cc20a37c3b61202476c5295d1addf57bd65543364e0337e37ed2bc"}, -] -twilio = [ - {file = "twilio-7.3.2-py2.py3-none-any.whl", hash = "sha256:6cc6ed114b07a7ce853503a5a27281f56237b411ea415012955cff3a57045f1b"}, - {file = "twilio-7.3.2.tar.gz", hash = "sha256:3170da33c7f4293bbebcd032b183866e044fcf8418e5c5e15bdd5ec7a0a958b6"}, -] -types-pytz = [ - {file = "types-pytz-2021.3.1.tar.gz", hash = "sha256:dffd77f3efecd3b1555f187a9bf3a638d55fac296700b829c41bd51ec72a6eb7"}, - {file = "types_pytz-2021.3.1-py3-none-any.whl", hash = "sha256:d58a0688094b768d8e21c044e45861cbcaecba0494fd5b9c5feb3e1739211606"}, -] -types-pyyaml = [ - {file = "types-PyYAML-6.0.1.tar.gz", hash = "sha256:2e27b0118ca4248a646101c5c318dc02e4ca2866d6bc42e84045dbb851555a76"}, - {file = "types_PyYAML-6.0.1-py3-none-any.whl", hash = "sha256:d5b318269652e809b5c30a5fe666c50159ab80bfd41cd6bafe655bf20b29fcba"}, -] -typing-extensions = [ - {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"}, - {file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"}, -] -urllib3 = [ - {file = "urllib3-1.26.7-py2.py3-none-any.whl", hash = "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"}, - {file = "urllib3-1.26.7.tar.gz", hash = "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece"}, -] -uwsgi = [ - {file = "uwsgi-2.0.20.tar.gz", hash = "sha256:88ab9867d8973d8ae84719cf233b7dafc54326fcaec89683c3f9f77c002cdff9"}, -] -vine = [ - {file = "vine-5.0.0-py2.py3-none-any.whl", hash = "sha256:4c9dceab6f76ed92105027c49c823800dd33cacce13bdedc5b914e3514b7fb30"}, - {file = "vine-5.0.0.tar.gz", hash = "sha256:7d3b1624a953da82ef63462013bbd271d3eb75751489f9807598e8f340bd637e"}, -] -wcwidth = [ - {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, - {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, -] -webencodings = [ - {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, - {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, -] -whoosh = [ - {file = "Whoosh-2.7.4-py2.py3-none-any.whl", hash = "sha256:aa39c3c3426e3fd107dcb4bde64ca1e276a65a889d9085a6e4b54ba82420a852"}, - {file = "Whoosh-2.7.4.tar.gz", hash = "sha256:7ca5633dbfa9e0e0fa400d3151a8a0c4bec53bd2ecedc0a67705b17565c31a83"}, - {file = "Whoosh-2.7.4.zip", hash = "sha256:e0857375f63e9041e03fedd5b7541f97cf78917ac1b6b06c1fcc9b45375dda69"}, -] -wrapt = [ - {file = "wrapt-1.13.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:e05e60ff3b2b0342153be4d1b597bbcfd8330890056b9619f4ad6b8d5c96a81a"}, - {file = "wrapt-1.13.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:85148f4225287b6a0665eef08a178c15097366d46b210574a658c1ff5b377489"}, - {file = "wrapt-1.13.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:2dded5496e8f1592ec27079b28b6ad2a1ef0b9296d270f77b8e4a3a796cf6909"}, - {file = "wrapt-1.13.3-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:e94b7d9deaa4cc7bac9198a58a7240aaf87fe56c6277ee25fa5b3aa1edebd229"}, - {file = "wrapt-1.13.3-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:498e6217523111d07cd67e87a791f5e9ee769f9241fcf8a379696e25806965af"}, - {file = "wrapt-1.13.3-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ec7e20258ecc5174029a0f391e1b948bf2906cd64c198a9b8b281b811cbc04de"}, - {file = "wrapt-1.13.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:87883690cae293541e08ba2da22cacaae0a092e0ed56bbba8d018cc486fbafbb"}, - {file = "wrapt-1.13.3-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:f99c0489258086308aad4ae57da9e8ecf9e1f3f30fa35d5e170b4d4896554d80"}, - {file = "wrapt-1.13.3-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:6a03d9917aee887690aa3f1747ce634e610f6db6f6b332b35c2dd89412912bca"}, - {file = "wrapt-1.13.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:936503cb0a6ed28dbfa87e8fcd0a56458822144e9d11a49ccee6d9a8adb2ac44"}, - {file = "wrapt-1.13.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f9c51d9af9abb899bd34ace878fbec8bf357b3194a10c4e8e0a25512826ef056"}, - {file = "wrapt-1.13.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:220a869982ea9023e163ba915077816ca439489de6d2c09089b219f4e11b6785"}, - {file = "wrapt-1.13.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:0877fe981fd76b183711d767500e6b3111378ed2043c145e21816ee589d91096"}, - {file = "wrapt-1.13.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:43e69ffe47e3609a6aec0fe723001c60c65305784d964f5007d5b4fb1bc6bf33"}, - {file = "wrapt-1.13.3-cp310-cp310-win32.whl", hash = "sha256:78dea98c81915bbf510eb6a3c9c24915e4660302937b9ae05a0947164248020f"}, - {file = "wrapt-1.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:ea3e746e29d4000cd98d572f3ee2a6050a4f784bb536f4ac1f035987fc1ed83e"}, - {file = "wrapt-1.13.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:8c73c1a2ec7c98d7eaded149f6d225a692caa1bd7b2401a14125446e9e90410d"}, - {file = "wrapt-1.13.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:086218a72ec7d986a3eddb7707c8c4526d677c7b35e355875a0fe2918b059179"}, - {file = "wrapt-1.13.3-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:e92d0d4fa68ea0c02d39f1e2f9cb5bc4b4a71e8c442207433d8db47ee79d7aa3"}, - {file = "wrapt-1.13.3-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:d4a5f6146cfa5c7ba0134249665acd322a70d1ea61732723c7d3e8cc0fa80755"}, - {file = "wrapt-1.13.3-cp35-cp35m-win32.whl", hash = "sha256:8aab36778fa9bba1a8f06a4919556f9f8c7b33102bd71b3ab307bb3fecb21851"}, - {file = "wrapt-1.13.3-cp35-cp35m-win_amd64.whl", hash = "sha256:944b180f61f5e36c0634d3202ba8509b986b5fbaf57db3e94df11abee244ba13"}, - {file = "wrapt-1.13.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:2ebdde19cd3c8cdf8df3fc165bc7827334bc4e353465048b36f7deeae8ee0918"}, - {file = "wrapt-1.13.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:610f5f83dd1e0ad40254c306f4764fcdc846641f120c3cf424ff57a19d5f7ade"}, - {file = "wrapt-1.13.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5601f44a0f38fed36cc07db004f0eedeaadbdcec90e4e90509480e7e6060a5bc"}, - {file = "wrapt-1.13.3-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:e6906d6f48437dfd80464f7d7af1740eadc572b9f7a4301e7dd3d65db285cacf"}, - {file = "wrapt-1.13.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:766b32c762e07e26f50d8a3468e3b4228b3736c805018e4b0ec8cc01ecd88125"}, - {file = "wrapt-1.13.3-cp36-cp36m-win32.whl", hash = "sha256:5f223101f21cfd41deec8ce3889dc59f88a59b409db028c469c9b20cfeefbe36"}, - {file = "wrapt-1.13.3-cp36-cp36m-win_amd64.whl", hash = "sha256:f122ccd12fdc69628786d0c947bdd9cb2733be8f800d88b5a37c57f1f1d73c10"}, - {file = "wrapt-1.13.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:46f7f3af321a573fc0c3586612db4decb7eb37172af1bc6173d81f5b66c2e068"}, - {file = "wrapt-1.13.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:778fd096ee96890c10ce96187c76b3e99b2da44e08c9e24d5652f356873f6709"}, - {file = "wrapt-1.13.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0cb23d36ed03bf46b894cfec777eec754146d68429c30431c99ef28482b5c1df"}, - {file = "wrapt-1.13.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:96b81ae75591a795d8c90edc0bfaab44d3d41ffc1aae4d994c5aa21d9b8e19a2"}, - {file = "wrapt-1.13.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7dd215e4e8514004c8d810a73e342c536547038fb130205ec4bba9f5de35d45b"}, - {file = "wrapt-1.13.3-cp37-cp37m-win32.whl", hash = "sha256:47f0a183743e7f71f29e4e21574ad3fa95676136f45b91afcf83f6a050914829"}, - {file = "wrapt-1.13.3-cp37-cp37m-win_amd64.whl", hash = "sha256:fd76c47f20984b43d93de9a82011bb6e5f8325df6c9ed4d8310029a55fa361ea"}, - {file = "wrapt-1.13.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b73d4b78807bd299b38e4598b8e7bd34ed55d480160d2e7fdaabd9931afa65f9"}, - {file = "wrapt-1.13.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ec9465dd69d5657b5d2fa6133b3e1e989ae27d29471a672416fd729b429eb554"}, - {file = "wrapt-1.13.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dd91006848eb55af2159375134d724032a2d1d13bcc6f81cd8d3ed9f2b8e846c"}, - {file = "wrapt-1.13.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ae9de71eb60940e58207f8e71fe113c639da42adb02fb2bcbcaccc1ccecd092b"}, - {file = "wrapt-1.13.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:51799ca950cfee9396a87f4a1240622ac38973b6df5ef7a41e7f0b98797099ce"}, - {file = "wrapt-1.13.3-cp38-cp38-win32.whl", hash = "sha256:4b9c458732450ec42578b5642ac53e312092acf8c0bfce140ada5ca1ac556f79"}, - {file = "wrapt-1.13.3-cp38-cp38-win_amd64.whl", hash = "sha256:7dde79d007cd6dfa65afe404766057c2409316135cb892be4b1c768e3f3a11cb"}, - {file = "wrapt-1.13.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:981da26722bebb9247a0601e2922cedf8bb7a600e89c852d063313102de6f2cb"}, - {file = "wrapt-1.13.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:705e2af1f7be4707e49ced9153f8d72131090e52be9278b5dbb1498c749a1e32"}, - {file = "wrapt-1.13.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:25b1b1d5df495d82be1c9d2fad408f7ce5ca8a38085e2da41bb63c914baadff7"}, - {file = "wrapt-1.13.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:77416e6b17926d953b5c666a3cb718d5945df63ecf922af0ee576206d7033b5e"}, - {file = "wrapt-1.13.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:865c0b50003616f05858b22174c40ffc27a38e67359fa1495605f96125f76640"}, - {file = "wrapt-1.13.3-cp39-cp39-win32.whl", hash = "sha256:0a017a667d1f7411816e4bf214646d0ad5b1da2c1ea13dec6c162736ff25a374"}, - {file = "wrapt-1.13.3-cp39-cp39-win_amd64.whl", hash = "sha256:81bd7c90d28a4b2e1df135bfbd7c23aee3050078ca6441bead44c42483f9ebfb"}, - {file = "wrapt-1.13.3.tar.gz", hash = "sha256:1fea9cd438686e6682271d36f3481a9f3636195578bab9ca3382e2f5f01fc185"}, -] -wsproto = [ - {file = "wsproto-1.0.0-py3-none-any.whl", hash = "sha256:d8345d1808dd599b5ffb352c25a367adb6157e664e140dbecba3f9bc007edb9f"}, - {file = "wsproto-1.0.0.tar.gz", hash = "sha256:868776f8456997ad0d9720f7322b746bbe9193751b5b290b7f924659377c8c38"}, -] -yubiotp = [ - {file = "YubiOTP-1.0.0.post1-py2.py3-none-any.whl", hash = "sha256:7ad57011866e0bc6c6d179ffbc3926fcc0e82d410178a6d01ba4da0f88332878"}, - {file = "YubiOTP-1.0.0.post1.tar.gz", hash = "sha256:c13825f7b76a69afb92f19521f4dea9f5031d70f45123b505dc2e0ac03132065"}, -] diff --git a/pyproject.toml b/pyproject.toml index 68707b75ac229f3e68b91bdc9a4e34ac158b0137..f0cfec6f98e15956eabf2efa6abc60651b16504e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,11 +1,18 @@ [tool.poetry] name = "AlekSIS-Core" -version = "2.3.dev0" +version = "2.5.1.dev0" packages = [ { include = "aleksis" } ] readme = "README.rst" -include = ["CHANGELOG.rst", "LICENCE.rst", "docs/*", "docs/**/*", "aleksis/**/*.mo", "conftest.py", "tox.ini"] +include = [ + { path = "aleksis/**/*.mo", format = ["sdist", "wheel"] }, + { path = "*.rst", format = "sdist" }, + { path = "docs/*", format = "sdist" }, + { path = "docs/**/*", format = "sdist" }, + { path = "conftest.py", format = "sdist" }, + { path = "tox.ini", format = "sdist" } +] description = "AlekSIS (School Information System) — Core" authors = [ @@ -57,7 +64,7 @@ django-sass-processor = "1.0" libsass = "^0.21.0" colour = "^0.1.5" dynaconf = {version = "^3.1", extras = ["yaml", "toml", "ini"]} -django-auth-ldap = { version = "^3.0", optional = true } +django-auth-ldap = { version = "^4.0", optional = true } django-maintenance-mode = "^0.16.0" django-ipware = "^4.0" django-impersonate = "^1.4" @@ -74,19 +81,19 @@ html2text = "^2020.0.0" django-ckeditor = "^6.0.0" django-js-reverse = "^0.9.1" calendarweek = "^0.5.0" -Celery = {version=">=5.0,<5.2", extras=["django", "redis"]} +Celery = {version="^5.2", extras=["django", "redis"]} django-celery-results = "^2.0.1" django-celery-beat = "^2.2.0" django-celery-email = "^3.0.0" django-jsonstore = "^0.5.0" django-polymorphic = "^3.0.0" -django-colorfield = "^0.5.0" +django-colorfield = "^0.6.0" django-bleach = "^1.0.0" django-guardian = "^2.2.0" rules = "^3.0" django-cache-memoize = "^0.1.6" django-haystack = "^3.1" -celery-haystack-ng = "^0.20" +celery-haystack-ng = "^0.21.1" django-dbbackup = "^3.3.0" spdx-license-list = "^0.5.0" license-expression = "^21.6" @@ -99,11 +106,13 @@ django-cachalot = "^2.3.2" django-prometheus = "^2.1.0" django-model-utils = "^4.0.0" bs4 = "^0.0.1" -django-allauth = "^0.46.0" +django-invitations = "^1.9.3" +django-cleavejs = "^0.1.0" +django-allauth = "^0.47.0" django-uwsgi-ng = "^1.1.0" django-extensions = "^3.1.1" ipython = "^7.20.0" -django-oauth-toolkit = "^1.5.0" +django-oauth-toolkit = "^1.6.2" django-redis = "^5.0.0" django-storages = {version = "^1.11.1", optional = true} boto3 = {version = "^1.17.33", optional = true} @@ -116,11 +125,13 @@ python-gnupg = "^0.4.7" sentry-sdk = {version = "^1.4.3", optional = true} django-image-cropping = "^1.6.1" easy-thumbnails = "^2.8" +django-cte = "^1.1.5" +pycountry = "^20.7.3" [tool.poetry.extras] ldap = ["django-auth-ldap"] s3 = ["boto3", "django-storages"] -sentry = ["sentry"] +sentry = ["sentry-sdk"] [tool.poetry.dev-dependencies] aleksis-builddeps = "^5" diff --git a/tox.ini b/tox.ini index 6ba5d926ea520a574125f4a9717b93ba0020a2c3..4819e5b95946e3f021429e75c36fe13e7dd61d25 100644 --- a/tox.ini +++ b/tox.ini @@ -9,7 +9,7 @@ whitelist_externals = poetry skip_install = true envdir = {toxworkdir}/globalenv commands_pre = - poetry install + poetry install -E ldap poetry run aleksis-admin yarn install poetry run aleksis-admin collectstatic --no-input commands =