diff --git a/Ctl/dev/auto_pdb_load_data.sh b/Ctl/dev/auto_pdb_load_data.sh new file mode 100755 index 00000000..cf4d9e90 --- /dev/null +++ b/Ctl/dev/auto_pdb_load_data.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +AUTO_PDB_LOAD_DATA_DIR="/srv/www.peeringdb.com/peeringdb_server/scripts/auto_pdb_load_data.py" +PID=$(docker exec peeringdb pgrep -f "python $AUTO_PDB_LOAD_DATA_DIR") + +if [ "$1" = "" ]; then + echo "use '-h' or 'help' for usage" + exit 1 +elif [ "$1" = "start" ]; then + if [[ -n $PID ]]; then + echo "The automated pdb_load_data already started" + exit 1 + else + COMMAND="python $AUTO_PDB_LOAD_DATA_DIR >> /var/log/auto_pdb_load_data.log 2>&1 &" + echo "Starting the automated pdb_load_data" + fi +elif [ "$1" = "stop" ]; then + if [[ -n $PID ]]; then + COMMAND="kill $PID" + echo "The automated pdb_load_data has been stopped" + else + echo "cron process not found" + exit 1 + fi +elif [ "$1" = "log" ]; then + COMMAND="cat /var/log/auto_pdb_load_data.log" +elif [ "$1" = "-h" ] || [ "$1" = "help" ]; then + echo "Usage: ./Ctl/dev/auto_pdb_load_data.sh" + echo "" + echo "Available options:" + echo " start Start automated service to run pdb_load_data" + echo " stop Stop automated pdb_load_data command" + echo " log Show log" + exit 1 +else + echo "$1 is not an option, use '-h' or 'help' for usage" + exit 1 +fi + +docker exec peeringdb sh -c "$COMMAND" diff --git a/Ctl/dev/docker-compose.yml b/Ctl/dev/docker-compose.yml index f40129f7..1943a9ed 100644 --- a/Ctl/dev/docker-compose.yml +++ b/Ctl/dev/docker-compose.yml @@ -22,9 +22,11 @@ services: context: ../.. dockerfile: Dockerfile target: tester + container_name: peeringdb command: runserver 0.0.0.0:8000 env_file: .env depends_on: + - database - elasticsearch environment: DATABASE_USER: peeringdb diff --git a/Ctl/dev/setup.sh b/Ctl/dev/setup.sh new file mode 100755 index 00000000..278e983c --- /dev/null +++ b/Ctl/dev/setup.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +if [ "$1" = "" ]; then + cron="on" +elif [ "$1" = "disable" ]; then + cron="off" +elif [ "$1" = "-h" ] || [ "$1" = "help" ]; then + echo "Usage: ./Ctl/dev/setup.sh" + echo "" + echo "Available options:" + echo " disable Disable automated generate data from pdb_load_data command" + echo " help Show available commands" + exit 1 +else + echo "$1 is not an option, use '-h' or 'help' for usage" + exit 1 +fi + +./Ctl/dev/compose.sh build peeringdb +./Ctl/dev/compose.sh up -d database +./Ctl/dev/run.sh migrate +until ./Ctl/dev/run.sh migrate; do + echo "Migrations failed. Retrying in 5 seconds..." + sleep 5 +done +./Ctl/dev/run.sh loaddata fixtures/initial_data.json +./Ctl/dev/run.sh createsuperuser +./Ctl/dev/run.sh createcachetable +./Ctl/dev/compose.sh up -d peeringdb +if [ "$cron" = "on" ]; then + ./Ctl/dev/auto_pdb_load_data.sh start +fi diff --git a/Ctl/docker/entrypoint.sh b/Ctl/docker/entrypoint.sh index 8dd96b68..3d46b31d 100755 --- a/Ctl/docker/entrypoint.sh +++ b/Ctl/docker/entrypoint.sh @@ -12,6 +12,7 @@ function migrate() { cd /srv/www.peeringdb.com + case "$1" in "uwsgi" ) echo starting uwsgi @@ -35,6 +36,7 @@ case "$1" in export DATABASE_USER=root export DATABASE_PASSWORD="" export RELEASE_ENV=run_tests + export PEERINGDB_SYNC_CACHE_URL="" unset BASE_URL unset OAUTH2_PROVIDER_APPLICATION_MODEL unset SESSION_COOKIE_DOMAIN diff --git a/Ctl/local/auto_pdb_load_data.sh b/Ctl/local/auto_pdb_load_data.sh new file mode 100755 index 00000000..84a85fa8 --- /dev/null +++ b/Ctl/local/auto_pdb_load_data.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +AUTO_PDB_LOAD_DATA_DIR="/srv/www.peeringdb.com/peeringdb_server/scripts/auto_pdb_load_data.py" +PID=$(docker exec peeringdb pgrep -f "python $AUTO_PDB_LOAD_DATA_DIR") + +if [ "$1" = "" ]; then + echo "use '-h' or 'help' for usage" + exit 1 +elif [ "$1" = "start" ]; then + if [[ -n $PID ]]; then + echo "The automated pdb_load_data already started" + exit 1 + else + COMMAND="python $AUTO_PDB_LOAD_DATA_DIR >> /var/log/auto_pdb_load_data.log 2>&1 &" + echo "Starting the automated pdb_load_data" + fi +elif [ "$1" = "stop" ]; then + if [[ -n $PID ]]; then + COMMAND="kill $PID" + echo "The automated pdb_load_data has been stopped" + else + echo "cron process not found" + exit 1 + fi +elif [ "$1" = "log" ]; then + COMMAND="cat /var/log/auto_pdb_load_data.log" +elif [ "$1" = "-h" ] || [ "$1" = "help" ]; then + echo "Usage: ./Ctl/local/auto_pdb_load_data.sh" + echo "" + echo "Available options:" + echo " start Start automated service to run pdb_load_data" + echo " stop Stop automated pdb_load_data command" + echo " log Show log" + exit 1 +else + echo "$1 is not an option, use '-h' or 'help' for usage" + exit 1 +fi + +docker exec peeringdb sh -c "$COMMAND" diff --git a/Ctl/local/compose.sh b/Ctl/local/compose.sh new file mode 100755 index 00000000..124f2394 --- /dev/null +++ b/Ctl/local/compose.sh @@ -0,0 +1,10 @@ +#!/bin/bash + + +COMPOSE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +PROJECT_NAME=$(basename $(git rev-parse --show-toplevel))$(basename $COMPOSE_DIR) + +docker-compose -p $PROJECT_NAME -f $COMPOSE_DIR/docker-compose.yml $@ +if [[ "$@" == *"up -d peeringdb"* ]]; then + ./Ctl/local/auto_pdb_load_data.sh start +fi diff --git a/Ctl/local/docker-compose.yml b/Ctl/local/docker-compose.yml new file mode 100644 index 00000000..4a3073f7 --- /dev/null +++ b/Ctl/local/docker-compose.yml @@ -0,0 +1,49 @@ +version: "3.4" +services: + database: + image: "mysql:8" + environment: + MYSQL_DATABASE: peeringdb + MYSQL_USER: peeringdb + MYSQL_PASSWORD: devPASSWORD + MYSQL_ALLOW_EMPTY_PASSWORD: 1 + restart: always + ports: + - "23306:3306" + volumes: + - peeringdb_database:/var/lib/mysql:Z + networks: + - peeringdb_local_network + + peeringdb: + user: "0:0" + image: ghcr.io/peeringdb/peeringdb-server:latest + container_name: peeringdb + command: runserver 0.0.0.0:8000 + env_file: .env + depends_on: + - database + - elasticsearch + environment: + DATABASE_USER: peeringdb + DATABASE_PASSWORD: devPASSWORD + DATABASE_HOST: database + ports: + - "${DJANGO_PORT:-8000}:8000" + networks: + - peeringdb_local_network + + elasticsearch: + image: docker.elastic.co/elasticsearch/elasticsearch:7.6.1 + ports: + - "19200:9200" + environment: + - discovery.type=single-node + networks: + - peeringdb_local_network + +volumes: + peeringdb_database: + +networks: + peeringdb_local_network: diff --git a/Ctl/local/env.example b/Ctl/local/env.example new file mode 100644 index 00000000..e69de29b diff --git a/Ctl/local/exec.sh b/Ctl/local/exec.sh new file mode 100755 index 00000000..2ee68f65 --- /dev/null +++ b/Ctl/local/exec.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +COMPOSE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +PROJECT_NAME=$(basename $(git rev-parse --show-toplevel))$(basename $COMPOSE_DIR) + +docker-compose -p $PROJECT_NAME -f $COMPOSE_DIR/docker-compose.yml exec peeringdb manage $@ diff --git a/Ctl/local/run.sh b/Ctl/local/run.sh new file mode 100755 index 00000000..87a46b1e --- /dev/null +++ b/Ctl/local/run.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +COMPOSE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +PROJECT_NAME=$(basename $(git rev-parse --show-toplevel))$(basename $COMPOSE_DIR) + +docker-compose -p $PROJECT_NAME -f $COMPOSE_DIR/docker-compose.yml run $run_options --rm peeringdb $@ diff --git a/Ctl/local/setup.sh b/Ctl/local/setup.sh new file mode 100755 index 00000000..1b7dc24c --- /dev/null +++ b/Ctl/local/setup.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +if [ "$1" = "" ]; then + cron="on" +elif [ "$1" = "disable" ]; then + cron="off" +elif [ "$1" = "-h" ] || [ "$1" = "help" ]; then + echo "Usage: ./Ctl/local/setup.sh" + echo "" + echo "Available options:" + echo " disable Disable automated generate data from pdb_load_data command" + echo " help Show available commands" + exit 1 +else + echo "$1 is not an option, use '-h' or 'help' for usage" + exit 1 +fi + +# Check if .env file exists, if not copy from example.env +if [ ! -f ./Ctl/local/.env ]; then + cp ./Ctl/local/env.example ./Ctl/local/.env +fi + +./Ctl/local/compose.sh build peeringdb +./Ctl/local/compose.sh up -d database +./Ctl/local/run.sh migrate +until ./Ctl/local/run.sh migrate; do + echo "Migrations failed. Retrying in 5 seconds..." + sleep 5 +done +./Ctl/local/run.sh loaddata fixtures/initial_data.json + +#echo "--- Creating superuser ---" +#echo "" + +#./Ctl/local/run.sh createsuperuser +./Ctl/local/run.sh createcachetable + +echo "--- Starting PeeringDB ---" +echo "" +./Ctl/local/compose.sh up -d peeringdb + +echo "--- Loading PeeringDB data (this can take a while) ---" +echo "" +./Ctl/local/run.sh pdb_load_data --commit + +echo "--- Updating search index ---" +echo "" +./Ctl/local/run.sh search_index -f --rebuild + +echo "--- Fetching api-cache ---" +echo "" +./Ctl/local/exec.sh pdb_fetch_api_cache + +if [ "$cron" = "on" ]; then + echo "Starting automatic sync daemon" + ./Ctl/local/auto_pdb_load_data.sh start +fi diff --git a/docs/local_setup.md b/docs/local_setup.md new file mode 100644 index 00000000..7b8b1a3b --- /dev/null +++ b/docs/local_setup.md @@ -0,0 +1,58 @@ + +# Setting up a local peeringdb instance + +Note: if you're looking at setting up a developer instance please refer to the development instructions instead. + +This will set up an instance you can use to run a local snapshot of peeringdb. + +Usage: +```sh +./Ctl/local/setup.sh [option] +``` + +This is a bash script used to set up a local PeeringDB environment. The script takes an optional argument which can be either "disable" or "help". If no argument is provided, the script assumes that automated data synchronization from the production API is enabled. + +The script checks if the .env file exists, if not, it copies from env.example. + +It then builds the peeringdb container, sets up the database, runs migrations, loads initial data, creates a cache table, starts the PeeringDB container, loads PeeringDB data, updates the search index, fetches api-cache and if automated data generation is enabled, it starts the automatic sync daemon. + + +Options: +- disable: Disable automated generate data from pdb_load_data command +- help: Show available commands + +# Manually interacting with the automatic data sync + +This is a bash script used to manage the automated pdb_load_data service. The script takes one required argument which can be either "start", "stop", "log" or "help". + +The "start" option starts the automated pdb_load_data service if it's not already running. The "stop" option stops the automated pdb_load_data service if it's running. The "log" option shows the log of the automated pdb_load_data service. The "help" option shows the available commands. + +Usage: +```sh +./Ctl/local/auto_pdb_load_data.sh [option] +``` + +Options: +- start: Start automated service to run pdb_load_data +- stop: Stop automated pdb_load_data command +- log: Show log +- help: Show available commands + +# Example: automatic api cache regeneration + +Currently automatic api cache updates aren't scheduled on local instances, as they can take up a lot of resources. Here is an example of a python script that will regenerate the API cache of your instance every 1000 seconds. + +```py +import subprocess +import time + +def run_commands(): + """ + Run the specified shell commands every 5 minutes. + """ + while True: + subprocess.run(["Ctl/local/exec.sh", "pdb_api_cache", "--depth", "0"]) + time.sleep(1000) + +run_commands() +``` diff --git a/mainsite/oauth2/validators.py b/mainsite/oauth2/validators.py index c5a006ea..781f1b1f 100644 --- a/mainsite/oauth2/validators.py +++ b/mainsite/oauth2/validators.py @@ -5,6 +5,10 @@ from mainsite.oauth2.scopes import SupportedScopes class OIDCValidator(OAuth2Validator): + + # https://django-oauth-toolkit.readthedocs.io/en/latest/changelog.html#id12 + oidc_claim_scope = None + def get_additional_claims(self): """PeeringDB-specific claims added to the standard claims defined in a JWT token. diff --git a/mainsite/settings/__init__.py b/mainsite/settings/__init__.py index 98619e23..ae5a2ac0 100644 --- a/mainsite/settings/__init__.py +++ b/mainsite/settings/__init__.py @@ -811,6 +811,11 @@ CORS_ALLOW_METHODS = ["GET", "OPTIONS"] # allows PeeringDB to use external OAuth2 sources set_bool("OAUTH_ENABLED", False) +# https://django-oauth-toolkit.readthedocs.io/en/latest/changelog.html#id12 +# default changed to True in django-oauth-toolkit v2, set to False for now +# to avoid breaking existing clients +set_bool("PKCE_REQUIRED", False) + # enables OpenID Connect support set_bool("OIDC_ENABLED", True) @@ -840,6 +845,7 @@ MIDDLEWARE += ( OAUTH2_PROVIDER = { "OIDC_ENABLED": OIDC_ENABLED, "OIDC_RSA_PRIVATE_KEY": OIDC_RSA_PRIVATE_KEY, + "PKCE_REQUIRED": PKCE_REQUIRED, "OAUTH2_VALIDATOR_CLASS": "mainsite.oauth2.validators.OIDCValidator", "SCOPES": { SupportedScopes.OPENID: "OpenID Connect scope", @@ -1234,10 +1240,13 @@ set_option("DELETE_ORPHANED_USER_DAYS", 90) # Notify orphaned users n days before deletion set_option("NOTIFY_ORPHANED_USER_DAYS", 30) -# Grace peruid before a newly created user can be flagged for deletion +# Grace period before a newly created user can be flagged for deletion # This is so users have some time to affiliate naturally. (days) set_option("MIN_AGE_ORPHANED_USER_DAYS", 14) +# Notification period to notify organizations of users missing 2FA (days) +set_option("NOTIFY_MISSING_2FA_DAYS", 30) + # pdb_validate_data cache timeout default set_option("PDB_VALIDATE_DATA_CACHE_TIMEOUT", 3600) @@ -1307,4 +1316,8 @@ set_option("PEERINGDB_SYNC_PASSWORD", "") # If the api key is specified it will be used over the username and password set_option("PEERINGDB_SYNC_API_KEY", "") +# peeringdb sync cache +set_option("PEERINGDB_SYNC_CACHE_URL", "https://cache.peeringdb.com/api") +set_option("PEERINGDB_SYNC_CACHE_DIR", os.path.join(BASE_DIR, "sync-cache")) + print_debug(f"loaded settings for PeeringDB {PEERINGDB_VERSION} (DEBUG: {DEBUG})") diff --git a/peeringdb_server/admin.py b/peeringdb_server/admin.py index f048b8c3..8b038ea5 100644 --- a/peeringdb_server/admin.py +++ b/peeringdb_server/admin.py @@ -1713,6 +1713,14 @@ class UserOrgAffiliationRequestAdmin(ModelAdminWithUrlActions, ProtectedDeleteAd request, _("Cannot approve a canceled affiliation request") ) continue + if each.org.require_2fa and not each.user.has_2fa: + messages.error( + request, + _( + "Cannot approve while User has 2FA disabled - organization requires 2FA" + ), + ) + continue each.approve() each.notify_ownership_approved() diff --git a/peeringdb_server/client_adaptor/backend.py b/peeringdb_server/client_adaptor/backend.py index 925efa59..276646de 100644 --- a/peeringdb_server/client_adaptor/backend.py +++ b/peeringdb_server/client_adaptor/backend.py @@ -135,9 +135,17 @@ class Backend(BaseBackend): setattr(obj, field.name, value) if obj.HandleRef.tag == "ix": + obj._meta.get_field("updated").auto_now = False + obj._meta.get_field("created").auto_now = False obj.save(create_ixlan=False) + obj._meta.get_field("updated").auto_now = True + obj._meta.get_field("created").auto_now = True else: + obj._meta.get_field("updated").auto_now = False + obj._meta.get_field("created").auto_now = False obj.save() + obj._meta.get_field("updated").auto_now = True + obj._meta.get_field("created").auto_now = True def detect_uniqueness_error(self, exc): """ diff --git a/peeringdb_server/forms.py b/peeringdb_server/forms.py index 9b8dfc1c..c845cddb 100644 --- a/peeringdb_server/forms.py +++ b/peeringdb_server/forms.py @@ -250,6 +250,7 @@ class OrgUserOptions(forms.ModelForm): class Meta: model = Organization fields = [ + "require_2fa", "restrict_user_emails", "email_domains", "periodic_reauth", diff --git a/peeringdb_server/management/commands/pdb_api_test.py b/peeringdb_server/management/commands/pdb_api_test.py index 23068480..2d0e4b3a 100644 --- a/peeringdb_server/management/commands/pdb_api_test.py +++ b/peeringdb_server/management/commands/pdb_api_test.py @@ -1714,6 +1714,8 @@ class TestJSON(unittest.TestCase): """ Tests the carrier-facility creation and approval processes + + As of #1344 all carrierfac objects are automatically approved. """ # create carrer-facility @@ -1737,101 +1739,8 @@ class TestJSON(unittest.TestCase): assert carrierfac.facility == facility assert carrierfac.carrier == carrier - assert carrierfac.status == "pending" - - # only the facility org can approve - - response = self.db_org_admin._request( - f"carrierfac/{carrierfac.id}/approve", method="POST", data="{}" - ) - - assert response.status_code == 403 - - # give permissions to approve the carrier facility (same as facility org) - if hasattr(self, "org_key"): - self.org_key.grainy_permissions.add_permission( - f"peeringdb.organization.{facility.org.id}.facility", 15 - ) - else: - self.db_org_admin.user_inst.grainy_permissions.add_permission( - f"peeringdb.organization.{facility.org.id}.facility", 15 - ) - - # need to re-init rest client so permissions stick - self.db_org_admin = self.rest_client(URL, verbose=VERBOSE, **USER_ORG_ADMIN) - - response = self.db_org_admin._request( - f"carrierfac/{carrierfac.id}/approve", method="POST", data="{}" - ) - - assert response.status_code == 200 - - carrierfac.refresh_from_db() - assert carrierfac.status == "ok" - ########################################################################## - - def test_org_admin_002_reject_carrierfac(self): - """ - Tests the carrier-facility creation and rejection - processes - """ - - # create carrier-facility - - carrier = SHARED["carrier_rw_ok"] - facility = SHARED["fac_r_ok"] - - data = {"carrier_id": carrier.id, "fac_id": facility.id} - - r_data = ( - self.db_org_admin._request("carrierfac", method="POST", data=data) - .json() - .get("data")[0] - ) - - SHARED["carrierfac_id"] = r_data.get("id") - - carrierfac = CarrierFacility.objects.get(id=SHARED["carrierfac_id"]) - - # assert that the carrier-facility is status pending (needs to be rejected) - - assert carrierfac.facility == facility - assert carrierfac.carrier == carrier - assert carrierfac.status == "pending" - - # only the facility org can reject - - response = self.db_org_admin._request( - f"carrierfac/{carrierfac.id}/reject", method="POST", data="{}" - ) - - assert response.status_code == 403 - - # give permissions to approve the carrier facility (same as facility org) - if hasattr(self, "org_key"): - self.org_key.grainy_permissions.add_permission( - f"peeringdb.organization.{facility.org.id}.facility", 15 - ) - else: - self.db_org_admin.user_inst.grainy_permissions.add_permission( - f"peeringdb.organization.{facility.org.id}.facility", 15 - ) - - # need to re-init rest client so permissions stick - self.db_org_admin = self.rest_client(URL, verbose=VERBOSE, **USER_ORG_ADMIN) - - response = self.db_org_admin._request( - f"carrierfac/{carrierfac.id}/reject", method="POST", data="{}" - ) - - assert response.status_code == 200 - - carrierfac.refresh_from_db() - - assert carrierfac.status == "deleted" - def test_org_admin_002_auto_approve_carrierfac(self): """ Tests the carrier-facility creation and AUTO approval diff --git a/peeringdb_server/management/commands/pdb_fetch_api_cache.py b/peeringdb_server/management/commands/pdb_fetch_api_cache.py new file mode 100644 index 00000000..cb9ed613 --- /dev/null +++ b/peeringdb_server/management/commands/pdb_fetch_api_cache.py @@ -0,0 +1,46 @@ +""" +Django management command +Will fetch api cache files from PEERINGDB_SYNC_CACHE_URL to API_CACHE_ROOT +""" + +import json +import os +import sys +from urllib.parse import urljoin + +import requests +from django.conf import settings +from django.core.management.base import BaseCommand + +from peeringdb_server.models import REFTAG_MAP + + +class Command(BaseCommand): + + help = "Fetch api cache files from PEERINGDB_SYNC_CACHE_URL to API_CACHE_ROOT" + + def handle(self, *args, **options): + """ + Fetch api cache files from PEERINGDB_SYNC_CACHE_URL to API_CACHE_ROOT + """ + tags = REFTAG_MAP.keys() + + for tag in tags: + + url = urljoin(f"{settings.PEERINGDB_SYNC_CACHE_URL}/", tag) + "-0.json" + response = requests.get(url) + + # Make sure the request was successful + if response.status_code == 200: + data = response.json() + + # store the json data to a file in data/cache directory + cache_file_path = os.path.join(settings.API_CACHE_ROOT, f"{tag}-0.json") + with open(cache_file_path, "w") as file: + json.dump(data, file, indent=4) + self.stdout.write(f"Successfully fetched data for {tag} from {url}") + else: + self.stdout.write( + f"Error fetching data for {tag} from {url}: HTTP {response.status_code}" + ) + sys.exit(1) diff --git a/peeringdb_server/management/commands/pdb_load_data.py b/peeringdb_server/management/commands/pdb_load_data.py index 95ca83c4..eee270f0 100644 --- a/peeringdb_server/management/commands/pdb_load_data.py +++ b/peeringdb_server/management/commands/pdb_load_data.py @@ -63,6 +63,10 @@ class Command(BaseCommand): "--commit", action="store_true", help="will commit the changes" ) + parser.add_argument( + "--no-cache", action="store_true", help="will not use the sync cache" + ) + def handle(self, *args, **options): if settings.RELEASE_ENV != "dev" and not settings.TUTORIAL_MODE: self.stdout.write( @@ -83,7 +87,14 @@ class Command(BaseCommand): # settings.USE_TZ = True db_settings = settings.DATABASES.get("default") - sync_options = {"url": options.get("url")} + sync_options = { + "url": options.get("url"), + "cache_url": settings.PEERINGDB_SYNC_CACHE_URL, + "cache_dir": settings.PEERINGDB_SYNC_CACHE_DIR, + } + + if options.get("no_cache"): + sync_options["cache_url"] = "" # allow authentication for the sync (set as env vars) if settings.PEERINGDB_SYNC_API_KEY: @@ -96,6 +107,8 @@ class Command(BaseCommand): "No authentication configured for sync, using anonymous access - this may cause rate limiting issues. Set PEERINGDB_SYNC_API_KEY or PEERINGDB_SYNC_USERNAME and PEERINGDB_SYNC_PASSWORD to configure authentication." ) + print("Syncing data from {url}".format(**sync_options)) + config = { "sync": sync_options, "orm": { @@ -128,5 +141,10 @@ class Command(BaseCommand): # disable validation of parent status during sync settings.DATA_QUALITY_VALIDATE_PARENT_STATUS = False + # disable elasticsearch auto indexing if there are zero records + if pdb_models.Organization.objects.count() == 0: + settings.ELASTICSEARCH_DSL_AUTOSYNC = False + settings.ELASTICSEARCH_DSL_AUTO_REFRESH = False + client = Client(config) client.update_all(resource.all_resources(), since=None) diff --git a/peeringdb_server/management/commands/pdb_notify_2fa.py b/peeringdb_server/management/commands/pdb_notify_2fa.py new file mode 100644 index 00000000..4af72579 --- /dev/null +++ b/peeringdb_server/management/commands/pdb_notify_2fa.py @@ -0,0 +1,108 @@ +""" +Load initial data from another peeringdb instance using the REST API. +""" + +from datetime import timedelta + +from django.conf import settings +from django.core.management.base import BaseCommand +from django.template import loader +from django.urls import reverse +from django.utils import timezone + +from peeringdb_server.models import Organization + + +class Command(BaseCommand): + help = "Notify the organization user admins if the member of the organization that required 2fa has a member without 2fa enabled" + + def add_arguments(self, parser): + parser.add_argument( + "--commit", action="store_true", help="will commit the changes" + ) + + parser.add_argument("--limit", type=int, default=10) + + def handle(self, *args, **options): + + threshold = timezone.now() - timedelta(days=settings.NOTIFY_MISSING_2FA_DAYS) + + orgs_require_2fa = Organization.objects.filter( + require_2fa=True, + last_notified__lt=threshold, + status="ok", + ) | Organization.objects.filter( + require_2fa=True, + last_notified=None, + status="ok", + ) + + if options.get("limit"): + limit = options.get("limit") + orgs_require_2fa = orgs_require_2fa[:limit] + + if any( + not user.has_2fa + for org in Organization.objects.all() + for user in org.all_users + ): + for org in orgs_require_2fa: + users_without_2fa = [] + if org.all_users: + org_users_without_2fa = [ + user for user in org.all_users if not user.has_2fa + ] + users_without_2fa.extend(org_users_without_2fa) + if users_without_2fa: + if not options.get("commit"): + self.stdout.write(f"{org} would get emailed") + continue + self.notify_org(org, users_without_2fa) + + if not options.get("commit"): + self.stdout.write( + "Run the command with `--commit` if you are sure you want " + "to send notification to the organization admins.".format(**options) + ) + + def notify_org(self, org, users): + + users_without_2fa = [] + + for user in users: + users_without_2fa = [] + action_url = f"{settings.BASE_URL}{reverse('handle-2fa')}?org={org.id}&member={user.id}" + + message = loader.get_template( + "email/notify-org-member-disable-2fa.txt" + ).render( + { + "org": org.name, + "member": user, + "drop_member_url": f"{action_url}&action=drop", + "leave_member_affiliate_url": f"{action_url}&action=leave", + "cancel_2fa_url": f"{action_url}&action=disable", + "org_url": f"{settings.BASE_URL}/org/{org.id}#users", + "support_email": settings.DEFAULT_FROM_EMAIL, + } + ) + users_without_2fa.append(message) + + for admin_user in org.admin_usergroup.user_set.all(): + admin_user.email_user( + subject=f"The following users affiliated with {org.name} organization do not have 2FA turned on", + message=loader.get_template( + "email/notify-org-user-admin-2fa.txt" + ).render( + { + "org_name": org.name, + "users_without_2fa": users_without_2fa, + "org_url": f"{settings.BASE_URL}/org/{org.id}#users", + "support_email": settings.DEFAULT_FROM_EMAIL, + } + ), + ) + org.last_notified = ( + timezone.now() + ) # Update last_notified field to the current time + org.save() diff --git a/peeringdb_server/management/commands/pdb_wipe.py b/peeringdb_server/management/commands/pdb_wipe.py index 651fe862..136e1768 100644 --- a/peeringdb_server/management/commands/pdb_wipe.py +++ b/peeringdb_server/management/commands/pdb_wipe.py @@ -43,6 +43,9 @@ class Command(BaseCommand): self.load_data = options.get("load_data", False) self.load_data_url = options.get("load_data_url") + settings.ELASTICSEARCH_DSL_AUTOSYNC = False + settings.ELASTICSEARCH_DSL_AUTO_REFRESH = False + if not settings.TUTORIAL_MODE: self.log("Command can only be run with tutorial mode enabled") return @@ -75,6 +78,10 @@ class Command(BaseCommand): self.log("Cleared seassions") + self.log( + "Search indexes will need to be manually updated (if applicable) using the search_index command" + ) + if self.load_data: call_command( "pdb_load_data", diff --git a/peeringdb_server/migrations/0111_update_carrierfac_status.py b/peeringdb_server/migrations/0111_update_carrierfac_status.py new file mode 100644 index 00000000..ea3478e8 --- /dev/null +++ b/peeringdb_server/migrations/0111_update_carrierfac_status.py @@ -0,0 +1,17 @@ +from django.db import migrations + +from peeringdb_server.models import CarrierFacility + + +def update_carrierfac_status(apps, schema_editor): + CarrierFacility.objects.filter(status="pending").update(status="ok") + + +class Migration(migrations.Migration): + dependencies = [ + ("peeringdb_server", "0110_social_media"), + ] + + operations = [ + migrations.RunPython(update_carrierfac_status, migrations.RunPython.noop), + ] diff --git a/peeringdb_server/migrations/0112_organization_require_totpdevice_and_more.py b/peeringdb_server/migrations/0112_organization_require_totpdevice_and_more.py new file mode 100644 index 00000000..f5b02c4b --- /dev/null +++ b/peeringdb_server/migrations/0112_organization_require_totpdevice_and_more.py @@ -0,0 +1,65 @@ +# Generated by Django 4.2 on 2023-06-24 04:31 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("peeringdb_server", "0111_update_carrierfac_status"), + ] + + operations = [ + migrations.AddField( + model_name="organization", + name="require_2fa", + field=models.BooleanField( + default=False, + help_text="Require users in your organization to activate 2FA.", + ), + ), + migrations.AlterField( + model_name="oauthapplication", + name="user", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="%(app_label)s_%(class)s", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AlterField( + model_name="organizationapikey", + name="hashed_key", + field=models.CharField(editable=False, max_length=150), + ), + migrations.AlterField( + model_name="organizationapikey", + name="id", + field=models.CharField( + editable=False, + max_length=150, + primary_key=True, + serialize=False, + unique=True, + ), + ), + migrations.AlterField( + model_name="userapikey", + name="hashed_key", + field=models.CharField(editable=False, max_length=150), + ), + migrations.AlterField( + model_name="userapikey", + name="id", + field=models.CharField( + editable=False, + max_length=150, + primary_key=True, + serialize=False, + unique=True, + ), + ), + ] diff --git a/peeringdb_server/migrations/0113_organization_last_notified.py b/peeringdb_server/migrations/0113_organization_last_notified.py new file mode 100644 index 00000000..6661185b --- /dev/null +++ b/peeringdb_server/migrations/0113_organization_last_notified.py @@ -0,0 +1,22 @@ +# Generated by Django 4.2.2 on 2023-07-03 09:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("peeringdb_server", "0112_organization_require_totpdevice_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="organization", + name="last_notified", + field=models.DateTimeField( + blank=True, + help_text="Date when the organization admins were notified about 2FA", + null=True, + ), + ), + ] diff --git a/peeringdb_server/migrations/0114_oauthapplication_post_logout_redirect_uris_and_more.py b/peeringdb_server/migrations/0114_oauthapplication_post_logout_redirect_uris_and_more.py new file mode 100644 index 00000000..373ac71b --- /dev/null +++ b/peeringdb_server/migrations/0114_oauthapplication_post_logout_redirect_uris_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 4.2.3 on 2023-07-10 13:48 + +import oauth2_provider.generators +import oauth2_provider.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("peeringdb_server", "0113_organization_last_notified"), + ] + + operations = [ + migrations.AddField( + model_name="oauthapplication", + name="post_logout_redirect_uris", + field=models.TextField( + blank=True, help_text="Allowed Post Logout URIs list, space separated" + ), + ), + migrations.AlterField( + model_name="oauthapplication", + name="client_secret", + field=oauth2_provider.models.ClientSecretField( + blank=True, + db_index=True, + default=oauth2_provider.generators.generate_client_secret, + help_text="Hashed on Save. Copy it now if this is a new secret.", + max_length=255, + ), + ), + ] diff --git a/peeringdb_server/migrations/0115_hash_oauth_client_secret.py b/peeringdb_server/migrations/0115_hash_oauth_client_secret.py new file mode 100644 index 00000000..ad9afab4 --- /dev/null +++ b/peeringdb_server/migrations/0115_hash_oauth_client_secret.py @@ -0,0 +1,29 @@ +import oauth2_provider.generators +import oauth2_provider.models +from django.db import migrations +from oauth2_provider import settings + + +def forwards_func(apps, schema_editor): + """ + Forward migration touches every application.client_secret which will cause it to be hashed if not already the case. + """ + Application = apps.get_model(settings.APPLICATION_MODEL) + applications = Application._default_manager.all() + for application in applications: + application.save(update_fields=["client_secret"]) + + +class Migration(migrations.Migration): + + dependencies = [ + ("oauth2_provider", "0005_auto_20211222_2352"), + ( + "peeringdb_server", + "0114_oauthapplication_post_logout_redirect_uris_and_more", + ), + ] + + operations = [ + migrations.RunPython(forwards_func), + ] diff --git a/peeringdb_server/mock.py b/peeringdb_server/mock.py index 450b19f0..ee466f86 100644 --- a/peeringdb_server/mock.py +++ b/peeringdb_server/mock.py @@ -350,3 +350,6 @@ class Mock: def email_domains(self, data, reftag=None): return None + + def last_notified(self, data, reftag=None): + return None diff --git a/peeringdb_server/models.py b/peeringdb_server/models.py index 495ef326..5600d163 100644 --- a/peeringdb_server/models.py +++ b/peeringdb_server/models.py @@ -945,6 +945,20 @@ class Organization(ProtectedMixin, pdb_models.OrganizationBase, GeocodeBaseMixin help_text="Date when the organization was flagged", ) + # restrict users in the organization to be required + # to always activate 2FA. + require_2fa = models.BooleanField( + default=False, + help_text=_("Require users in your organization to activate 2FA."), + ) + last_notified = models.DateTimeField( + null=True, + blank=True, + auto_now=False, + auto_now_add=False, + help_text="Date when the organization admins were notified about 2FA", + ) + class Meta(pdb_models.OrganizationBase.Meta): indexes = [models.Index(fields=["status"], name="org_status")] @@ -5805,6 +5819,14 @@ class User(AbstractBaseUser, PermissionsMixin): group = Group.objects.get(id=settings.USER_GROUP_ID) return group in self.groups.all() + @property + def has_2fa(self): + """ + Returns true if the user has set up any TOTP or webauth security keys. + """ + + return self.totpdevice_set.exists() or self.webauthn_security_keys.exists() + @staticmethod def autocomplete_search_fields(): """ diff --git a/peeringdb_server/org_admin_views.py b/peeringdb_server/org_admin_views.py index b023e6ad..cb8f83dc 100644 --- a/peeringdb_server/org_admin_views.py +++ b/peeringdb_server/org_admin_views.py @@ -511,6 +511,17 @@ def uoar_approve(request, **kwargs): uoar.delete() return JsonResponse({"status": "ok"}) + if org.require_2fa: + if not uoar.user.has_2fa: + message = ( + f"User {uoar.user.full_name} requests affiliation with Organization {uoar.org.name} " + f"but has not enabled 2FA. Org {uoar.org.name} does not allow users to affiliate " + f"unless they have enabled 2FA on their account. You will be able to approve an " + f"affiliation request from User {uoar.user.full_name}, and assign permissions to " + f"them, when they have enabled 2FA." + ) + return JsonResponse({"message": message}, status=403) + uoar.approve() # notify rest of org admins that the affiliation request has been diff --git a/peeringdb_server/scripts/auto_pdb_load_data.py b/peeringdb_server/scripts/auto_pdb_load_data.py new file mode 100644 index 00000000..b2715f0f --- /dev/null +++ b/peeringdb_server/scripts/auto_pdb_load_data.py @@ -0,0 +1,61 @@ +""" +Runs the pdb_load_data command on a randomized interval + +Minimum interval is set through PEERINGDB_SYNC_INTERVAL environment variable (seconds) +and will default to 15 minutes if not set. + +A random offset of up to 15 minutes will be appalied. +""" + +import os +import random +import subprocess +import time + +import structlog + +# Configure logging +logger = structlog.getLogger(__name__) + + +def run_pdb_load_data(): + command = "python manage.py pdb_load_data --commit" + directory = "/srv/www.peeringdb.com/" + + subprocess.call(command, shell=True, cwd=directory) + + +if __name__ == "__main__": + + try: + PEERINGDB_SYNC_INTERVAL = int( + os.environ.get("PEERINGDB_SYNC_INTERVAL", 15 * 60) + ) + except ValueError: + PEERINGDB_SYNC_INTERVAL = 1 + + default_sleep = PEERINGDB_SYNC_INTERVAL + + # apply a maximum offset of 15 minutes + max_sleep = default_sleep + (15 * 60) + + logger.info("Starting pdb_load_data daemon...") + + first_run = True + + while bool(PEERINGDB_SYNC_INTERVAL): + + # sleep for a random amount of time between the default interval + # and the maximum interval + if first_run: + sleep_time = 0 + else: + sleep_time = random.randint(default_sleep, max_sleep) + logger.info(f"Sleeping for {sleep_time} seconds...") + + time.sleep(sleep_time) + + run_pdb_load_data() + logger.info("Data loaded successfully.") + + first_run = False diff --git a/peeringdb_server/search.py b/peeringdb_server/search.py index 8db0e675..ee3e2c4c 100644 --- a/peeringdb_server/search.py +++ b/peeringdb_server/search.py @@ -242,6 +242,37 @@ def elasticsearch_proximity_entity(name): return None +def order_results_alphabetically(result, search_term): + """ + Order the search results alphabetically and put the exact case-insensitive matches in front. + + Args: + - result: A dictionary containing categories and their search results. + - search_term: A string representing the search term. + + Returns: + - result: A dictionary containing the search results in alphabetical order. + """ + + search_term_lower = search_term.lower() + + for category in result: + result[category] = sorted(result[category], key=lambda x: x["name"].lower()) + + exact_match_index = -1 + + for index, item in enumerate(result[category]): + if item["name"].lower() == search_term_lower: + exact_match_index = index + break + + if exact_match_index != -1: + exact_match = result[category].pop(exact_match_index) + result[category].insert(0, exact_match) + + return result + + def search_v2(term, geo={}): """ Search searchable objects (ixp, network, facility ...) by term on elasticsearch engine. @@ -333,6 +364,8 @@ def search_v2(term, geo={}): pk_map, ) + result = order_results_alphabetically(result, term) + return result diff --git a/peeringdb_server/serializers.py b/peeringdb_server/serializers.py index d8ceeaf9..e8a6b15a 100644 --- a/peeringdb_server/serializers.py +++ b/peeringdb_server/serializers.py @@ -283,8 +283,8 @@ class GeocodeSerializerMixin: suggested_address = instance.process_geo_location() # normalize state if needed - if suggested_address.get("state") != instance.state: - instance.state = suggested_address.get("state") + if suggested_address.get("state", "") != instance.state: + instance.state = suggested_address.get("state", "") instance.save() # provide other normalization options as suggestion to the user @@ -1796,20 +1796,8 @@ class CarrierFacilitySerializer(ModelSerializer): data.get("carrier"), self.Meta.model.handleref.tag ) - # new carrier-facility relationship should be pending - # until the facility approves it. - # - # if the carrier org is the same as the facility org the connection - # is auto-approved - - if ( - data.get("carrier") - and data.get("facility") - and data["carrier"].org_id == data["facility"].org_id - ): - data["status"] = "ok" - else: - data["status"] = "pending" + # new carrier-facility relationship should be auto-approved + data["status"] = "ok" return super().validate_create(data) @@ -3326,6 +3314,7 @@ class OrganizationSerializer( "website", "social_media", "notes", + "require_2fa", "net_set", "fac_set", "ix_set", diff --git a/peeringdb_server/static/20c/twentyc.edit.js b/peeringdb_server/static/20c/twentyc.edit.js index 2dd422f2..fa1af50a 100644 --- a/peeringdb_server/static/20c/twentyc.edit.js +++ b/peeringdb_server/static/20c/twentyc.edit.js @@ -681,6 +681,10 @@ twentyc.editable.target.error_handlers.http_json = function(response, me, sender info = ["Too Many Requests", response.responseJSON.message]; + } else if(response.status == 403) { + + info = ["Forbidden", response.responseJSON.message]; + } else { if(response.responseJSON && response.responseJSON.non_field_errors) { diff --git a/peeringdb_server/static/site.css b/peeringdb_server/static/site.css index d70fe8b1..f3038aa4 100644 --- a/peeringdb_server/static/site.css +++ b/peeringdb_server/static/site.css @@ -1645,14 +1645,22 @@ div.captcha .fallback { padding-left: 0px; } -.badge-2fa { +.badge-2fa-enabled { border-radius: 3px; - background-color: orange; + background-color: green; padding: 1px 3px; color: #fff; font-weight: bold; } +.badge-2fa-disabled { + border-radius: 3px; + background-color: transparent; + padding: 1px 3px; + color: #000; + font-weight: bold; +} + /** * right to left direction */ @@ -1726,3 +1734,14 @@ div.stats_row { position: absolute; border: 1.2px solid rgb(75, 96, 99); } + + +textarea#id_redirect_uris { + width: 100%; +} + +textarea.input-block-level, +input.input-block-level { + display: block; + width: 100%; +} diff --git a/peeringdb_server/templates/email/notify-org-member-disable-2fa.txt b/peeringdb_server/templates/email/notify-org-member-disable-2fa.txt new file mode 100644 index 00000000..2442a893 --- /dev/null +++ b/peeringdb_server/templates/email/notify-org-member-disable-2fa.txt @@ -0,0 +1,6 @@ +{% load i18n %} +{{ member }} +--------------------------------------------{% blocktrans %} +Would you like to drop their affiliation or leave it in place? If you drop affiliations, they will not be able to re-affiliate until they have 2FA turned on. +{% endblocktrans %} +[{{ _('Drop Affiliations') }}] [{{ _('Leave them Affiliated') }}] [{{ _('Cancel 2FA Requirement') }}] diff --git a/peeringdb_server/templates/email/notify-org-user-admin-2fa.txt b/peeringdb_server/templates/email/notify-org-user-admin-2fa.txt new file mode 100644 index 00000000..659449c7 --- /dev/null +++ b/peeringdb_server/templates/email/notify-org-user-admin-2fa.txt @@ -0,0 +1,9 @@ +{% load i18n %}{% blocktrans %} +The following users affiliated with {{ org_name }} organization do not have 2FA turned on: +{% endblocktrans %} +{% for member_2fa_notification in users_without_2fa %} +{{member_2fa_notification|safe}} +{% endfor %} +{% trans "You may view and edit your organization users at" %} {{ org_url }}. + +{% trans "If you have questions, please don't hesitate to contact peeringdb support at" %} {{ support_email }}. diff --git a/peeringdb_server/templates/site/handle-2fa.html b/peeringdb_server/templates/site/handle-2fa.html new file mode 100644 index 00000000..101d86d1 --- /dev/null +++ b/peeringdb_server/templates/site/handle-2fa.html @@ -0,0 +1,22 @@ +{% extends "site/base.html" %} +{% load i18n %} +{% block content %} +
+
+
+ + +

{% trans "Confirmation" %}

+

{{ confirm_message }}

+ + + +
+
+
+ +{% endblock %} diff --git a/peeringdb_server/templates/site/notification_banner.html b/peeringdb_server/templates/site/notification_banner.html index 399b8175..ec3cd547 100644 --- a/peeringdb_server/templates/site/notification_banner.html +++ b/peeringdb_server/templates/site/notification_banner.html @@ -1,11 +1,14 @@ {% load i18n %} - +{% endif %} diff --git a/peeringdb_server/templates/site/view_organization_tools.html b/peeringdb_server/templates/site/view_organization_tools.html index 938545d0..89b9b319 100644 --- a/peeringdb_server/templates/site/view_organization_tools.html +++ b/peeringdb_server/templates/site/view_organization_tools.html @@ -862,7 +862,7 @@
{{ user.full_name }}
-
{{ user.username }} {% if user.totpdevice_set.exists %}2FA{% endif %}{% if user.webauthn_security_keys.exists %}U2F{% endif %}
+
{{ user.username }} {% if user.has_2fa %}2FA{% else %}{% trans "No 2FA" %}{% endif %}{% if user.webauthn_security_keys.exists %}U2F{% endif %}
{% for valid_email in user_emails.1 %} @@ -907,6 +907,10 @@
{{ instance.id }}
+
+
+ {% trans "Require users in your organization to enable 2FA." %} +
{% trans "Restrict user email addresses to these domains" %} diff --git a/peeringdb_server/urls.py b/peeringdb_server/urls.py index 7a3ace2a..9950f07b 100644 --- a/peeringdb_server/urls.py +++ b/peeringdb_server/urls.py @@ -47,6 +47,7 @@ from peeringdb_server.oauth_views import AuthorizationView from peeringdb_server.views import ( OrganizationLogoUpload, cancel_affiliation_request, + handle_2fa, network_dismiss_ixf_proposal, network_reset_ixf_proposals, profile_add_email, @@ -245,6 +246,7 @@ urlpatterns = [ peeringdb_server.org_admin_views.update_user_options, name="org-admin-user-options", ), + re_path(r"^org_admin/handle-2fa$", handle_2fa, name="handle-2fa"), re_path( r"^org_admin/manage_user/delete$", peeringdb_server.org_admin_views.manage_user_delete, diff --git a/peeringdb_server/views.py b/peeringdb_server/views.py index c7c4085e..844321ee 100644 --- a/peeringdb_server/views.py +++ b/peeringdb_server/views.py @@ -1302,7 +1302,15 @@ def view_index(request, errors=None): template = loader.get_template("site/index.html") + if request.user.is_authenticated: + organizations_require_2fa = any( + org.require_2fa for org in request.user.organizations + ) + else: + organizations_require_2fa = False + recent = { + "organizations_require_2fa": organizations_require_2fa, "net": Network.handleref.filter(status="ok").order_by("-updated")[:5], "fac": Facility.handleref.filter(status="ok").order_by("-updated")[:5], "ix": InternetExchange.handleref.filter(status="ok").order_by("-updated")[:5], @@ -3606,3 +3614,55 @@ def view_set_user_org(request): response = JsonResponse({"status": "ok"}) return response + + +@ensure_csrf_cookie +@login_required +def handle_2fa(request): + if request.user.is_authenticated: + user_admin = request.user + action = request.GET.get("action") + commit = request.GET.get("commit") + try: + org = Organization.objects.get(id=request.GET.get("org")) + except Organization.DoesNotExist: + return view_index(request, errors=[_("Invalid organization")]) + try: + member = User.objects.get(id=request.GET.get("member")) + except User.DoesNotExist: + return view_index(request, errors=[_("Invalid member")]) + if user_admin.is_org_admin(org) and member.is_org_member(org): + confirm_url = f"/org_admin/handle-2fa?&org={org.id}&member={member.id}&action={action}&commit=1" + if action == "drop": + if commit: + org.usergroup.user_set.remove(member) + else: + confirm_message = f"This will completely remove {member} from {org}" + elif action == "leave": + if commit: + pass + else: + confirm_message = f"This will allow {member} to keep all privileges within {org}. This conflicts with your 2FA Policy" + elif action == "disable": + if commit: + org.require_2fa = False + org.save() + else: + confirm_message = f"This will turn off the 2FA requirement for {org}, users will not need to use 2FA to login" + else: + return view_index(request, errors=[_("Action not provided")]) + if commit: + return redirect("/") + return render( + request, + "site/handle-2fa.html", + {"confirm_message": confirm_message, "confirm_url": confirm_url}, + ) + else: + return view_index( + request, errors=[_(f"Only admin of the {org} can perform the action")] + ) + else: + return view_index( + request, errors=[_("Login as the organization admin to perform the action")] + ) diff --git a/poetry.lock b/poetry.lock index c8ea60d0..2a3c3ec9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,9 +1,10 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. [[package]] name = "asgiref" version = "3.7.2" description = "ASGI specs, helper code, and adapters" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -21,6 +22,7 @@ tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] name = "asn1crypto" version = "1.5.1" 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 = "main" optional = false python-versions = "*" files = [ @@ -28,21 +30,11 @@ files = [ {file = "asn1crypto-1.5.1.tar.gz", hash = "sha256:13ae38502be632115abf8a24cbe5f4da52e3b5231990aff31123c805306ccb9c"}, ] -[[package]] -name = "async-generator" -version = "1.10" -description = "Async generators and context managers for Python 3.5+" -optional = false -python-versions = ">=3.5" -files = [ - {file = "async_generator-1.10-py3-none-any.whl", hash = "sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b"}, - {file = "async_generator-1.10.tar.gz", hash = "sha256:6ebb3d106c12920aaae42ccb6f787ef5eefdcdd166ea3d628fa8476abe712144"}, -] - [[package]] name = "attrs" version = "23.1.0" description = "Classes Without Boilerplate" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -61,6 +53,7 @@ tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pyte name = "black" version = "22.12.0" description = "The uncompromising code formatter." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -96,6 +89,7 @@ uvloop = ["uvloop (>=0.15.2)"] name = "bleach" version = "6.0.0" description = "An easy safelist-based HTML-sanitizing tool." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -114,6 +108,7 @@ css = ["tinycss2 (>=1.1.0,<1.2)"] name = "cbor2" version = "5.4.6" description = "CBOR (de)serializer with extensive tag support" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -163,6 +158,7 @@ test = ["pytest", "pytest-cov"] name = "certifi" version = "2023.5.7" description = "Python package for providing Mozilla's CA Bundle." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -174,6 +170,7 @@ files = [ name = "cffi" version = "1.15.1" description = "Foreign Function Interface for Python calling C code." +category = "main" optional = false python-versions = "*" files = [ @@ -250,6 +247,7 @@ pycparser = "*" name = "cfgv" version = "3.3.1" description = "Validate configuration and produce human readable error messages." +category = "dev" optional = false python-versions = ">=3.6.1" files = [ @@ -259,97 +257,99 @@ files = [ [[package]] name = "charset-normalizer" -version = "3.1.0" +version = "3.2.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, - {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, + {file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"}, + {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"}, ] [[package]] name = "click" -version = "8.1.3" +version = "8.1.4" description = "Composable command line interface toolkit" +category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, + {file = "click-8.1.4-py3-none-any.whl", hash = "sha256:2739815aaa5d2c986a88f1e9230c55e17f0caad3d958a5e13ad0797c166db9e3"}, + {file = "click-8.1.4.tar.gz", hash = "sha256:b97d0c74955da062a7d4ef92fadb583806a585b2ea81958a81bd72726cbb8e37"}, ] [package.dependencies] @@ -359,6 +359,7 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -370,6 +371,7 @@ files = [ name = "confu" version = "1.8.0" description = "Configuration file validation and generation" +category = "main" optional = false python-versions = ">=3.6.2,<4.0.0" files = [ @@ -381,6 +383,7 @@ files = [ name = "contextlib2" version = "21.6.0" description = "Backports and enhancements for the contextlib module" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -392,6 +395,7 @@ files = [ name = "coreapi" version = "2.3.3" description = "Python client library for Core API." +category = "main" optional = false python-versions = "*" files = [ @@ -409,6 +413,7 @@ uritemplate = "*" name = "coreschema" version = "0.0.4" description = "Core Schema." +category = "main" optional = false python-versions = "*" files = [ @@ -423,6 +428,7 @@ jinja2 = "*" name = "coverage" version = "7.2.7" description = "Code coverage measurement for Python" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -496,30 +502,35 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "41.0.1" +version = "41.0.2" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-41.0.1-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:f73bff05db2a3e5974a6fd248af2566134d8981fd7ab012e5dd4ddb1d9a70699"}, - {file = "cryptography-41.0.1-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:1a5472d40c8f8e91ff7a3d8ac6dfa363d8e3138b961529c996f3e2df0c7a411a"}, - {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fa01527046ca5facdf973eef2535a27fec4cb651e4daec4d043ef63f6ecd4ca"}, - {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b46e37db3cc267b4dea1f56da7346c9727e1209aa98487179ee8ebed09d21e43"}, - {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d198820aba55660b4d74f7b5fd1f17db3aa5eb3e6893b0a41b75e84e4f9e0e4b"}, - {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:948224d76c4b6457349d47c0c98657557f429b4e93057cf5a2f71d603e2fc3a3"}, - {file = "cryptography-41.0.1-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:059e348f9a3c1950937e1b5d7ba1f8e968508ab181e75fc32b879452f08356db"}, - {file = "cryptography-41.0.1-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:b4ceb5324b998ce2003bc17d519080b4ec8d5b7b70794cbd2836101406a9be31"}, - {file = "cryptography-41.0.1-cp37-abi3-win32.whl", hash = "sha256:8f4ab7021127a9b4323537300a2acfb450124b2def3756f64dc3a3d2160ee4b5"}, - {file = "cryptography-41.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:1fee5aacc7367487b4e22484d3c7e547992ed726d14864ee33c0176ae43b0d7c"}, - {file = "cryptography-41.0.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9a6c7a3c87d595608a39980ebaa04d5a37f94024c9f24eb7d10262b92f739ddb"}, - {file = "cryptography-41.0.1-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5d092fdfedaec4cbbffbf98cddc915ba145313a6fdaab83c6e67f4e6c218e6f3"}, - {file = "cryptography-41.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1a8e6c2de6fbbcc5e14fd27fb24414507cb3333198ea9ab1258d916f00bc3039"}, - {file = "cryptography-41.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cb33ccf15e89f7ed89b235cff9d49e2e62c6c981a6061c9c8bb47ed7951190bc"}, - {file = "cryptography-41.0.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5f0ff6e18d13a3de56f609dd1fd11470918f770c6bd5d00d632076c727d35485"}, - {file = "cryptography-41.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7bfc55a5eae8b86a287747053140ba221afc65eb06207bedf6e019b8934b477c"}, - {file = "cryptography-41.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:eb8163f5e549a22888c18b0d53d6bb62a20510060a22fd5a995ec8a05268df8a"}, - {file = "cryptography-41.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:8dde71c4169ec5ccc1087bb7521d54251c016f126f922ab2dfe6649170a3b8c5"}, - {file = "cryptography-41.0.1.tar.gz", hash = "sha256:d34579085401d3f49762d2f7d6634d6b6c2ae1242202e860f4d26b046e3a1006"}, + {file = "cryptography-41.0.2-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:01f1d9e537f9a15b037d5d9ee442b8c22e3ae11ce65ea1f3316a41c78756b711"}, + {file = "cryptography-41.0.2-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:079347de771f9282fbfe0e0236c716686950c19dee1b76240ab09ce1624d76d7"}, + {file = "cryptography-41.0.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:439c3cc4c0d42fa999b83ded80a9a1fb54d53c58d6e59234cfe97f241e6c781d"}, + {file = "cryptography-41.0.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f14ad275364c8b4e525d018f6716537ae7b6d369c094805cae45300847e0894f"}, + {file = "cryptography-41.0.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:84609ade00a6ec59a89729e87a503c6e36af98ddcd566d5f3be52e29ba993182"}, + {file = "cryptography-41.0.2-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:49c3222bb8f8e800aead2e376cbef687bc9e3cb9b58b29a261210456a7783d83"}, + {file = "cryptography-41.0.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:d73f419a56d74fef257955f51b18d046f3506270a5fd2ac5febbfa259d6c0fa5"}, + {file = "cryptography-41.0.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:2a034bf7d9ca894720f2ec1d8b7b5832d7e363571828037f9e0c4f18c1b58a58"}, + {file = "cryptography-41.0.2-cp37-abi3-win32.whl", hash = "sha256:d124682c7a23c9764e54ca9ab5b308b14b18eba02722b8659fb238546de83a76"}, + {file = "cryptography-41.0.2-cp37-abi3-win_amd64.whl", hash = "sha256:9c3fe6534d59d071ee82081ca3d71eed3210f76ebd0361798c74abc2bcf347d4"}, + {file = "cryptography-41.0.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a719399b99377b218dac6cf547b6ec54e6ef20207b6165126a280b0ce97e0d2a"}, + {file = "cryptography-41.0.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:182be4171f9332b6741ee818ec27daff9fb00349f706629f5cbf417bd50e66fd"}, + {file = "cryptography-41.0.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:7a9a3bced53b7f09da251685224d6a260c3cb291768f54954e28f03ef14e3766"}, + {file = "cryptography-41.0.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f0dc40e6f7aa37af01aba07277d3d64d5a03dc66d682097541ec4da03cc140ee"}, + {file = "cryptography-41.0.2-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:674b669d5daa64206c38e507808aae49904c988fa0a71c935e7006a3e1e83831"}, + {file = "cryptography-41.0.2-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7af244b012711a26196450d34f483357e42aeddb04128885d95a69bd8b14b69b"}, + {file = "cryptography-41.0.2-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9b6d717393dbae53d4e52684ef4f022444fc1cce3c48c38cb74fca29e1f08eaa"}, + {file = "cryptography-41.0.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:192255f539d7a89f2102d07d7375b1e0a81f7478925b3bc2e0549ebf739dae0e"}, + {file = "cryptography-41.0.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f772610fe364372de33d76edcd313636a25684edb94cee53fd790195f5989d14"}, + {file = "cryptography-41.0.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:b332cba64d99a70c1e0836902720887fb4529ea49ea7f5462cf6640e095e11d2"}, + {file = "cryptography-41.0.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9a6673c1828db6270b76b22cc696f40cde9043eb90373da5c2f8f2158957f42f"}, + {file = "cryptography-41.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:342f3767e25876751e14f8459ad85e77e660537ca0a066e10e75df9c9e9099f0"}, + {file = "cryptography-41.0.2.tar.gz", hash = "sha256:7d230bf856164de164ecb615ccc14c7fc6de6906ddd5b491f3af90d3514c925c"}, ] [package.dependencies] @@ -539,6 +550,7 @@ test-randomorder = ["pytest-randomly"] name = "decorator" version = "4.4.2" description = "Decorators for Humans" +category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*" files = [ @@ -550,6 +562,7 @@ files = [ name = "defusedxml" version = "0.7.1" description = "XML bomb protection for Python stdlib modules" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -561,6 +574,7 @@ files = [ name = "deprecated" version = "1.2.14" 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.*" files = [ @@ -578,6 +592,7 @@ dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] name = "diff-match-patch" version = "20230430" description = "Diff Match and Patch" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -592,6 +607,7 @@ dev = ["attribution (==1.6.2)", "black (==23.3.0)", "flit (==3.8.0)", "mypy (==1 name = "distlib" version = "0.3.6" description = "Distribution utilities" +category = "dev" optional = false python-versions = "*" files = [ @@ -603,6 +619,7 @@ files = [ name = "django" version = "4.2.3" description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -623,6 +640,7 @@ bcrypt = ["bcrypt"] name = "django-allauth" version = "0.54.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 = ">=3.7" files = [ @@ -640,6 +658,7 @@ requests-oauthlib = ">=0.3.0" name = "django-autocomplete-light" version = "3.9.7" description = "Fresh autocompletes for Django" +category = "main" optional = false python-versions = "*" files = [ @@ -660,6 +679,7 @@ tags = ["django-taggit"] name = "django-bootstrap5" version = "23.3" description = "Bootstrap 5 for Django" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -672,13 +692,14 @@ django = ">=3.2" [[package]] name = "django-cors-headers" -version = "4.1.0" +version = "4.2.0" description = "django-cors-headers is a Django application for handling the server headers required for Cross-Origin Resource Sharing (CORS)." +category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "django_cors_headers-4.1.0-py3-none-any.whl", hash = "sha256:88a4bfae24b6404dd0e0640203cb27704a2a57fd546a429e5d821dfa53dd1acf"}, - {file = "django_cors_headers-4.1.0.tar.gz", hash = "sha256:36a8d7a6dee6a85f872fe5916cc878a36d0812043866355438dfeda0b20b6b78"}, + {file = "django_cors_headers-4.2.0-py3-none-any.whl", hash = "sha256:9ada212b0e2efd4a5e339360ffc869cb21ac5605e810afe69f7308e577ea5bde"}, + {file = "django_cors_headers-4.2.0.tar.gz", hash = "sha256:f9749c6410fe738278bc2b6ef17f05195bc7b251693c035752d8257026af024f"}, ] [package.dependencies] @@ -688,6 +709,7 @@ Django = ">=3.2" name = "django-countries" version = "7.5.1" description = "Provides a country field for Django models." +category = "main" optional = false python-versions = "*" files = [ @@ -709,6 +731,7 @@ test = ["djangorestframework", "graphene-django", "pytest", "pytest-cov", "pytes name = "django-crispy-forms" version = "2.0" description = "Best way to have Django DRY forms" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -723,6 +746,7 @@ django = ">=3.2" name = "django-csp" version = "3.7" description = "Django Content Security Policy support." +category = "main" optional = false python-versions = "*" files = [ @@ -741,6 +765,7 @@ tests = ["jinja2 (>=2.9.6)", "mock (==1.0.1)", "pep8 (==1.4.6)", "pytest (<4.0)" name = "django-debug-toolbar" version = "4.1.0" description = "A configurable set of panels that display various debug information about the current request/response." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -756,6 +781,7 @@ sqlparse = ">=0.2" name = "django-elasticsearch-dsl" version = "7.3" description = "Wrapper around elasticsearch-dsl-py for django models" +category = "main" optional = false python-versions = "*" files = [ @@ -771,6 +797,7 @@ six = "*" name = "django-extensions" version = "3.2.3" description = "Extensions for Django" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -785,6 +812,7 @@ Django = ">=3.2" name = "django-formtools" version = "2.4.1" description = "A set of high-level abstractions for Django forms" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -799,6 +827,7 @@ Django = ">=3.2" name = "django-grainy" version = "2.0.0" description = "granular permissions for django" +category = "main" optional = false python-versions = ">=3.8,<4.0" files = [ @@ -817,6 +846,7 @@ six = ">=1.11.0,<=2.0.0" name = "django-grappelli" version = "3.0.6" description = "A jazzy skin for the Django Admin-Interface." +category = "main" optional = false python-versions = "*" files = [ @@ -828,6 +858,7 @@ files = [ name = "django-handleref" version = "2.0.0" description = "django object tracking" +category = "main" optional = false python-versions = ">=3.8,<4.0" files = [ @@ -839,6 +870,7 @@ files = [ name = "django-hashers-passlib" version = "1.0.0" description = "Django hashers using passlib" +category = "main" optional = false python-versions = "*" files = [] @@ -858,6 +890,7 @@ resolved_reference = "be7900109778600927380e01d4ec59d04d0734a8" name = "django-haystack" version = "3.2.1" description = "Pluggable search for Django." +category = "main" optional = false python-versions = "*" files = [ @@ -874,6 +907,7 @@ elasticsearch = ["elasticsearch (>=5,<8)"] name = "django-import-export" version = "2.9.0" description = "Django application and library for importing and exporting data with included admin integration." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -890,6 +924,7 @@ tablib = {version = ">=3.0.0", extras = ["html", "ods", "xls", "xlsx", "yaml"]} name = "django-inet" version = "1.1.1" description = "django internet utilities" +category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -901,6 +936,7 @@ files = [ name = "django-ipware" version = "5.0.0" description = "A Django application to retrieve user's IP address" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -910,13 +946,14 @@ files = [ [[package]] name = "django-oauth-toolkit" -version = "1.6.1" +version = "2.3.0" description = "OAuth2 Provider for Django" +category = "main" optional = false python-versions = "*" files = [ - {file = "django-oauth-toolkit-1.6.1.tar.gz", hash = "sha256:529acda23541ededac8c6a16f15ae767f94e503a22cb96c1e300aa4ff274ad50"}, - {file = "django_oauth_toolkit-1.6.1-py3-none-any.whl", hash = "sha256:d206132ac272fdcf9d916df2e64d2df3ffb769eaad545f4010647c9c0a1deb01"}, + {file = "django-oauth-toolkit-2.3.0.tar.gz", hash = "sha256:cf1cb1a5744672e6bd7d66b4a110a463bcef9cf5ed4f27e29682cc6a4d0df1ed"}, + {file = "django_oauth_toolkit-2.3.0-py3-none-any.whl", hash = "sha256:47dfeab97ec21496f307c2cf3468e64ca08897fa499bf3104366d32005c9111d"}, ] [package.dependencies] @@ -929,6 +966,7 @@ requests = ">=2.13.0" name = "django-otp" version = "1.2.2" description = "A pluggable framework for adding two-factor authentication to Django using one-time passwords." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -946,6 +984,7 @@ qrcode = ["qrcode"] name = "django-peeringdb" version = "3.1.0" description = "PeeringDB Django models" +category = "main" optional = false python-versions = ">=3.8,<4.0" files = [ @@ -963,6 +1002,7 @@ django_inet = ">=1,<2" name = "django-phonenumber-field" version = "6.4.0" description = "An international phone number field for django models." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -981,6 +1021,7 @@ phonenumberslite = ["phonenumberslite (>=7.0.2)"] name = "django-ranged-response" version = "0.2.0" description = "Modified Django FileResponse that adds Content-Range headers." +category = "main" optional = false python-versions = "*" files = [ @@ -994,6 +1035,7 @@ django = "*" name = "django-ratelimit" version = "4.0.0" description = "Cache-based rate-limiting for Django." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1005,6 +1047,7 @@ files = [ name = "django-rest-swagger" version = "2.2.0" description = "Swagger UI for Django REST Framework 3.5+" +category = "main" optional = false python-versions = "*" files = [ @@ -1022,6 +1065,7 @@ simplejson = "*" name = "django-reversion" version = "4.0.2" description = "An extension to the Django web framework that provides version control for model instances." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1036,6 +1080,7 @@ django = ">=2.0" name = "django-security-keys" version = "1.0.1" description = "Django webauthn security key integration" +category = "main" optional = false python-versions = ">=3.8,<4.0" files = [ @@ -1049,17 +1094,18 @@ webauthn = ">=1,<2" [[package]] name = "django-simple-captcha" -version = "0.5.17" +version = "0.5.18" description = "A very simple, yet powerful, Django captcha application" +category = "main" optional = false python-versions = "*" files = [ - {file = "django-simple-captcha-0.5.17.tar.gz", hash = "sha256:9649e66dab4e71efacbfef02f48b83b91684898352a1ab56f1686ce71033b328"}, - {file = "django_simple_captcha-0.5.17-py2.py3-none-any.whl", hash = "sha256:f9a07e5e9de264ba4039c9eaad66bc48188a21ceda5fcdc2fa13c5512141c2c9"}, + {file = "django-simple-captcha-0.5.18.tar.gz", hash = "sha256:6e1fcc4f4005f7d69ee7a2e59a7e863b5d3918f36a85a4d811498984aecc48ce"}, + {file = "django_simple_captcha-0.5.18-py2.py3-none-any.whl", hash = "sha256:567ad84fa64c86508c679b8425cc1410c44b3cd6467e54f8d31cf077d9366407"}, ] [package.dependencies] -Django = ">=2.2" +Django = ">=3.2" django-ranged-response = "0.2.0" Pillow = ">=6.2.0" @@ -1068,13 +1114,14 @@ test = ["testfixtures"] [[package]] name = "django-structlog" -version = "5.1.0" +version = "5.3.0" description = "Structured Logging for Django" +category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "django-structlog-5.1.0.tar.gz", hash = "sha256:e7a86b01e11b32296095d35565b44f9f179acb9563aa3e85cae698539db07756"}, - {file = "django_structlog-5.1.0-py3-none-any.whl", hash = "sha256:a2dbe27e4add95cd386bcdfd7e05fe4547b02061881b0ee743b84a3d55a5df89"}, + {file = "django-structlog-5.3.0.tar.gz", hash = "sha256:078577c91e58cbaf66ecb47ec2b710ce4864b234f474691d29578e75c055ef8b"}, + {file = "django_structlog-5.3.0-py3-none-any.whl", hash = "sha256:ab3e27671f6b6cea886eac86ab5b280c937adacff1a63bce9f716c7b3357571b"}, ] [package.dependencies] @@ -1088,13 +1135,14 @@ celery = ["celery (>=5.1)"] [[package]] name = "django-tables2" -version = "2.5.3" +version = "2.6.0" description = "Table/data-grid framework for Django" +category = "main" optional = false python-versions = "*" files = [ - {file = "django-tables2-2.5.3.tar.gz", hash = "sha256:f6c1623aac188d29aae9cf6b4de3211c96c525e49890654bec3359c181600eb9"}, - {file = "django_tables2-2.5.3-py2.py3-none-any.whl", hash = "sha256:e336fdf8899a8fab110550a40cad956064bd4054818e0b972c1893b3e2542168"}, + {file = "django-tables2-2.6.0.tar.gz", hash = "sha256:479eed04007cc04bcf764a6fb7a5e3955d94b878ba7f3a4bd4edbd2f7769e08d"}, + {file = "django_tables2-2.6.0-py2.py3-none-any.whl", hash = "sha256:04f23c1181d93716c67085a3c324b449180fd0c5162ef4619acb0b2d9a166133"}, ] [package.dependencies] @@ -1107,6 +1155,7 @@ tablib = ["tablib"] name = "django-two-factor-auth" version = "1.14.0" description = "Complete Two-Factor Authentication for Django" +category = "main" optional = false python-versions = "*" files = [ @@ -1132,6 +1181,7 @@ yubikey = ["django-otp-yubikey"] name = "django-vanilla-views" version = "3.0.0" description = "Beautifully simple class based views." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1143,6 +1193,7 @@ files = [ name = "djangorestframework" version = "3.14.0" description = "Web APIs for Django, made easy." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1158,6 +1209,7 @@ pytz = "*" name = "djangorestframework-api-key" version = "2.3.0" description = "API key permissions for the Django REST Framework" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1169,6 +1221,7 @@ files = [ name = "elasticsearch" version = "7.9.1" description = "Python client for Elasticsearch" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4" files = [ @@ -1190,6 +1243,7 @@ requests = ["requests (>=2.4.0,<3.0.0)"] name = "elasticsearch-dsl" version = "7.4.1" description = "Python client for Elasticsearch" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1209,6 +1263,7 @@ develop = ["coverage (<5.0.0)", "mock", "pytest (>=3.0.0)", "pytest-cov", "pytes name = "et-xmlfile" version = "1.1.0" description = "An implementation of lxml.xmlfile for the standard library" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1218,13 +1273,14 @@ files = [ [[package]] name = "exceptiongroup" -version = "1.1.1" +version = "1.1.2" description = "Backport of PEP 654 (exception groups)" +category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, - {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, + {file = "exceptiongroup-1.1.2-py3-none-any.whl", hash = "sha256:e346e69d186172ca7cf029c8c1d16235aa0e04035e5750b4b95039e65204328f"}, + {file = "exceptiongroup-1.1.2.tar.gz", hash = "sha256:12c3e887d6485d16943a309616de20ae5582633e0a2eda17f4e10fd61c1e8af5"}, ] [package.extras] @@ -1234,6 +1290,7 @@ test = ["pytest (>=6)"] name = "filelock" version = "3.12.2" description = "A platform independent file lock." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1249,6 +1306,7 @@ testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "p name = "flake8" version = "6.0.0" description = "the modular source code checker: pep8 pyflakes and co" +category = "dev" optional = false python-versions = ">=3.8.1" files = [ @@ -1265,6 +1323,7 @@ pyflakes = ">=3.0.0,<3.1.0" name = "future" version = "0.18.3" description = "Clean single-source support for Python 3 and 2" +category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -1275,6 +1334,7 @@ files = [ name = "geographiclib" version = "2.0" description = "The geodesic routines from GeographicLib" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1286,6 +1346,7 @@ files = [ name = "geopy" version = "2.3.0" description = "Python Geocoding Toolbox" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1309,6 +1370,7 @@ timezone = ["pytz"] name = "ghp-import" version = "2.1.0" description = "Copy your docs directly to the gh-pages branch." +category = "dev" optional = false python-versions = "*" files = [ @@ -1326,6 +1388,7 @@ dev = ["flake8", "markdown", "twine", "wheel"] name = "googlemaps" version = "4.10.0" description = "Python client library for Google Maps Platform" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -1339,6 +1402,7 @@ requests = ">=2.20.0,<3.0" name = "grainy" version = "1.8.1" description = "granular permissions utility" +category = "main" optional = false python-versions = ">=3.6,<4.0" files = [ @@ -1349,6 +1413,7 @@ files = [ name = "h11" version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1360,6 +1425,7 @@ files = [ name = "identify" version = "2.5.24" description = "File identification library for Python" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1374,6 +1440,7 @@ license = ["ukkonen"] name = "idna" version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -1383,13 +1450,14 @@ files = [ [[package]] name = "importlib-metadata" -version = "6.7.0" +version = "6.8.0" description = "Read metadata from Python packages" +category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "importlib_metadata-6.7.0-py3-none-any.whl", hash = "sha256:cb52082e659e97afc5dac71e79de97d8681de3aa07ff18578330904a9d18e5b5"}, - {file = "importlib_metadata-6.7.0.tar.gz", hash = "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4"}, + {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, + {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, ] [package.dependencies] @@ -1398,12 +1466,13 @@ zipp = ">=0.5" [package.extras] docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] [[package]] name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1415,6 +1484,7 @@ files = [ name = "isort" version = "5.12.0" description = "A Python utility / library to sort Python imports." +category = "dev" optional = false python-versions = ">=3.8.0" files = [ @@ -1432,6 +1502,7 @@ requirements-deprecated-finder = ["pip-api", "pipreqs"] name = "itypes" version = "1.2.0" description = "Simple immutable types for python." +category = "main" optional = false python-versions = "*" files = [ @@ -1443,6 +1514,7 @@ files = [ name = "jinja2" version = "3.1.2" description = "A very fast and expressive template engine." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1458,27 +1530,46 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "jsonschema" -version = "4.17.3" +version = "4.18.0" description = "An implementation of JSON Schema validation for Python" +category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "jsonschema-4.17.3-py3-none-any.whl", hash = "sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"}, - {file = "jsonschema-4.17.3.tar.gz", hash = "sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d"}, + {file = "jsonschema-4.18.0-py3-none-any.whl", hash = "sha256:b508dd6142bd03f4c3670534c80af68cd7bbff9ea830b9cf2625d4a3c49ddf60"}, + {file = "jsonschema-4.18.0.tar.gz", hash = "sha256:8caf5b57a990a98e9b39832ef3cb35c176fe331414252b6e1b26fd5866f891a4"}, ] [package.dependencies] -attrs = ">=17.4.0" -pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" +attrs = ">=22.2.0" +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rpds-py = ">=0.7.1" [package.extras] format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] +[[package]] +name = "jsonschema-specifications" +version = "2023.6.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema_specifications-2023.6.1-py3-none-any.whl", hash = "sha256:3d2b82663aff01815f744bb5c7887e2121a63399b49b104a3c96145474d091d7"}, + {file = "jsonschema_specifications-2023.6.1.tar.gz", hash = "sha256:ca1c4dd059a9e7b34101cf5b3ab7ff1d18b139f35950d598d629837ef66e8f28"}, +] + +[package.dependencies] +referencing = ">=0.28.0" + [[package]] name = "jwcrypto" version = "1.5.0" description = "Implementation of JOSE Web standards" +category = "main" optional = false python-versions = ">= 3.6" files = [ @@ -1493,6 +1584,7 @@ deprecated = "*" name = "markdown" version = "3.3.7" description = "Python implementation of Markdown." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1510,6 +1602,7 @@ testing = ["coverage", "pyyaml"] name = "markdown-include" version = "0.8.1" description = "A Python-Markdown extension which provides an 'include' function" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1527,6 +1620,7 @@ tests = ["pytest"] name = "markuppy" version = "1.14" description = "An HTML/XML generator" +category = "main" optional = false python-versions = "*" files = [ @@ -1537,6 +1631,7 @@ files = [ name = "markupsafe" version = "2.1.3" description = "Safely add untrusted strings to HTML/XML markup." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1596,6 +1691,7 @@ files = [ name = "mccabe" version = "0.7.0" description = "McCabe checker, plugin for flake8" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1607,6 +1703,7 @@ files = [ name = "mergedeep" version = "1.3.4" description = "A deep merge function for 🐍." +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1618,6 +1715,7 @@ files = [ name = "mkdocs" version = "1.4.3" description = "Project documentation with Markdown." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1644,30 +1742,32 @@ min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-imp [[package]] name = "munge" -version = "1.2.1" +version = "1.3.0" description = "data manipulation library and client" +category = "main" optional = false -python-versions = ">=3.6,<4.0" +python-versions = ">=3.8,<4.0" files = [ - {file = "munge-1.2.1-py3-none-any.whl", hash = "sha256:65fb76389b54970beeef6a80b9e1b45cb230d34743cf11565af926ebc8af2627"}, - {file = "munge-1.2.1.tar.gz", hash = "sha256:3daeb20c2964aa4136c57ebfd422ee7e059eb92fbb0ca1e0c3e392ee9a923853"}, + {file = "munge-1.3.0-py3-none-any.whl", hash = "sha256:fe24e8fd33b388c70abf296f94814aec596d10eb96c0b95a669a49f71012d1f0"}, + {file = "munge-1.3.0.tar.gz", hash = "sha256:5417d47b46e4215d561ce7c01e46098787476bb81eb0c70a7b9b20b38eafa0e5"}, ] [package.dependencies] click = ">=5.1" -PyYAML = {version = ">=5.1,<6.0", optional = true, markers = "extra == \"yaml\""} -requests = ">=2.6,<3.0" -tomlkit = {version = ">=0.7.2,<0.8.0", optional = true, markers = "extra == \"tomlkit\""} +PyYAML = {version = ">=5.1", optional = true, markers = "extra == \"yaml\""} +requests = ">=2.6" +tomlkit = {version = ">=0.7.2", optional = true, markers = "extra == \"tomlkit\""} [package.extras] -toml = ["toml (>=0.10.2,<0.11.0)"] -tomlkit = ["tomlkit (>=0.7.2,<0.8.0)"] -yaml = ["PyYAML (>=5.1,<6.0)"] +toml = ["toml (>=0.10.2)"] +tomlkit = ["tomlkit (>=0.7.2)"] +yaml = ["PyYAML (>=5.1)"] [[package]] name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -1679,6 +1779,7 @@ files = [ name = "mysqlclient" version = "2.2.0" description = "Python interface to MySQL" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1695,6 +1796,7 @@ files = [ name = "nodeenv" version = "1.8.0" description = "Node.js virtual environment builder" +category = "dev" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" files = [ @@ -1709,6 +1811,7 @@ setuptools = "*" name = "oauthlib" version = "3.2.2" description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1725,6 +1828,7 @@ signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] name = "odfpy" version = "1.4.1" description = "Python API and tools to manipulate OpenDocument files" +category = "main" optional = false python-versions = "*" files = [ @@ -1738,6 +1842,7 @@ defusedxml = "*" name = "openapi-codec" version = "1.3.2" description = "An OpenAPI codec for Core API." +category = "main" optional = false python-versions = "*" files = [ @@ -1751,6 +1856,7 @@ coreapi = ">=2.2.0" name = "openpyxl" version = "3.1.2" description = "A Python library to read/write Excel 2010 xlsx/xlsm files" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1765,6 +1871,7 @@ et-xmlfile = "*" name = "outcome" version = "1.2.0" description = "Capture the outcome of Python function calls." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1779,6 +1886,7 @@ attrs = ">=19.2.0" name = "packaging" version = "23.1" description = "Core utilities for Python packages" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1790,6 +1898,7 @@ files = [ name = "passlib" version = "1.7.4" description = "comprehensive password hashing framework supporting over 30 schemes" +category = "main" optional = false python-versions = "*" files = [ @@ -1807,6 +1916,7 @@ totp = ["cryptography"] name = "pathspec" version = "0.11.1" description = "Utility library for gitignore style pattern matching of file paths." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1818,102 +1928,99 @@ files = [ name = "peeringdb" version = "1.5.0" description = "PeeringDB Django models" +category = "main" optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "peeringdb-1.5.0-py3-none-any.whl", hash = "sha256:0b8589198fdeb847b1b6fbf676dd53cb6b44d66e175f9dc78259b17273aba6ca"}, - {file = "peeringdb-1.5.0.tar.gz", hash = "sha256:c164e0ad9d57b783a31f4b5023cf62fb77ae89bf6fdb1c1e0b930d35f1888496"}, -] +python-versions = "^3.8" +files = [] +develop = false [package.dependencies] -confu = ">=1,<2" -munge = {version = ">=1.2.0,<2.0.0", extras = ["tomlkit", "yaml"]} -"twentyc.rpc" = ">=1,<2" +confu = "^1" +munge = {version = "^1.2.0", extras = ["tomlkit", "yaml"]} +"twentyc.rpc" = "^1" + +[package.source] +type = "git" +url = "https://github.com/peeringdb/peeringdb-py.git" +reference = "support_202306" +resolved_reference = "0f9f0215bf5b671108e3763def795e45952e1870" [[package]] name = "phonenumbers" -version = "8.13.15" +version = "8.13.16" description = "Python version of Google's common library for parsing, formatting, storing and validating international phone numbers." +category = "main" optional = false python-versions = "*" files = [ - {file = "phonenumbers-8.13.15-py2.py3-none-any.whl", hash = "sha256:634b277dc53933962961697211746f2fb7bf945a6725a853a1556cdb4a7531e4"}, - {file = "phonenumbers-8.13.15.tar.gz", hash = "sha256:adf80fc0027ce8eac990f5e1d3fa00022b481133d65fa40c1c40ae9020fc5a66"}, + {file = "phonenumbers-8.13.16-py2.py3-none-any.whl", hash = "sha256:d7ca6b392eac44b50b923c6dc661525c73b21fa506723d2540c72de3db023442"}, + {file = "phonenumbers-8.13.16.tar.gz", hash = "sha256:92772b142eac9f3aeb0e87958c436996ac16d468d96646483997c8a57517933b"}, ] [[package]] name = "pillow" -version = "9.5.0" +version = "10.0.0" description = "Python Imaging Library (Fork)" +category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "Pillow-9.5.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:ace6ca218308447b9077c14ea4ef381ba0b67ee78d64046b3f19cf4e1139ad16"}, - {file = "Pillow-9.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d3d403753c9d5adc04d4694d35cf0391f0f3d57c8e0030aac09d7678fa8030aa"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ba1b81ee69573fe7124881762bb4cd2e4b6ed9dd28c9c60a632902fe8db8b38"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe7e1c262d3392afcf5071df9afa574544f28eac825284596ac6db56e6d11062"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f36397bf3f7d7c6a3abdea815ecf6fd14e7fcd4418ab24bae01008d8d8ca15e"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:252a03f1bdddce077eff2354c3861bf437c892fb1832f75ce813ee94347aa9b5"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:85ec677246533e27770b0de5cf0f9d6e4ec0c212a1f89dfc941b64b21226009d"}, - {file = "Pillow-9.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b416f03d37d27290cb93597335a2f85ed446731200705b22bb927405320de903"}, - {file = "Pillow-9.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1781a624c229cb35a2ac31cc4a77e28cafc8900733a864870c49bfeedacd106a"}, - {file = "Pillow-9.5.0-cp310-cp310-win32.whl", hash = "sha256:8507eda3cd0608a1f94f58c64817e83ec12fa93a9436938b191b80d9e4c0fc44"}, - {file = "Pillow-9.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:d3c6b54e304c60c4181da1c9dadf83e4a54fd266a99c70ba646a9baa626819eb"}, - {file = "Pillow-9.5.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:7ec6f6ce99dab90b52da21cf0dc519e21095e332ff3b399a357c187b1a5eee32"}, - {file = "Pillow-9.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:560737e70cb9c6255d6dcba3de6578a9e2ec4b573659943a5e7e4af13f298f5c"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96e88745a55b88a7c64fa49bceff363a1a27d9a64e04019c2281049444a571e3"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d9c206c29b46cfd343ea7cdfe1232443072bbb270d6a46f59c259460db76779a"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cfcc2c53c06f2ccb8976fb5c71d448bdd0a07d26d8e07e321c103416444c7ad1"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:a0f9bb6c80e6efcde93ffc51256d5cfb2155ff8f78292f074f60f9e70b942d99"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8d935f924bbab8f0a9a28404422da8af4904e36d5c33fc6f677e4c4485515625"}, - {file = "Pillow-9.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fed1e1cf6a42577953abbe8e6cf2fe2f566daebde7c34724ec8803c4c0cda579"}, - {file = "Pillow-9.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c1170d6b195555644f0616fd6ed929dfcf6333b8675fcca044ae5ab110ded296"}, - {file = "Pillow-9.5.0-cp311-cp311-win32.whl", hash = "sha256:54f7102ad31a3de5666827526e248c3530b3a33539dbda27c6843d19d72644ec"}, - {file = "Pillow-9.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:cfa4561277f677ecf651e2b22dc43e8f5368b74a25a8f7d1d4a3a243e573f2d4"}, - {file = "Pillow-9.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:965e4a05ef364e7b973dd17fc765f42233415974d773e82144c9bbaaaea5d089"}, - {file = "Pillow-9.5.0-cp312-cp312-win32.whl", hash = "sha256:22baf0c3cf0c7f26e82d6e1adf118027afb325e703922c8dfc1d5d0156bb2eeb"}, - {file = "Pillow-9.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:432b975c009cf649420615388561c0ce7cc31ce9b2e374db659ee4f7d57a1f8b"}, - {file = "Pillow-9.5.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:5d4ebf8e1db4441a55c509c4baa7a0587a0210f7cd25fcfe74dbbce7a4bd1906"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:375f6e5ee9620a271acb6820b3d1e94ffa8e741c0601db4c0c4d3cb0a9c224bf"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99eb6cafb6ba90e436684e08dad8be1637efb71c4f2180ee6b8f940739406e78"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dfaaf10b6172697b9bceb9a3bd7b951819d1ca339a5ef294d1f1ac6d7f63270"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:763782b2e03e45e2c77d7779875f4432e25121ef002a41829d8868700d119392"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:35f6e77122a0c0762268216315bf239cf52b88865bba522999dc38f1c52b9b47"}, - {file = "Pillow-9.5.0-cp37-cp37m-win32.whl", hash = "sha256:aca1c196f407ec7cf04dcbb15d19a43c507a81f7ffc45b690899d6a76ac9fda7"}, - {file = "Pillow-9.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322724c0032af6692456cd6ed554bb85f8149214d97398bb80613b04e33769f6"}, - {file = "Pillow-9.5.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:a0aa9417994d91301056f3d0038af1199eb7adc86e646a36b9e050b06f526597"}, - {file = "Pillow-9.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f8286396b351785801a976b1e85ea88e937712ee2c3ac653710a4a57a8da5d9c"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c830a02caeb789633863b466b9de10c015bded434deb3ec87c768e53752ad22a"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fbd359831c1657d69bb81f0db962905ee05e5e9451913b18b831febfe0519082"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8fc330c3370a81bbf3f88557097d1ea26cd8b019d6433aa59f71195f5ddebbf"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:7002d0797a3e4193c7cdee3198d7c14f92c0836d6b4a3f3046a64bd1ce8df2bf"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:229e2c79c00e85989a34b5981a2b67aa079fd08c903f0aaead522a1d68d79e51"}, - {file = "Pillow-9.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9adf58f5d64e474bed00d69bcd86ec4bcaa4123bfa70a65ce72e424bfb88ed96"}, - {file = "Pillow-9.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:662da1f3f89a302cc22faa9f14a262c2e3951f9dbc9617609a47521c69dd9f8f"}, - {file = "Pillow-9.5.0-cp38-cp38-win32.whl", hash = "sha256:6608ff3bf781eee0cd14d0901a2b9cc3d3834516532e3bd673a0a204dc8615fc"}, - {file = "Pillow-9.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:e49eb4e95ff6fd7c0c402508894b1ef0e01b99a44320ba7d8ecbabefddcc5569"}, - {file = "Pillow-9.5.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:482877592e927fd263028c105b36272398e3e1be3269efda09f6ba21fd83ec66"}, - {file = "Pillow-9.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3ded42b9ad70e5f1754fb7c2e2d6465a9c842e41d178f262e08b8c85ed8a1d8e"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c446d2245ba29820d405315083d55299a796695d747efceb5717a8b450324115"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8aca1152d93dcc27dc55395604dcfc55bed5f25ef4c98716a928bacba90d33a3"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:608488bdcbdb4ba7837461442b90ea6f3079397ddc968c31265c1e056964f1ef"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:60037a8db8750e474af7ffc9faa9b5859e6c6d0a50e55c45576bf28be7419705"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:07999f5834bdc404c442146942a2ecadd1cb6292f5229f4ed3b31e0a108746b1"}, - {file = "Pillow-9.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a127ae76092974abfbfa38ca2d12cbeddcdeac0fb71f9627cc1135bedaf9d51a"}, - {file = "Pillow-9.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:489f8389261e5ed43ac8ff7b453162af39c3e8abd730af8363587ba64bb2e865"}, - {file = "Pillow-9.5.0-cp39-cp39-win32.whl", hash = "sha256:9b1af95c3a967bf1da94f253e56b6286b50af23392a886720f563c547e48e964"}, - {file = "Pillow-9.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:77165c4a5e7d5a284f10a6efaa39a0ae8ba839da344f20b111d62cc932fa4e5d"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:833b86a98e0ede388fa29363159c9b1a294b0905b5128baf01db683672f230f5"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aaf305d6d40bd9632198c766fb64f0c1a83ca5b667f16c1e79e1661ab5060140"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0852ddb76d85f127c135b6dd1f0bb88dbb9ee990d2cd9aa9e28526c93e794fba"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:91ec6fe47b5eb5a9968c79ad9ed78c342b1f97a091677ba0e012701add857829"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cb841572862f629b99725ebaec3287fc6d275be9b14443ea746c1dd325053cbd"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c380b27d041209b849ed246b111b7c166ba36d7933ec6e41175fd15ab9eb1572"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c9af5a3b406a50e313467e3565fc99929717f780164fe6fbb7704edba0cebbe"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5671583eab84af046a397d6d0ba25343c00cd50bce03787948e0fff01d4fd9b1"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:84a6f19ce086c1bf894644b43cd129702f781ba5751ca8572f08aa40ef0ab7b7"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1e7723bd90ef94eda669a3c2c19d549874dd5badaeefabefd26053304abe5799"}, - {file = "Pillow-9.5.0.tar.gz", hash = "sha256:bf548479d336726d7a0eceb6e767e179fbde37833ae42794602631a070d630f1"}, + {file = "Pillow-10.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1f62406a884ae75fb2f818694469519fb685cc7eaff05d3451a9ebe55c646891"}, + {file = "Pillow-10.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d5db32e2a6ccbb3d34d87c87b432959e0db29755727afb37290e10f6e8e62614"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edf4392b77bdc81f36e92d3a07a5cd072f90253197f4a52a55a8cec48a12483b"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:520f2a520dc040512699f20fa1c363eed506e94248d71f85412b625026f6142c"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:8c11160913e3dd06c8ffdb5f233a4f254cb449f4dfc0f8f4549eda9e542c93d1"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a74ba0c356aaa3bb8e3eb79606a87669e7ec6444be352870623025d75a14a2bf"}, + {file = "Pillow-10.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5d0dae4cfd56969d23d94dc8e89fb6a217be461c69090768227beb8ed28c0a3"}, + {file = "Pillow-10.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22c10cc517668d44b211717fd9775799ccec4124b9a7f7b3635fc5386e584992"}, + {file = "Pillow-10.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:dffe31a7f47b603318c609f378ebcd57f1554a3a6a8effbc59c3c69f804296de"}, + {file = "Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485"}, + {file = "Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629"}, + {file = "Pillow-10.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3b08d4cc24f471b2c8ca24ec060abf4bebc6b144cb89cba638c720546b1cf538"}, + {file = "Pillow-10.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d737a602fbd82afd892ca746392401b634e278cb65d55c4b7a8f48e9ef8d008d"}, + {file = "Pillow-10.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f"}, + {file = "Pillow-10.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:bc2ec7c7b5d66b8ec9ce9f720dbb5fa4bace0f545acd34870eff4a369b44bf37"}, + {file = "Pillow-10.0.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:d80cf684b541685fccdd84c485b31ce73fc5c9b5d7523bf1394ce134a60c6883"}, + {file = "Pillow-10.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76de421f9c326da8f43d690110f0e79fe3ad1e54be811545d7d91898b4c8493e"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81ff539a12457809666fef6624684c008e00ff6bf455b4b89fd00a140eecd640"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce543ed15570eedbb85df19b0a1a7314a9c8141a36ce089c0a894adbfccb4568"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:685ac03cc4ed5ebc15ad5c23bc555d68a87777586d970c2c3e216619a5476223"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:d72e2ecc68a942e8cf9739619b7f408cc7b272b279b56b2c83c6123fcfa5cdff"}, + {file = "Pillow-10.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d50b6aec14bc737742ca96e85d6d0a5f9bfbded018264b3b70ff9d8c33485551"}, + {file = "Pillow-10.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:00e65f5e822decd501e374b0650146063fbb30a7264b4d2744bdd7b913e0cab5"}, + {file = "Pillow-10.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:f31f9fdbfecb042d046f9d91270a0ba28368a723302786c0009ee9b9f1f60199"}, + {file = "Pillow-10.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:1ce91b6ec08d866b14413d3f0bbdea7e24dfdc8e59f562bb77bc3fe60b6144ca"}, + {file = "Pillow-10.0.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:349930d6e9c685c089284b013478d6f76e3a534e36ddfa912cde493f235372f3"}, + {file = "Pillow-10.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3a684105f7c32488f7153905a4e3015a3b6c7182e106fe3c37fbb5ef3e6994c3"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4f69b3700201b80bb82c3a97d5e9254084f6dd5fb5b16fc1a7b974260f89f43"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f07ea8d2f827d7d2a49ecf1639ec02d75ffd1b88dcc5b3a61bbb37a8759ad8d"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:040586f7d37b34547153fa383f7f9aed68b738992380ac911447bb78f2abe530"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:f88a0b92277de8e3ca715a0d79d68dc82807457dae3ab8699c758f07c20b3c51"}, + {file = "Pillow-10.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c7cf14a27b0d6adfaebb3ae4153f1e516df54e47e42dcc073d7b3d76111a8d86"}, + {file = "Pillow-10.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3400aae60685b06bb96f99a21e1ada7bc7a413d5f49bce739828ecd9391bb8f7"}, + {file = "Pillow-10.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:dbc02381779d412145331789b40cc7b11fdf449e5d94f6bc0b080db0a56ea3f0"}, + {file = "Pillow-10.0.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:9211e7ad69d7c9401cfc0e23d49b69ca65ddd898976d660a2fa5904e3d7a9baa"}, + {file = "Pillow-10.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:faaf07ea35355b01a35cb442dd950d8f1bb5b040a7787791a535de13db15ed90"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9f72a021fbb792ce98306ffb0c348b3c9cb967dce0f12a49aa4c3d3fdefa967"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f7c16705f44e0504a3a2a14197c1f0b32a95731d251777dcb060aa83022cb2d"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:76edb0a1fa2b4745fb0c99fb9fb98f8b180a1bbceb8be49b087e0b21867e77d3"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:368ab3dfb5f49e312231b6f27b8820c823652b7cd29cfbd34090565a015e99ba"}, + {file = "Pillow-10.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:608bfdee0d57cf297d32bcbb3c728dc1da0907519d1784962c5f0c68bb93e5a3"}, + {file = "Pillow-10.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5c6e3df6bdd396749bafd45314871b3d0af81ff935b2d188385e970052091017"}, + {file = "Pillow-10.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:7be600823e4c8631b74e4a0d38384c73f680e6105a7d3c6824fcf226c178c7e6"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:92be919bbc9f7d09f7ae343c38f5bb21c973d2576c1d45600fce4b74bafa7ac0"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8182b523b2289f7c415f589118228d30ac8c355baa2f3194ced084dac2dbba"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:38250a349b6b390ee6047a62c086d3817ac69022c127f8a5dc058c31ccef17f3"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:88af2003543cc40c80f6fca01411892ec52b11021b3dc22ec3bc9d5afd1c5334"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c189af0545965fa8d3b9613cfdb0cd37f9d71349e0f7750e1fd704648d475ed2"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce7b031a6fc11365970e6a5686d7ba8c63e4c1cf1ea143811acbb524295eabed"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:db24668940f82321e746773a4bc617bfac06ec831e5c88b643f91f122a785684"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:efe8c0681042536e0d06c11f48cebe759707c9e9abf880ee213541c5b46c5bf3"}, + {file = "Pillow-10.0.0.tar.gz", hash = "sha256:9c82b5b3e043c7af0d95792d0d20ccf68f61a1fec6b3530e718b688422727396"}, ] [package.extras] @@ -1922,13 +2029,14 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa [[package]] name = "platformdirs" -version = "3.8.0" +version = "3.8.1" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "platformdirs-3.8.0-py3-none-any.whl", hash = "sha256:ca9ed98ce73076ba72e092b23d3c93ea6c4e186b3f1c3dad6edd98ff6ffcca2e"}, - {file = "platformdirs-3.8.0.tar.gz", hash = "sha256:b0cabcb11063d21a0b261d557acb0a9d2126350e63b70cdf7db6347baea456dc"}, + {file = "platformdirs-3.8.1-py3-none-any.whl", hash = "sha256:cec7b889196b9144d088e4c57d9ceef7374f6c39694ad1577a0aab50d27ea28c"}, + {file = "platformdirs-3.8.1.tar.gz", hash = "sha256:f87ca4fcff7d2b0f81c6a748a77973d7af0f4d526f98f308477c3c436c74d528"}, ] [package.extras] @@ -1939,6 +2047,7 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest- name = "pluggy" version = "1.2.0" description = "plugin and hook calling mechanisms for python" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1954,6 +2063,7 @@ testing = ["pytest", "pytest-benchmark"] name = "pre-commit" version = "3.3.3" description = "A framework for managing and maintaining multi-language pre-commit hooks." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1972,6 +2082,7 @@ virtualenv = ">=20.10.0" name = "pycodestyle" version = "2.10.0" description = "Python style guide checker" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1983,6 +2094,7 @@ files = [ 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.*" files = [ @@ -1992,47 +2104,48 @@ files = [ [[package]] name = "pydantic" -version = "1.10.9" +version = "1.10.11" description = "Data validation and settings management using python type hints" +category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-1.10.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e692dec4a40bfb40ca530e07805b1208c1de071a18d26af4a2a0d79015b352ca"}, - {file = "pydantic-1.10.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3c52eb595db83e189419bf337b59154bdcca642ee4b2a09e5d7797e41ace783f"}, - {file = "pydantic-1.10.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:939328fd539b8d0edf244327398a667b6b140afd3bf7e347cf9813c736211896"}, - {file = "pydantic-1.10.9-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b48d3d634bca23b172f47f2335c617d3fcb4b3ba18481c96b7943a4c634f5c8d"}, - {file = "pydantic-1.10.9-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f0b7628fb8efe60fe66fd4adadd7ad2304014770cdc1f4934db41fe46cc8825f"}, - {file = "pydantic-1.10.9-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e1aa5c2410769ca28aa9a7841b80d9d9a1c5f223928ca8bec7e7c9a34d26b1d4"}, - {file = "pydantic-1.10.9-cp310-cp310-win_amd64.whl", hash = "sha256:eec39224b2b2e861259d6f3c8b6290d4e0fbdce147adb797484a42278a1a486f"}, - {file = "pydantic-1.10.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d111a21bbbfd85c17248130deac02bbd9b5e20b303338e0dbe0faa78330e37e0"}, - {file = "pydantic-1.10.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2e9aec8627a1a6823fc62fb96480abe3eb10168fd0d859ee3d3b395105ae19a7"}, - {file = "pydantic-1.10.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07293ab08e7b4d3c9d7de4949a0ea571f11e4557d19ea24dd3ae0c524c0c334d"}, - {file = "pydantic-1.10.9-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ee829b86ce984261d99ff2fd6e88f2230068d96c2a582f29583ed602ef3fc2c"}, - {file = "pydantic-1.10.9-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4b466a23009ff5cdd7076eb56aca537c745ca491293cc38e72bf1e0e00de5b91"}, - {file = "pydantic-1.10.9-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7847ca62e581e6088d9000f3c497267868ca2fa89432714e21a4fb33a04d52e8"}, - {file = "pydantic-1.10.9-cp311-cp311-win_amd64.whl", hash = "sha256:7845b31959468bc5b78d7b95ec52fe5be32b55d0d09983a877cca6aedc51068f"}, - {file = "pydantic-1.10.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:517a681919bf880ce1dac7e5bc0c3af1e58ba118fd774da2ffcd93c5f96eaece"}, - {file = "pydantic-1.10.9-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67195274fd27780f15c4c372f4ba9a5c02dad6d50647b917b6a92bf00b3d301a"}, - {file = "pydantic-1.10.9-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2196c06484da2b3fded1ab6dbe182bdabeb09f6318b7fdc412609ee2b564c49a"}, - {file = "pydantic-1.10.9-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:6257bb45ad78abacda13f15bde5886efd6bf549dd71085e64b8dcf9919c38b60"}, - {file = "pydantic-1.10.9-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3283b574b01e8dbc982080d8287c968489d25329a463b29a90d4157de4f2baaf"}, - {file = "pydantic-1.10.9-cp37-cp37m-win_amd64.whl", hash = "sha256:5f8bbaf4013b9a50e8100333cc4e3fa2f81214033e05ac5aa44fa24a98670a29"}, - {file = "pydantic-1.10.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9cd67fb763248cbe38f0593cd8611bfe4b8ad82acb3bdf2b0898c23415a1f82"}, - {file = "pydantic-1.10.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f50e1764ce9353be67267e7fd0da08349397c7db17a562ad036aa7c8f4adfdb6"}, - {file = "pydantic-1.10.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73ef93e5e1d3c8e83f1ff2e7fdd026d9e063c7e089394869a6e2985696693766"}, - {file = "pydantic-1.10.9-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:128d9453d92e6e81e881dd7e2484e08d8b164da5507f62d06ceecf84bf2e21d3"}, - {file = "pydantic-1.10.9-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ad428e92ab68798d9326bb3e5515bc927444a3d71a93b4a2ca02a8a5d795c572"}, - {file = "pydantic-1.10.9-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fab81a92f42d6d525dd47ced310b0c3e10c416bbfae5d59523e63ea22f82b31e"}, - {file = "pydantic-1.10.9-cp38-cp38-win_amd64.whl", hash = "sha256:963671eda0b6ba6926d8fc759e3e10335e1dc1b71ff2a43ed2efd6996634dafb"}, - {file = "pydantic-1.10.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:970b1bdc6243ef663ba5c7e36ac9ab1f2bfecb8ad297c9824b542d41a750b298"}, - {file = "pydantic-1.10.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7e1d5290044f620f80cf1c969c542a5468f3656de47b41aa78100c5baa2b8276"}, - {file = "pydantic-1.10.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83fcff3c7df7adff880622a98022626f4f6dbce6639a88a15a3ce0f96466cb60"}, - {file = "pydantic-1.10.9-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0da48717dc9495d3a8f215e0d012599db6b8092db02acac5e0d58a65248ec5bc"}, - {file = "pydantic-1.10.9-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0a2aabdc73c2a5960e87c3ffebca6ccde88665616d1fd6d3db3178ef427b267a"}, - {file = "pydantic-1.10.9-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9863b9420d99dfa9c064042304868e8ba08e89081428a1c471858aa2af6f57c4"}, - {file = "pydantic-1.10.9-cp39-cp39-win_amd64.whl", hash = "sha256:e7c9900b43ac14110efa977be3da28931ffc74c27e96ee89fbcaaf0b0fe338e1"}, - {file = "pydantic-1.10.9-py3-none-any.whl", hash = "sha256:6cafde02f6699ce4ff643417d1a9223716ec25e228ddc3b436fe7e2d25a1f305"}, - {file = "pydantic-1.10.9.tar.gz", hash = "sha256:95c70da2cd3b6ddf3b9645ecaa8d98f3d80c606624b6d245558d202cd23ea3be"}, + {file = "pydantic-1.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ff44c5e89315b15ff1f7fdaf9853770b810936d6b01a7bcecaa227d2f8fe444f"}, + {file = "pydantic-1.10.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a6c098d4ab5e2d5b3984d3cb2527e2d6099d3de85630c8934efcfdc348a9760e"}, + {file = "pydantic-1.10.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16928fdc9cb273c6af00d9d5045434c39afba5f42325fb990add2c241402d151"}, + {file = "pydantic-1.10.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0588788a9a85f3e5e9ebca14211a496409cb3deca5b6971ff37c556d581854e7"}, + {file = "pydantic-1.10.11-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e9baf78b31da2dc3d3f346ef18e58ec5f12f5aaa17ac517e2ffd026a92a87588"}, + {file = "pydantic-1.10.11-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:373c0840f5c2b5b1ccadd9286782852b901055998136287828731868027a724f"}, + {file = "pydantic-1.10.11-cp310-cp310-win_amd64.whl", hash = "sha256:c3339a46bbe6013ef7bdd2844679bfe500347ac5742cd4019a88312aa58a9847"}, + {file = "pydantic-1.10.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:08a6c32e1c3809fbc49debb96bf833164f3438b3696abf0fbeceb417d123e6eb"}, + {file = "pydantic-1.10.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a451ccab49971af043ec4e0d207cbc8cbe53dbf148ef9f19599024076fe9c25b"}, + {file = "pydantic-1.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b02d24f7b2b365fed586ed73582c20f353a4c50e4be9ba2c57ab96f8091ddae"}, + {file = "pydantic-1.10.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f34739a89260dfa420aa3cbd069fbcc794b25bbe5c0a214f8fb29e363484b66"}, + {file = "pydantic-1.10.11-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e297897eb4bebde985f72a46a7552a7556a3dd11e7f76acda0c1093e3dbcf216"}, + {file = "pydantic-1.10.11-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d185819a7a059550ecb85d5134e7d40f2565f3dd94cfd870132c5f91a89cf58c"}, + {file = "pydantic-1.10.11-cp311-cp311-win_amd64.whl", hash = "sha256:4400015f15c9b464c9db2d5d951b6a780102cfa5870f2c036d37c23b56f7fc1b"}, + {file = "pydantic-1.10.11-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2417de68290434461a266271fc57274a138510dca19982336639484c73a07af6"}, + {file = "pydantic-1.10.11-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:331c031ba1554b974c98679bd0780d89670d6fd6f53f5d70b10bdc9addee1713"}, + {file = "pydantic-1.10.11-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8268a735a14c308923e8958363e3a3404f6834bb98c11f5ab43251a4e410170c"}, + {file = "pydantic-1.10.11-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:44e51ba599c3ef227e168424e220cd3e544288c57829520dc90ea9cb190c3248"}, + {file = "pydantic-1.10.11-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d7781f1d13b19700b7949c5a639c764a077cbbdd4322ed505b449d3ca8edcb36"}, + {file = "pydantic-1.10.11-cp37-cp37m-win_amd64.whl", hash = "sha256:7522a7666157aa22b812ce14c827574ddccc94f361237ca6ea8bb0d5c38f1629"}, + {file = "pydantic-1.10.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc64eab9b19cd794a380179ac0e6752335e9555d214cfcb755820333c0784cb3"}, + {file = "pydantic-1.10.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8dc77064471780262b6a68fe67e013298d130414d5aaf9b562c33987dbd2cf4f"}, + {file = "pydantic-1.10.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe429898f2c9dd209bd0632a606bddc06f8bce081bbd03d1c775a45886e2c1cb"}, + {file = "pydantic-1.10.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:192c608ad002a748e4a0bed2ddbcd98f9b56df50a7c24d9a931a8c5dd053bd3d"}, + {file = "pydantic-1.10.11-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ef55392ec4bb5721f4ded1096241e4b7151ba6d50a50a80a2526c854f42e6a2f"}, + {file = "pydantic-1.10.11-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:41e0bb6efe86281623abbeeb0be64eab740c865388ee934cd3e6a358784aca6e"}, + {file = "pydantic-1.10.11-cp38-cp38-win_amd64.whl", hash = "sha256:265a60da42f9f27e0b1014eab8acd3e53bd0bad5c5b4884e98a55f8f596b2c19"}, + {file = "pydantic-1.10.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:469adf96c8e2c2bbfa655fc7735a2a82f4c543d9fee97bd113a7fb509bf5e622"}, + {file = "pydantic-1.10.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e6cbfbd010b14c8a905a7b10f9fe090068d1744d46f9e0c021db28daeb8b6de1"}, + {file = "pydantic-1.10.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abade85268cc92dff86d6effcd917893130f0ff516f3d637f50dadc22ae93999"}, + {file = "pydantic-1.10.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9738b0f2e6c70f44ee0de53f2089d6002b10c33264abee07bdb5c7f03038303"}, + {file = "pydantic-1.10.11-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:787cf23e5a0cde753f2eabac1b2e73ae3844eb873fd1f5bdbff3048d8dbb7604"}, + {file = "pydantic-1.10.11-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:174899023337b9fc685ac8adaa7b047050616136ccd30e9070627c1aaab53a13"}, + {file = "pydantic-1.10.11-cp39-cp39-win_amd64.whl", hash = "sha256:1954f8778489a04b245a1e7b8b22a9d3ea8ef49337285693cf6959e4b757535e"}, + {file = "pydantic-1.10.11-py3-none-any.whl", hash = "sha256:008c5e266c8aada206d0627a011504e14268a62091450210eda7c07fabe6963e"}, + {file = "pydantic-1.10.11.tar.gz", hash = "sha256:f66d479cf7eb331372c470614be6511eae96f1f120344c25f3f9bb59fb1b5528"}, ] [package.dependencies] @@ -2046,6 +2159,7 @@ email = ["email-validator (>=1.0.3)"] name = "pydot" version = "1.4.2" description = "Python interface to Graphviz's Dot" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -2060,6 +2174,7 @@ pyparsing = ">=2.1.4" name = "pyflakes" version = "3.0.1" description = "passive checker of Python programs" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2071,6 +2186,7 @@ files = [ name = "pyjwt" version = "2.7.0" description = "JSON Web Token implementation in Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2091,6 +2207,7 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] name = "pymdgen" version = "1.0.0" description = "python code markdown documentation generator" +category = "dev" optional = false python-versions = ">=3.6,<4.0" files = [ @@ -2101,6 +2218,7 @@ files = [ name = "pyopenssl" version = "23.2.0" description = "Python wrapper module around the OpenSSL library" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2119,6 +2237,7 @@ test = ["flaky", "pretend", "pytest (>=3.0.1)"] name = "pyparsing" version = "3.1.0" description = "pyparsing module - Classes and methods to define and execute parsing grammars" +category = "dev" optional = false python-versions = ">=3.6.8" files = [ @@ -2133,6 +2252,7 @@ diagrams = ["jinja2", "railroad-diagrams"] name = "pypng" version = "0.20220715.0" description = "Pure Python library for saving and loading PNG images" +category = "main" optional = false python-versions = "*" files = [ @@ -2140,46 +2260,11 @@ files = [ {file = "pypng-0.20220715.0.tar.gz", hash = "sha256:739c433ba96f078315de54c0db975aee537cbc3e1d0ae4ed9aab0ca1e427e2c1"}, ] -[[package]] -name = "pyrsistent" -version = "0.19.3" -description = "Persistent/Functional/Immutable data structures" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pyrsistent-0.19.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:20460ac0ea439a3e79caa1dbd560344b64ed75e85d8703943e0b66c2a6150e4a"}, - {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c18264cb84b5e68e7085a43723f9e4c1fd1d935ab240ce02c0324a8e01ccb64"}, - {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b774f9288dda8d425adb6544e5903f1fb6c273ab3128a355c6b972b7df39dcf"}, - {file = "pyrsistent-0.19.3-cp310-cp310-win32.whl", hash = "sha256:5a474fb80f5e0d6c9394d8db0fc19e90fa540b82ee52dba7d246a7791712f74a"}, - {file = "pyrsistent-0.19.3-cp310-cp310-win_amd64.whl", hash = "sha256:49c32f216c17148695ca0e02a5c521e28a4ee6c5089f97e34fe24163113722da"}, - {file = "pyrsistent-0.19.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f0774bf48631f3a20471dd7c5989657b639fd2d285b861237ea9e82c36a415a9"}, - {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ab2204234c0ecd8b9368dbd6a53e83c3d4f3cab10ecaf6d0e772f456c442393"}, - {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e42296a09e83028b3476f7073fcb69ffebac0e66dbbfd1bd847d61f74db30f19"}, - {file = "pyrsistent-0.19.3-cp311-cp311-win32.whl", hash = "sha256:64220c429e42a7150f4bfd280f6f4bb2850f95956bde93c6fda1b70507af6ef3"}, - {file = "pyrsistent-0.19.3-cp311-cp311-win_amd64.whl", hash = "sha256:016ad1afadf318eb7911baa24b049909f7f3bb2c5b1ed7b6a8f21db21ea3faa8"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4db1bd596fefd66b296a3d5d943c94f4fac5bcd13e99bffe2ba6a759d959a28"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aeda827381f5e5d65cced3024126529ddc4289d944f75e090572c77ceb19adbf"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:42ac0b2f44607eb92ae88609eda931a4f0dfa03038c44c772e07f43e738bcac9"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-win32.whl", hash = "sha256:e8f2b814a3dc6225964fa03d8582c6e0b6650d68a232df41e3cc1b66a5d2f8d1"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c9bb60a40a0ab9aba40a59f68214eed5a29c6274c83b2cc206a359c4a89fa41b"}, - {file = "pyrsistent-0.19.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a2471f3f8693101975b1ff85ffd19bb7ca7dd7c38f8a81701f67d6b4f97b87d8"}, - {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc5d149f31706762c1f8bda2e8c4f8fead6e80312e3692619a75301d3dbb819a"}, - {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3311cb4237a341aa52ab8448c27e3a9931e2ee09561ad150ba94e4cfd3fc888c"}, - {file = "pyrsistent-0.19.3-cp38-cp38-win32.whl", hash = "sha256:f0e7c4b2f77593871e918be000b96c8107da48444d57005b6a6bc61fb4331b2c"}, - {file = "pyrsistent-0.19.3-cp38-cp38-win_amd64.whl", hash = "sha256:c147257a92374fde8498491f53ffa8f4822cd70c0d85037e09028e478cababb7"}, - {file = "pyrsistent-0.19.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b735e538f74ec31378f5a1e3886a26d2ca6351106b4dfde376a26fc32a044edc"}, - {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99abb85579e2165bd8522f0c0138864da97847875ecbd45f3e7e2af569bfc6f2"}, - {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a8cb235fa6d3fd7aae6a4f1429bbb1fec1577d978098da1252f0489937786f3"}, - {file = "pyrsistent-0.19.3-cp39-cp39-win32.whl", hash = "sha256:c74bed51f9b41c48366a286395c67f4e894374306b197e62810e0fdaf2364da2"}, - {file = "pyrsistent-0.19.3-cp39-cp39-win_amd64.whl", hash = "sha256:878433581fc23e906d947a6814336eee031a00e6defba224234169ae3d3d6a98"}, - {file = "pyrsistent-0.19.3-py3-none-any.whl", hash = "sha256:ccf0d6bd208f8111179f0c26fdf84ed7c3891982f2edaeae7422575f47e66b64"}, - {file = "pyrsistent-0.19.3.tar.gz", hash = "sha256:1a2994773706bbb4995c31a97bc94f1418314923bd1048c6d964837040376440"}, -] - [[package]] name = "pysocks" version = "1.7.1" description = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information." +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -2192,6 +2277,7 @@ files = [ name = "pytest" version = "7.4.0" description = "pytest: simple powerful testing with Python" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2214,6 +2300,7 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no name = "pytest-cov" version = "4.1.0" description = "Pytest plugin for measuring coverage." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2232,6 +2319,7 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale name = "pytest-django" version = "4.5.2" description = "A Django plugin for pytest." +category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -2250,6 +2338,7 @@ testing = ["Django", "django-configurations (>=2.0)"] name = "pytest-filedata" version = "0.4.0" description = "easily load data from files" +category = "dev" optional = false python-versions = "*" files = [ @@ -2265,6 +2354,7 @@ requests-mock = ">=1,<2" name = "pytest-mock" version = "3.11.1" description = "Thin-wrapper around the mock package for easier use with pytest" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2282,6 +2372,7 @@ dev = ["pre-commit", "pytest-asyncio", "tox"] 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" files = [ @@ -2296,6 +2387,7 @@ six = ">=1.5" name = "python-dotenv" version = "1.0.0" description = "Read key-value pairs from a .env file and set them as environment variables" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2310,6 +2402,7 @@ cli = ["click (>=5.0)"] name = "python3-openid" version = "3.2.0" description = "OpenID support for modern servers and consumers." +category = "main" optional = false python-versions = "*" files = [ @@ -2328,6 +2421,7 @@ postgresql = ["psycopg2"] name = "pytz" version = "2023.3" description = "World timezone definitions, modern and historical" +category = "main" optional = false python-versions = "*" files = [ @@ -2337,13 +2431,14 @@ files = [ [[package]] name = "pyupgrade" -version = "3.7.0" +version = "3.9.0" description = "A tool to automatically upgrade syntax for newer versions." +category = "dev" optional = false -python-versions = ">=3.8" +python-versions = ">=3.8.1" files = [ - {file = "pyupgrade-3.7.0-py2.py3-none-any.whl", hash = "sha256:696c1e6ebec6697297d3e45ae511ecedb5b17d31e5212a20bc892ba51b1c0b6d"}, - {file = "pyupgrade-3.7.0.tar.gz", hash = "sha256:94841f8550547349aec108ad03fcdb19b64e4ef68fd21f5d0038826eb6dbe5f3"}, + {file = "pyupgrade-3.9.0-py2.py3-none-any.whl", hash = "sha256:1807e324a1432f05a830bc1847095c90b604c91de66237fff55cb98b99d4da10"}, + {file = "pyupgrade-3.9.0.tar.gz", hash = "sha256:a4c7132f4614f7acbacb756275c8a7881ad418f8a1c6ff6512c30dcf4c98f500"}, ] [package.dependencies] @@ -2351,46 +2446,59 @@ tokenize-rt = ">=3.2.0" [[package]] name = "pyyaml" -version = "5.4.1" +version = "6.0" description = "YAML parser and emitter for Python" +category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.6" files = [ - {file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"}, - {file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393"}, - {file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8"}, - {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"}, - {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"}, - {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"}, - {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347"}, - {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541"}, - {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"}, - {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"}, - {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"}, - {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"}, - {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa"}, - {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"}, - {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"}, - {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"}, - {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"}, - {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"}, - {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247"}, - {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc"}, - {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"}, - {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"}, - {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"}, - {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"}, - {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122"}, - {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6"}, - {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"}, - {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"}, - {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"}, + {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-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, + {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, + {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, + {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"}, ] [[package]] name = "pyyaml-env-tag" version = "0.1" description = "A custom YAML tag for referencing environment variables in YAML files. " +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2405,6 +2513,7 @@ pyyaml = "*" name = "qrcode" version = "7.4.2" description = "QR Code image generator" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2428,6 +2537,7 @@ test = ["coverage", "pytest"] name = "rdap" version = "1.3.1" description = "Registration Data Access Protocol tools" +category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -2439,10 +2549,27 @@ files = [ munge = ">=1.0.0,<2.0.0" requests = ">=2.25.1,<3.0.0" +[[package]] +name = "referencing" +version = "0.29.1" +description = "JSON Referencing + Python" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "referencing-0.29.1-py3-none-any.whl", hash = "sha256:d3c8f323ee1480095da44d55917cfb8278d73d6b4d5f677e3e40eb21314ac67f"}, + {file = "referencing-0.29.1.tar.gz", hash = "sha256:90cb53782d550ba28d2166ef3f55731f38397def8832baac5d45235f1995e35e"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" + [[package]] name = "requests" version = "2.31.0" description = "Python HTTP for Humans." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2464,6 +2591,7 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "requests-mock" version = "1.11.0" description = "Mock out responses from the requests package" +category = "dev" optional = false python-versions = "*" files = [ @@ -2483,6 +2611,7 @@ test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "tes name = "requests-oauthlib" version = "1.3.1" description = "OAuthlib authentication support for Requests." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -2497,10 +2626,118 @@ requests = ">=2.0.0" [package.extras] rsa = ["oauthlib[signedtoken] (>=3.0.0)"] +[[package]] +name = "rpds-py" +version = "0.8.10" +description = "Python bindings to Rust's persistent data structures (rpds)" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "rpds_py-0.8.10-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:93d06cccae15b3836247319eee7b6f1fdcd6c10dabb4e6d350d27bd0bdca2711"}, + {file = "rpds_py-0.8.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3816a890a6a9e9f1de250afa12ca71c9a7a62f2b715a29af6aaee3aea112c181"}, + {file = "rpds_py-0.8.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7c6304b894546b5a6bdc0fe15761fa53fe87d28527a7142dae8de3c663853e1"}, + {file = "rpds_py-0.8.10-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ad3bfb44c8840fb4be719dc58e229f435e227fbfbe133dc33f34981ff622a8f8"}, + {file = "rpds_py-0.8.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14f1c356712f66653b777ecd8819804781b23dbbac4eade4366b94944c9e78ad"}, + {file = "rpds_py-0.8.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:82bb361cae4d0a627006dadd69dc2f36b7ad5dc1367af9d02e296ec565248b5b"}, + {file = "rpds_py-0.8.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2e3c4f2a8e3da47f850d7ea0d7d56720f0f091d66add889056098c4b2fd576c"}, + {file = "rpds_py-0.8.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:15a90d0ac11b4499171067ae40a220d1ca3cb685ec0acc356d8f3800e07e4cb8"}, + {file = "rpds_py-0.8.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:70bb9c8004b97b4ef7ae56a2aa56dfaa74734a0987c78e7e85f00004ab9bf2d0"}, + {file = "rpds_py-0.8.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:d64f9f88d5203274a002b54442cafc9c7a1abff2a238f3e767b70aadf919b451"}, + {file = "rpds_py-0.8.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ccbbd276642788c4376fbe8d4e6c50f0fb4972ce09ecb051509062915891cbf0"}, + {file = "rpds_py-0.8.10-cp310-none-win32.whl", hash = "sha256:fafc0049add8043ad07ab5382ee80d80ed7e3699847f26c9a5cf4d3714d96a84"}, + {file = "rpds_py-0.8.10-cp310-none-win_amd64.whl", hash = "sha256:915031002c86a5add7c6fd4beb601b2415e8a1c956590a5f91d825858e92fe6e"}, + {file = "rpds_py-0.8.10-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:84eb541a44f7a18f07a6bfc48b95240739e93defe1fdfb4f2a295f37837945d7"}, + {file = "rpds_py-0.8.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f59996d0550894affaad8743e97b9b9c98f638b221fac12909210ec3d9294786"}, + {file = "rpds_py-0.8.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9adb5664b78fcfcd830000416c8cc69853ef43cb084d645b3f1f0296edd9bae"}, + {file = "rpds_py-0.8.10-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f96f3f98fbff7af29e9edf9a6584f3c1382e7788783d07ba3721790625caa43e"}, + {file = "rpds_py-0.8.10-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:376b8de737401050bd12810003d207e824380be58810c031f10ec563ff6aef3d"}, + {file = "rpds_py-0.8.10-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d1c2bc319428d50b3e0fa6b673ab8cc7fa2755a92898db3a594cbc4eeb6d1f7"}, + {file = "rpds_py-0.8.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73a1e48430f418f0ac3dfd87860e4cc0d33ad6c0f589099a298cb53724db1169"}, + {file = "rpds_py-0.8.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:134ec8f14ca7dbc6d9ae34dac632cdd60939fe3734b5d287a69683c037c51acb"}, + {file = "rpds_py-0.8.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4b519bac7c09444dd85280fd60f28c6dde4389c88dddf4279ba9b630aca3bbbe"}, + {file = "rpds_py-0.8.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9cd57981d9fab04fc74438d82460f057a2419974d69a96b06a440822d693b3c0"}, + {file = "rpds_py-0.8.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:69d089c026f6a8b9d64a06ff67dc3be196707b699d7f6ca930c25f00cf5e30d8"}, + {file = "rpds_py-0.8.10-cp311-none-win32.whl", hash = "sha256:220bdcad2d2936f674650d304e20ac480a3ce88a40fe56cd084b5780f1d104d9"}, + {file = "rpds_py-0.8.10-cp311-none-win_amd64.whl", hash = "sha256:6c6a0225b8501d881b32ebf3f5807a08ad3685b5eb5f0a6bfffd3a6e039b2055"}, + {file = "rpds_py-0.8.10-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:e3d0cd3dff0e7638a7b5390f3a53057c4e347f4ef122ee84ed93fc2fb7ea4aa2"}, + {file = "rpds_py-0.8.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d77dff3a5aa5eedcc3da0ebd10ff8e4969bc9541aa3333a8d41715b429e99f47"}, + {file = "rpds_py-0.8.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41c89a366eae49ad9e65ed443a8f94aee762931a1e3723749d72aeac80f5ef2f"}, + {file = "rpds_py-0.8.10-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3793c21494bad1373da517001d0849eea322e9a049a0e4789e50d8d1329df8e7"}, + {file = "rpds_py-0.8.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:805a5f3f05d186c5d50de2e26f765ba7896d0cc1ac5b14ffc36fae36df5d2f10"}, + {file = "rpds_py-0.8.10-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b01b39ad5411563031ea3977bbbc7324d82b088e802339e6296f082f78f6115c"}, + {file = "rpds_py-0.8.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3f1e860be21f3e83011116a65e7310486300e08d9a3028e73e8d13bb6c77292"}, + {file = "rpds_py-0.8.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a13c8e56c46474cd5958d525ce6a9996727a83d9335684e41f5192c83deb6c58"}, + {file = "rpds_py-0.8.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:93d99f957a300d7a4ced41615c45aeb0343bb8f067c42b770b505de67a132346"}, + {file = "rpds_py-0.8.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:148b0b38d719c0760e31ce9285a9872972bdd7774969a4154f40c980e5beaca7"}, + {file = "rpds_py-0.8.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3cc5e5b5514796f45f03a568981971b12a3570f3de2e76114f7dc18d4b60a3c4"}, + {file = "rpds_py-0.8.10-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:e8e24b210a4deb5a7744971f8f77393005bae7f873568e37dfd9effe808be7f7"}, + {file = "rpds_py-0.8.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b41941583adce4242af003d2a8337b066ba6148ca435f295f31ac6d9e4ea2722"}, + {file = "rpds_py-0.8.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c490204e16bca4f835dba8467869fe7295cdeaa096e4c5a7af97f3454a97991"}, + {file = "rpds_py-0.8.10-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1ee45cd1d84beed6cbebc839fd85c2e70a3a1325c8cfd16b62c96e2ffb565eca"}, + {file = "rpds_py-0.8.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a8ca409f1252e1220bf09c57290b76cae2f14723746215a1e0506472ebd7bdf"}, + {file = "rpds_py-0.8.10-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96b293c0498c70162effb13100624c5863797d99df75f2f647438bd10cbf73e4"}, + {file = "rpds_py-0.8.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4627520a02fccbd324b33c7a83e5d7906ec746e1083a9ac93c41ac7d15548c7"}, + {file = "rpds_py-0.8.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e39d7ab0c18ac99955b36cd19f43926450baba21e3250f053e0704d6ffd76873"}, + {file = "rpds_py-0.8.10-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ba9f1d1ebe4b63801977cec7401f2d41e888128ae40b5441270d43140efcad52"}, + {file = "rpds_py-0.8.10-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:802f42200d8caf7f25bbb2a6464cbd83e69d600151b7e3b49f49a47fa56b0a38"}, + {file = "rpds_py-0.8.10-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:d19db6ba816e7f59fc806c690918da80a7d186f00247048cd833acdab9b4847b"}, + {file = "rpds_py-0.8.10-cp38-none-win32.whl", hash = "sha256:7947e6e2c2ad68b1c12ee797d15e5f8d0db36331200b0346871492784083b0c6"}, + {file = "rpds_py-0.8.10-cp38-none-win_amd64.whl", hash = "sha256:fa326b3505d5784436d9433b7980171ab2375535d93dd63fbcd20af2b5ca1bb6"}, + {file = "rpds_py-0.8.10-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:7b38a9ac96eeb6613e7f312cd0014de64c3f07000e8bf0004ad6ec153bac46f8"}, + {file = "rpds_py-0.8.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c4d42e83ddbf3445e6514f0aff96dca511421ed0392d9977d3990d9f1ba6753c"}, + {file = "rpds_py-0.8.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b21575031478609db6dbd1f0465e739fe0e7f424a8e7e87610a6c7f68b4eb16"}, + {file = "rpds_py-0.8.10-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:574868858a7ff6011192c023a5289158ed20e3f3b94b54f97210a773f2f22921"}, + {file = "rpds_py-0.8.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae40f4a70a1f40939d66ecbaf8e7edc144fded190c4a45898a8cfe19d8fc85ea"}, + {file = "rpds_py-0.8.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:37f7ee4dc86db7af3bac6d2a2cedbecb8e57ce4ed081f6464510e537589f8b1e"}, + {file = "rpds_py-0.8.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:695f642a3a5dbd4ad2ffbbacf784716ecd87f1b7a460843b9ddf965ccaeafff4"}, + {file = "rpds_py-0.8.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f43ab4cb04bde6109eb2555528a64dfd8a265cc6a9920a67dcbde13ef53a46c8"}, + {file = "rpds_py-0.8.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a11ab0d97be374efd04f640c04fe5c2d3dabc6dfb998954ea946ee3aec97056d"}, + {file = "rpds_py-0.8.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:92cf5b3ee60eef41f41e1a2cabca466846fb22f37fc580ffbcb934d1bcab225a"}, + {file = "rpds_py-0.8.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ceaac0c603bf5ac2f505a78b2dcab78d3e6b706be6596c8364b64cc613d208d2"}, + {file = "rpds_py-0.8.10-cp39-none-win32.whl", hash = "sha256:dd4f16e57c12c0ae17606c53d1b57d8d1c8792efe3f065a37cb3341340599d49"}, + {file = "rpds_py-0.8.10-cp39-none-win_amd64.whl", hash = "sha256:c03a435d26c3999c2a8642cecad5d1c4d10c961817536af52035f6f4ee2f5dd0"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:0da53292edafecba5e1d8c1218f99babf2ed0bf1c791d83c0ab5c29b57223068"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:7d20a8ed227683401cc508e7be58cba90cc97f784ea8b039c8cd01111e6043e0"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97cab733d303252f7c2f7052bf021a3469d764fc2b65e6dbef5af3cbf89d4892"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8c398fda6df361a30935ab4c4bccb7f7a3daef2964ca237f607c90e9f3fdf66f"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2eb4b08c45f8f8d8254cdbfacd3fc5d6b415d64487fb30d7380b0d0569837bf1"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7dfb1cbb895810fa2b892b68153c17716c6abaa22c7dc2b2f6dcf3364932a1c"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89c92b74e8bf6f53a6f4995fd52f4bd510c12f103ee62c99e22bc9e05d45583c"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e9c0683cb35a9b5881b41bc01d5568ffc667910d9dbc632a1fba4e7d59e98773"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:0eeb2731708207d0fe2619afe6c4dc8cb9798f7de052da891de5f19c0006c315"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:7495010b658ec5b52835f21d8c8b1a7e52e194c50f095d4223c0b96c3da704b1"}, + {file = "rpds_py-0.8.10-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c72ebc22e70e04126158c46ba56b85372bc4d54d00d296be060b0db1671638a4"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:2cd3045e7f6375dda64ed7db1c5136826facb0159ea982f77d9cf6125025bd34"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:2418cf17d653d24ffb8b75e81f9f60b7ba1b009a23298a433a4720b2a0a17017"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a2edf8173ac0c7a19da21bc68818be1321998528b5e3f748d6ee90c0ba2a1fd"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f29b8c55fd3a2bc48e485e37c4e2df3317f43b5cc6c4b6631c33726f52ffbb3"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a7d20c1cf8d7b3960c5072c265ec47b3f72a0c608a9a6ee0103189b4f28d531"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:521fc8861a86ae54359edf53a15a05fabc10593cea7b3357574132f8427a5e5a"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5c191713e98e7c28800233f039a32a42c1a4f9a001a8a0f2448b07391881036"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:083df0fafe199371206111583c686c985dddaf95ab3ee8e7b24f1fda54515d09"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:ed41f3f49507936a6fe7003985ea2574daccfef999775525d79eb67344e23767"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:2614c2732bf45de5c7f9e9e54e18bc78693fa2f635ae58d2895b7965e470378c"}, + {file = "rpds_py-0.8.10-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c60528671d9d467009a6ec284582179f6b88651e83367d0ab54cb739021cd7de"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ee744fca8d1ea822480a2a4e7c5f2e1950745477143668f0b523769426060f29"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a38b9f526d0d6cbdaa37808c400e3d9f9473ac4ff64d33d9163fd05d243dbd9b"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60e0e86e870350e03b3e25f9b1dd2c6cc72d2b5f24e070249418320a6f9097b7"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f53f55a8852f0e49b0fc76f2412045d6ad9d5772251dea8f55ea45021616e7d5"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c493365d3fad241d52f096e4995475a60a80f4eba4d3ff89b713bc65c2ca9615"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:300eb606e6b94a7a26f11c8cc8ee59e295c6649bd927f91e1dbd37a4c89430b6"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a665f6f1a87614d1c3039baf44109094926dedf785e346d8b0a728e9cabd27a"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:927d784648211447201d4c6f1babddb7971abad922b32257ab74de2f2750fad0"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:c200b30dd573afa83847bed7e3041aa36a8145221bf0cfdfaa62d974d720805c"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:08166467258fd0240a1256fce272f689f2360227ee41c72aeea103e9e4f63d2b"}, + {file = "rpds_py-0.8.10-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:996cc95830de9bc22b183661d95559ec6b3cd900ad7bc9154c4cbf5be0c9b734"}, + {file = "rpds_py-0.8.10.tar.gz", hash = "sha256:13e643ce8ad502a0263397362fb887594b49cf84bf518d6038c16f235f2bcea4"}, +] + [[package]] name = "schema" version = "0.7.5" description = "Simple data validation library" +category = "main" optional = false python-versions = "*" files = [ @@ -2515,6 +2752,7 @@ contextlib2 = ">=0.5.5" name = "selenium" version = "4.10.0" description = "" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2532,6 +2770,7 @@ urllib3 = {version = ">=1.26,<3", extras = ["socks"]} name = "setuptools" version = "68.0.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2548,6 +2787,7 @@ testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs ( name = "simplejson" version = "3.19.1" description = "Simple, fast, extensible JSON encoder/decoder for Python" +category = "main" optional = false python-versions = ">=2.5, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -2642,6 +2882,7 @@ files = [ name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -2653,6 +2894,7 @@ files = [ name = "sniffio" version = "1.3.0" description = "Sniff out which async library your code is running under" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2664,6 +2906,7 @@ files = [ name = "sortedcontainers" version = "2.4.0" description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +category = "dev" optional = false python-versions = "*" files = [ @@ -2675,6 +2918,7 @@ files = [ name = "sqlparse" version = "0.4.4" description = "A non-validating SQL parser." +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -2691,6 +2935,7 @@ test = ["pytest", "pytest-cov"] name = "structlog" version = "23.1.0" description = "Structured Logging for Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2708,6 +2953,7 @@ typing = ["mypy", "rich", "twisted"] name = "tablib" version = "3.5.0" description = "Format agnostic tabular data library (XLS, JSON, YAML, CSV, etc.)" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2737,6 +2983,7 @@ yaml = ["pyyaml"] name = "tld" version = "0.13" description = "Extract the top-level domain (TLD) from the URL given." +category = "main" optional = false python-versions = ">=3.7, <4" files = [ @@ -2748,6 +2995,7 @@ files = [ name = "tokenize-rt" version = "5.1.0" description = "A wrapper around the stdlib `tokenize` which roundtrips." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2759,6 +3007,7 @@ files = [ name = "tomli" version = "2.0.1" description = "A lil' TOML parser" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2768,19 +3017,21 @@ files = [ [[package]] name = "tomlkit" -version = "0.7.2" +version = "0.11.8" description = "Style preserving TOML library" +category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.7" files = [ - {file = "tomlkit-0.7.2-py2.py3-none-any.whl", hash = "sha256:173ad840fa5d2aac140528ca1933c29791b79a374a0861a80347f42ec9328117"}, - {file = "tomlkit-0.7.2.tar.gz", hash = "sha256:d7a454f319a7e9bd2e249f239168729327e4dd2d27b17dc68be264ad1ce36754"}, + {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"}, + {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"}, ] [[package]] name = "tqdm" version = "4.65.0" description = "Fast, Extensible Progress Meter" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2799,18 +3050,18 @@ telegram = ["requests"] [[package]] name = "trio" -version = "0.22.0" +version = "0.22.1" description = "A friendly Python library for async concurrency and I/O" +category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "trio-0.22.0-py3-none-any.whl", hash = "sha256:f1dd0780a89bfc880c7c7994519cb53f62aacb2c25ff487001c0052bd721cdf0"}, - {file = "trio-0.22.0.tar.gz", hash = "sha256:ce68f1c5400a47b137c5a4de72c7c901bd4e7a24fbdebfe9b41de8c6c04eaacf"}, + {file = "trio-0.22.1-py3-none-any.whl", hash = "sha256:1270da4a4a33caf33f85c6a255f2ef5f71629a3ec9aea31a052062b673ae58d3"}, + {file = "trio-0.22.1.tar.gz", hash = "sha256:eb5f641b313eb502a16de176d84cecd9ccf2394a7c8655d2297398376bb15eca"}, ] [package.dependencies] -async-generator = ">=1.9" -attrs = ">=19.2.0" +attrs = ">=20.1.0" cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""} exceptiongroup = {version = ">=1.0.0rc9", markers = "python_version < \"3.11\""} idna = "*" @@ -2822,6 +3073,7 @@ sortedcontainers = "*" name = "trio-websocket" version = "0.10.3" description = "WebSocket library for Trio" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2838,6 +3090,7 @@ wsproto = ">=0.14" name = "twentyc-rpc" version = "1.0.0" description = "client for 20c's RESTful API" +category = "main" optional = false python-versions = ">=3.6.1,<4.0" files = [ @@ -2850,19 +3103,21 @@ requests = ">=2.10.0" [[package]] name = "typing-extensions" -version = "4.6.3" +version = "4.7.1" description = "Backported and Experimental Type Hints for Python 3.7+" +category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "typing_extensions-4.6.3-py3-none-any.whl", hash = "sha256:88a4153d8505aabbb4e13aacb7c486c2b4a33ca3b3f807914a9b4c844c471c26"}, - {file = "typing_extensions-4.6.3.tar.gz", hash = "sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5"}, + {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, + {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, ] [[package]] name = "tzdata" version = "2023.3" description = "Provider of IANA time zone data" +category = "main" optional = false python-versions = ">=2" files = [ @@ -2874,6 +3129,7 @@ files = [ name = "unidecode" version = "1.3.6" description = "ASCII transliterations of Unicode text" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -2885,6 +3141,7 @@ files = [ name = "uritemplate" version = "4.1.1" description = "Implementation of RFC 6570 URI Templates" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2896,6 +3153,7 @@ files = [ name = "urllib3" version = "2.0.3" description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2916,6 +3174,7 @@ zstd = ["zstandard (>=0.18.0)"] name = "uwsgi" version = "2.0.21" description = "The uWSGI server" +category = "main" optional = false python-versions = "*" files = [ @@ -2926,6 +3185,7 @@ files = [ name = "virtualenv" version = "20.23.1" description = "Virtual Python Environment builder" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2946,6 +3206,7 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess name = "watchdog" version = "3.0.0" description = "Filesystem events monitoring" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2983,26 +3244,28 @@ watchmedo = ["PyYAML (>=3.10)"] [[package]] name = "webauthn" -version = "1.8.1" +version = "1.9.0" description = "Pythonic WebAuthn" +category = "main" optional = false python-versions = "*" files = [ - {file = "webauthn-1.8.1-py3-none-any.whl", hash = "sha256:53914b8529df3e70bec0e41438eea8d99442ad3e54e32b86ce1ba83513bcf30e"}, - {file = "webauthn-1.8.1.tar.gz", hash = "sha256:caca3cc62045923c542819169c22122bdb81efa0246c9d5208d073942d806bf3"}, + {file = "webauthn-1.9.0-py3-none-any.whl", hash = "sha256:b12e02968085fa73099f3f8f486a1b1aee265a0840a6a8b6d076b551d4595aac"}, + {file = "webauthn-1.9.0.tar.gz", hash = "sha256:2e628e65aa1f267d03adead0dd0432fa8c91c8ea3f7e87087685fa7d2e62aaaa"}, ] [package.dependencies] asn1crypto = ">=1.4.0" cbor2 = ">=5.4.2.post1" -cryptography = ">=39.0.1" -pydantic = ">=1.9.0" -pyOpenSSL = ">=23.0.0" +cryptography = ">=41.0.1" +pydantic = ">=1.10.11,<2.0a0" +pyOpenSSL = ">=23.2.0" [[package]] name = "webdriver-manager" version = "3.8.6" description = "Library provides the way to automatically manage drivers for different browsers" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3020,6 +3283,7 @@ tqdm = "*" name = "webencodings" version = "0.5.1" description = "Character encoding aliases for legacy web content" +category = "main" optional = false python-versions = "*" files = [ @@ -3031,6 +3295,7 @@ files = [ name = "whoosh" version = "2.7.4" description = "Fast, pure-Python full text indexing, search, and spell checking library." +category = "main" optional = false python-versions = "*" files = [ @@ -3043,6 +3308,7 @@ files = [ name = "wrapt" version = "1.15.0" 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" files = [ @@ -3127,6 +3393,7 @@ files = [ name = "wsproto" version = "1.2.0" description = "WebSockets state-machine based protocol implementation" +category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -3141,6 +3408,7 @@ h11 = ">=0.9.0,<1" name = "xlrd" version = "2.0.1" description = "Library for developers to extract data from Microsoft Excel (tm) .xls spreadsheet files" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ @@ -3157,6 +3425,7 @@ test = ["pytest", "pytest-cov"] name = "xlwt" version = "1.3.0" description = "Library to create spreadsheet files compatible with MS Excel 97/2000/XP/2003 XLS files, on any platform, with Python 2.6, 2.7, 3.3+" +category = "main" optional = false python-versions = "*" files = [ @@ -3166,20 +3435,21 @@ files = [ [[package]] name = "zipp" -version = "3.15.0" +version = "3.16.0" description = "Backport of pathlib-compatible object wrapper for zip files" +category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, - {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, + {file = "zipp-3.16.0-py3-none-any.whl", hash = "sha256:5dadc3ad0a1f825fe42ce1bce0f2fc5a13af2e6b2d386af5b0ff295bc0a287d3"}, + {file = "zipp-3.16.0.tar.gz", hash = "sha256:1876cb065531855bbe83b6c489dcf69ecc28f1068d8e95959fe8bbc77774c941"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "bfca220eb41d1e2b65fa6305040e01268f5f88fd3219f4de1bf1df980a36460d" +content-hash = "79eb50a2376b30dc97f5367b2ca3fdb9f522f68f4639cded244323c2cc8901d3" diff --git a/pyproject.toml b/pyproject.toml index 2ffd3c28..dcf5ded3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,8 @@ django-handleref = ">=2" django-peeringdb = "==3.1.0" djangorestframework = ">=3.14.0" mysqlclient = ">=2.1.1" -peeringdb = ">=1.1.0, <2" +# locked to support_202306 branch until that is tagged and released to pypi +peeringdb = { git = "https://github.com/peeringdb/peeringdb-py.git", branch = "support_202306" } uwsgi = ">=2.0.14" # ancilary packages bleach = ">=2.1.3" @@ -34,17 +35,7 @@ django-extensions = ">=1.3.3" django-grappelli = ">=2.10.1" django-import-export = ">2.8.0,<3" django-hashers-passlib = { git = "https://github.com/mathiasertl/django-hashers-passlib.git" } -# FIXME: django-oauth-toolkit needs to be locked to 1.6.1 because it introduced -# api breaking changes that were then reverted in 1.6.2 - in order to upgrade -# we need to wait for them to re-introduce the changes or adapt our code to -# the reversion -# -# django-oauth-toolkit 2.0.0 is ready but also introduces additional BREAKING changes that may -# need to be communicated to users, such as unreversible hashing of their current client -# secrets. -# -# See https://django-oauth-toolkit.readthedocs.io/en/latest/changelog.html#id10 -django-oauth-toolkit = "==1.6.1" +django-oauth-toolkit = ">=2" django-phonenumber-field = ">=0.6" django-ratelimit = ">=4.0.0" django-rest-swagger = ">=2.1.2" diff --git a/tests/test_cmd_pdb_notify_2fa.py b/tests/test_cmd_pdb_notify_2fa.py new file mode 100644 index 00000000..78f53e77 --- /dev/null +++ b/tests/test_cmd_pdb_notify_2fa.py @@ -0,0 +1,100 @@ +from datetime import datetime, timedelta, timezone + +import pytest +from django.core.management import call_command +from django_otp.plugins.otp_totp.models import TOTPDevice + +from peeringdb_server.models import Organization, User + + +@pytest.fixture +def setup_data(): + users = [ + "org_admin", + "user_a", + "user_b", + "user_c", + "user_d", + "user_e", + "user_f", + ] + # create test users + for name in users: + setattr( + setup_data, + name, + User.objects.create_user(name, "%s@localhost" % name, name), + ) + getattr(setup_data, name).set_password(name) + + # create test org + setup_data.org_required_2fa_a = Organization.objects.create( + name="Test org 2FA A", status="ok", require_2fa=True + ) + setup_data.org_required_2fa_b = Organization.objects.create( + name="Test org 2FA B", status="ok", require_2fa=True + ) + setup_data.org_disabled_2fa = Organization.objects.create( + name="Test org no 2FA", status="ok" + ) + + # add org_admin user to org as admin + setup_data.org_required_2fa_a.admin_usergroup.user_set.add(setup_data.org_admin) + + # distribute group members + for user_index, user in enumerate(users): + if user_index in [1, 2]: + setup_data.org_required_2fa_a.usergroup.user_set.add( + getattr(setup_data, user) + ) + elif user_index in [3, 4]: + setup_data.org_required_2fa_b.usergroup.user_set.add( + getattr(setup_data, user) + ) + TOTPDevice.objects.create(user=getattr(setup_data, user), name="default") + elif user_index in [5, 6]: + setup_data.org_disabled_2fa.usergroup.user_set.add( + getattr(setup_data, user) + ) + + yield setup_data + + +@pytest.mark.django_db +def test_send_email(setup_data): + # Access the variables defined in setUpTestData + org_required_2fa_a = setup_data.org_required_2fa_a + org_required_2fa_b = setup_data.org_required_2fa_b + org_disabled_2fa = setup_data.org_disabled_2fa + MONTHS_AGO = datetime.now(tz=timezone.utc) - timedelta(days=30) + assert ( + org_required_2fa_a.last_notified is None + and org_required_2fa_b.last_notified is None + and org_disabled_2fa.last_notified is None + ) + + # run pdb_notify_2fa command with + call_command("pdb_notify_2fa", "--commit") + org_required_2fa_a.refresh_from_db() + org_required_2fa_b.refresh_from_db() + org_disabled_2fa.refresh_from_db() + + # check if last_notified is updated only for org that require 2FA has member with 2FA disabled + assert org_required_2fa_a.last_notified is not None + assert org_required_2fa_b.last_notified is None + assert org_disabled_2fa.last_notified is None + last_notified = org_required_2fa_a.last_notified + + # check if last_notified is not updated if current last_notified is less than a month + call_command("pdb_notify_2fa", "--commit") + org_required_2fa_a.refresh_from_db() + assert org_required_2fa_a.last_notified == last_notified + + # set the last_notified as a month has been passed + org_required_2fa_a.last_notified = MONTHS_AGO + org_required_2fa_a.save() + + # check if last_notified is updated if current last_notified is more than a month + call_command("pdb_notify_2fa", "--commit") + org_required_2fa_a.refresh_from_db() + assert org_required_2fa_a.last_notified != last_notified diff --git a/tests/test_orgadmin.py b/tests/test_orgadmin.py index 57e4e1bf..256014b6 100644 --- a/tests/test_orgadmin.py +++ b/tests/test_orgadmin.py @@ -5,6 +5,7 @@ from django.conf import settings from django.contrib.auth.models import Group from django.test import Client, RequestFactory, TestCase from django.urls import reverse +from django_otp.plugins.otp_totp.models import TOTPDevice from grainy.const import * import peeringdb_server.models as models @@ -634,7 +635,12 @@ class OrgAdminTests(TestCase): # test that org id was properly derived from network asn self.assertEqual(uoar.org.id, self.org.id) - # test approval + # set org.require_2fa to True + org = self.org + org.require_2fa = True + org.save() + + # test approval for user without 2FA request affiliation in organization that require 2FA with override_group_id(): request = self.factory.post( "/org-admin/uoar/approve?org_id=%d" % self.org.id, data={"id": uoar.id} @@ -642,8 +648,25 @@ class OrgAdminTests(TestCase): mock_csrf_session(request) request.user = self.org_admin - resp = json.loads(org_admin.uoar_approve(request).content) + resp = org_admin.uoar_approve(request) + self.assertEqual(resp.status_code, 403) + self.assertEqual( + json.loads(resp.content), + { + "message": "User requests affiliation with Organization Test org but has " + "not enabled 2FA. Org Test org does not allow users to affiliate " + "unless they have enabled 2FA on their account. You will be able " + "to approve an affiliation request from User , and assign " + "permissions to them, when they have enabled 2FA." + }, + ) + # create user TOTP devices + totpdevice = TOTPDevice.objects.create(user=self.user_c, name="default") + totpdevice.save() + + # test approval + resp = json.loads(org_admin.uoar_approve(request).content) self.assertEqual( { "status": "ok", @@ -698,6 +721,73 @@ class OrgAdminTests(TestCase): uoar_b.delete() + def test_handle_2fa(self): + """ + Test handling a user turning off 2FA while they are in an organization that requires it + views.handle_2fa + """ + org = self.org + org_other = self.org_other + member = self.user_c + org.usergroup.user_set.add(self.user_c) + actions = ["leave", "disable", "drop"] + settings.CSRF_USE_SESSIONS = False + + # check if request.user is not admin of the organization and member is not the member of the organization + request = self.factory.get( + f"/org_admin/handle-2fa?org={org_other.id}&member={member.id}&action={actions[0]}&commit=1" + ) + mock_csrf_session(request) + request.user = self.org_admin + resp = views.handle_2fa(request) + self.assertEqual(resp.status_code, 200) + self.assertIn( + f"Only admin of the {org_other} can perform the action".encode(), + resp.content, + ) + + # confirming dialog before perform the action + for action in actions: + request = self.factory.get( + f"/org_admin/handle-2fa?org={org.id}&member={member.id}&action={action}" + ) + mock_csrf_session(request) + request.user = self.org_admin + resp = views.handle_2fa(request) + self.assertEqual(resp.status_code, 200) + if action == "leave": + self.assertIn( + f"This will allow {member} to keep all privileges within {org}. This conflicts with your 2FA Policy".encode(), + resp.content, + ) + if action == "disable": + self.assertIn( + f"This will turn off the 2FA requirement for {org}, users will not need to use 2FA to login".encode(), + resp.content, + ) + if action == "drop": + self.assertIn( + f"This will completely remove {member} from {org}".encode(), + resp.content, + ) + + # after agree in the confirming dialog + for action in actions: + request = self.factory.get( + f"/org_admin/handle-2fa?org={org.id}&member={member.id}&action={action}&commit=1" + ) + mock_csrf_session(request) + request.user = self.org_admin + resp = views.handle_2fa(request) + self.assertEqual(resp.status_code, 302) + if action == "leave": + self.assertIn(member, org.usergroup.user_set.all()) + if action == "disable": + self.assertFalse(org.require_2fa) + if action == "drop": + self.assertNotIn(member, org.usergroup.user_set.all()) + settings.CSRF_USE_SESSIONS = True + def test_uoar_deny(self): """ Test denying of a user-org-affiliation-request diff --git a/tests/util.py b/tests/util.py index 24628f30..3e017821 100644 --- a/tests/util.py +++ b/tests/util.py @@ -5,7 +5,7 @@ from importlib import import_module from django.conf import settings from django.contrib.auth.models import AnonymousUser, Group from django.contrib.sessions.models import Session -from django.middleware.csrf import CSRF_SESSION_KEY +from django.middleware.csrf import CSRF_SESSION_KEY, _get_new_csrf_string from django.test import TestCase from django_grainy.models import GroupPermission, UserPermission @@ -135,5 +135,5 @@ def setup_test_data(filename): def mock_csrf_session(request): engine = import_module(settings.SESSION_ENGINE) request.session = engine.SessionStore("deadbeef") - request.session[CSRF_SESSION_KEY] = "csrf-session-key" + request.session[CSRF_SESSION_KEY] = _get_new_csrf_string() request._dont_enforce_csrf_checks = True