From ab8f5a2ac4f9e9cdc4c16067229409eb073c3da3 Mon Sep 17 00:00:00 2001
From: "Jens L."
Date: Mon, 17 Feb 2025 18:47:25 +0100
Subject: [PATCH] policies/geoip: distance + impossible travel (#12541)
* add history distance checks
Signed-off-by: Jens Langhammer
* start impossible travel
Signed-off-by: Jens Langhammer
* optimise
Signed-off-by: Jens Langhammer
* ui start
Signed-off-by: Jens Langhammer
* fix and add tests
Signed-off-by: Jens Langhammer
* fix ui, fix missing api
Signed-off-by: Jens Langhammer
* fix
Signed-off-by: Jens Langhammer
---------
Signed-off-by: Jens Langhammer
---
authentik/policies/geoip/api.py | 6 +
...ppolicy_check_history_distance_and_more.py | 43 +++
authentik/policies/geoip/models.py | 73 ++++-
authentik/policies/geoip/tests.py | 75 ++++-
blueprints/schema.json | 32 ++
poetry.lock | 288 +++++++++++++++++-
pyproject.toml | 1 +
schema.yml | 63 ++++
.../admin/policies/geoip/GeoIPPolicyForm.ts | 121 +++++++-
9 files changed, 684 insertions(+), 18 deletions(-)
create mode 100644 authentik/policies/geoip/migrations/0002_geoippolicy_check_history_distance_and_more.py
diff --git a/authentik/policies/geoip/api.py b/authentik/policies/geoip/api.py
index 5ea0b1e4aa..6d171c1378 100644
--- a/authentik/policies/geoip/api.py
+++ b/authentik/policies/geoip/api.py
@@ -42,6 +42,12 @@ class GeoIPPolicySerializer(CountryFieldMixin, PolicySerializer):
"asns",
"countries",
"countries_obj",
+ "check_history_distance",
+ "history_max_distance_km",
+ "distance_tolerance_km",
+ "history_login_count",
+ "check_impossible_travel",
+ "impossible_tolerance_km",
]
diff --git a/authentik/policies/geoip/migrations/0002_geoippolicy_check_history_distance_and_more.py b/authentik/policies/geoip/migrations/0002_geoippolicy_check_history_distance_and_more.py
new file mode 100644
index 0000000000..9e44800c94
--- /dev/null
+++ b/authentik/policies/geoip/migrations/0002_geoippolicy_check_history_distance_and_more.py
@@ -0,0 +1,43 @@
+# Generated by Django 5.0.10 on 2025-01-02 20:40
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("authentik_policies_geoip", "0001_initial"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="geoippolicy",
+ name="check_history_distance",
+ field=models.BooleanField(default=False),
+ ),
+ migrations.AddField(
+ model_name="geoippolicy",
+ name="check_impossible_travel",
+ field=models.BooleanField(default=False),
+ ),
+ migrations.AddField(
+ model_name="geoippolicy",
+ name="distance_tolerance_km",
+ field=models.PositiveIntegerField(default=50),
+ ),
+ migrations.AddField(
+ model_name="geoippolicy",
+ name="history_login_count",
+ field=models.PositiveIntegerField(default=5),
+ ),
+ migrations.AddField(
+ model_name="geoippolicy",
+ name="history_max_distance_km",
+ field=models.PositiveBigIntegerField(default=100),
+ ),
+ migrations.AddField(
+ model_name="geoippolicy",
+ name="impossible_tolerance_km",
+ field=models.PositiveIntegerField(default=100),
+ ),
+ ]
diff --git a/authentik/policies/geoip/models.py b/authentik/policies/geoip/models.py
index bd83ad12f6..f94341afd9 100644
--- a/authentik/policies/geoip/models.py
+++ b/authentik/policies/geoip/models.py
@@ -4,15 +4,21 @@ from itertools import chain
from django.contrib.postgres.fields import ArrayField
from django.db import models
+from django.utils.timezone import now
from django.utils.translation import gettext as _
from django_countries.fields import CountryField
+from geopy import distance
from rest_framework.serializers import BaseSerializer
+from authentik.events.context_processors.geoip import GeoIPDict
+from authentik.events.models import Event, EventAction
from authentik.policies.exceptions import PolicyException
from authentik.policies.geoip.exceptions import GeoIPNotFoundException
from authentik.policies.models import Policy
from authentik.policies.types import PolicyRequest, PolicyResult
+MAX_DISTANCE_HOUR_KM = 1000
+
class GeoIPPolicy(Policy):
"""Ensure the user satisfies requirements of geography or network topology, based on IP
@@ -21,6 +27,15 @@ class GeoIPPolicy(Policy):
asns = ArrayField(models.IntegerField(), blank=True, default=list)
countries = CountryField(multiple=True, blank=True)
+ distance_tolerance_km = models.PositiveIntegerField(default=50)
+
+ check_history_distance = models.BooleanField(default=False)
+ history_max_distance_km = models.PositiveBigIntegerField(default=100)
+ history_login_count = models.PositiveIntegerField(default=5)
+
+ check_impossible_travel = models.BooleanField(default=False)
+ impossible_tolerance_km = models.PositiveIntegerField(default=100)
+
@property
def serializer(self) -> type[BaseSerializer]:
from authentik.policies.geoip.api import GeoIPPolicySerializer
@@ -37,21 +52,27 @@ class GeoIPPolicy(Policy):
- the client IP is advertised by an autonomous system with ASN in the `asns`
- the client IP is geolocated in a country of `countries`
"""
- results: list[PolicyResult] = []
+ static_results: list[PolicyResult] = []
+ dynamic_results: list[PolicyResult] = []
if self.asns:
- results.append(self.passes_asn(request))
+ static_results.append(self.passes_asn(request))
if self.countries:
- results.append(self.passes_country(request))
+ static_results.append(self.passes_country(request))
- if not results:
+ if self.check_history_distance or self.check_impossible_travel:
+ dynamic_results.append(self.passes_distance(request))
+
+ if not static_results and not dynamic_results:
return PolicyResult(True)
- passing = any(r.passing for r in results)
- messages = chain(*[r.messages for r in results])
+ passing = any(r.passing for r in static_results) and all(r.passing for r in dynamic_results)
+ messages = chain(
+ *[r.messages for r in static_results], *[r.messages for r in dynamic_results]
+ )
result = PolicyResult(passing, *messages)
- result.source_results = results
+ result.source_results = list(chain(static_results, dynamic_results))
return result
@@ -73,7 +94,7 @@ class GeoIPPolicy(Policy):
def passes_country(self, request: PolicyRequest) -> PolicyResult:
# This is not a single get chain because `request.context` can contain `{ "geoip": None }`.
- geoip_data = request.context.get("geoip")
+ geoip_data: GeoIPDict | None = request.context.get("geoip")
country = geoip_data.get("country") if geoip_data else None
if not country:
@@ -87,6 +108,42 @@ class GeoIPPolicy(Policy):
return PolicyResult(True)
+ def passes_distance(self, request: PolicyRequest) -> PolicyResult:
+ """Check if current policy execution is out of distance range compared
+ to previous authentication requests"""
+ # Get previous login event and GeoIP data
+ previous_logins = Event.objects.filter(
+ action=EventAction.LOGIN, user__pk=request.user.pk, context__geo__isnull=False
+ ).order_by("-created")[: self.history_login_count]
+ _now = now()
+ geoip_data: GeoIPDict | None = request.context.get("geoip")
+ if not geoip_data:
+ return PolicyResult(False)
+ for previous_login in previous_logins:
+ previous_login_geoip: GeoIPDict = previous_login.context["geo"]
+
+ # Figure out distance
+ dist = distance.geodesic(
+ (previous_login_geoip["lat"], previous_login_geoip["long"]),
+ (geoip_data["lat"], geoip_data["long"]),
+ )
+ if self.check_history_distance and dist.km >= (
+ self.history_max_distance_km - self.distance_tolerance_km
+ ):
+ return PolicyResult(
+ False, _("Distance from previous authentication is larger than threshold.")
+ )
+ # Check if distance between `previous_login` and now is more
+ # than max distance per hour times the amount of hours since the previous login
+ # (round down to the lowest closest time of hours)
+ # clamped to be at least 1 hour
+ rel_time_hours = max(int((_now - previous_login.created).total_seconds() / 3600), 1)
+ if self.check_impossible_travel and dist.km >= (
+ (MAX_DISTANCE_HOUR_KM * rel_time_hours) - self.distance_tolerance_km
+ ):
+ return PolicyResult(False, _("Distance is further than possible."))
+ return PolicyResult(True)
+
class Meta(Policy.PolicyMeta):
verbose_name = _("GeoIP Policy")
verbose_name_plural = _("GeoIP Policies")
diff --git a/authentik/policies/geoip/tests.py b/authentik/policies/geoip/tests.py
index f84727d1df..a1178f35c4 100644
--- a/authentik/policies/geoip/tests.py
+++ b/authentik/policies/geoip/tests.py
@@ -1,8 +1,10 @@
"""geoip policy tests"""
from django.test import TestCase
-from guardian.shortcuts import get_anonymous_user
+from authentik.core.tests.utils import create_test_user
+from authentik.events.models import Event, EventAction
+from authentik.events.utils import get_user
from authentik.policies.engine import PolicyRequest, PolicyResult
from authentik.policies.exceptions import PolicyException
from authentik.policies.geoip.exceptions import GeoIPNotFoundException
@@ -14,8 +16,8 @@ class TestGeoIPPolicy(TestCase):
def setUp(self):
super().setUp()
-
- self.request = PolicyRequest(get_anonymous_user())
+ self.user = create_test_user()
+ self.request = PolicyRequest(self.user)
self.context_disabled_geoip = {}
self.context_unknown_ip = {"asn": None, "geoip": None}
@@ -126,3 +128,70 @@ class TestGeoIPPolicy(TestCase):
result: PolicyResult = policy.passes(self.request)
self.assertTrue(result.passing)
+
+ def test_history(self):
+ """Test history checks"""
+ Event.objects.create(
+ action=EventAction.LOGIN,
+ user=get_user(self.user),
+ context={
+ # Random location in Canada
+ "geo": {"lat": 55.868351, "long": -104.441011},
+ },
+ )
+ # Random location in Poland
+ self.request.context["geoip"] = {"lat": 50.950613, "long": 20.363679}
+
+ policy = GeoIPPolicy.objects.create(check_history_distance=True)
+
+ result: PolicyResult = policy.passes(self.request)
+ self.assertFalse(result.passing)
+
+ def test_history_no_data(self):
+ """Test history checks (with no geoip data in context)"""
+ Event.objects.create(
+ action=EventAction.LOGIN,
+ user=get_user(self.user),
+ context={
+ # Random location in Canada
+ "geo": {"lat": 55.868351, "long": -104.441011},
+ },
+ )
+
+ policy = GeoIPPolicy.objects.create(check_history_distance=True)
+
+ result: PolicyResult = policy.passes(self.request)
+ self.assertFalse(result.passing)
+
+ def test_history_impossible_travel(self):
+ """Test history checks"""
+ Event.objects.create(
+ action=EventAction.LOGIN,
+ user=get_user(self.user),
+ context={
+ # Random location in Canada
+ "geo": {"lat": 55.868351, "long": -104.441011},
+ },
+ )
+ # Random location in Poland
+ self.request.context["geoip"] = {"lat": 50.950613, "long": 20.363679}
+
+ policy = GeoIPPolicy.objects.create(check_impossible_travel=True)
+
+ result: PolicyResult = policy.passes(self.request)
+ self.assertFalse(result.passing)
+
+ def test_history_no_geoip(self):
+ """Test history checks (previous login with no geoip data)"""
+ Event.objects.create(
+ action=EventAction.LOGIN,
+ user=get_user(self.user),
+ context={},
+ )
+ # Random location in Poland
+ self.request.context["geoip"] = {"lat": 50.950613, "long": 20.363679}
+
+ policy = GeoIPPolicy.objects.create(check_history_distance=True)
+
+ result: PolicyResult = policy.passes(self.request)
+ self.assertFalse(result.passing)
diff --git a/blueprints/schema.json b/blueprints/schema.json
index d43da273e2..d3e3438f96 100644
--- a/blueprints/schema.json
+++ b/blueprints/schema.json
@@ -5232,6 +5232,38 @@
},
"maxItems": 249,
"title": "Countries"
+ },
+ "check_history_distance": {
+ "type": "boolean",
+ "title": "Check history distance"
+ },
+ "history_max_distance_km": {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 9223372036854775807,
+ "title": "History max distance km"
+ },
+ "distance_tolerance_km": {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 2147483647,
+ "title": "Distance tolerance km"
+ },
+ "history_login_count": {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 2147483647,
+ "title": "History login count"
+ },
+ "check_impossible_travel": {
+ "type": "boolean",
+ "title": "Check impossible travel"
+ },
+ "impossible_tolerance_km": {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 2147483647,
+ "title": "Impossible tolerance km"
}
},
"required": []
diff --git a/poetry.lock b/poetry.lock
index a772a7c1c2..db9bc2179b 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand.
+# This file is automatically @generated by Poetry 2.0.0 and should not be changed by hand.
[[package]]
name = "aiohappyeyeballs"
@@ -6,6 +6,7 @@ version = "2.3.5"
description = "Happy Eyeballs for asyncio"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "aiohappyeyeballs-2.3.5-py3-none-any.whl", hash = "sha256:4d6dea59215537dbc746e93e779caea8178c866856a721c9c660d7a5a7b8be03"},
{file = "aiohappyeyeballs-2.3.5.tar.gz", hash = "sha256:6fa48b9f1317254f122a07a131a86b71ca6946ca989ce6326fff54a99a920105"},
@@ -17,6 +18,7 @@ version = "3.10.11"
description = "Async http client/server framework (asyncio)"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5077b1a5f40ffa3ba1f40d537d3bec4383988ee51fbba6b74aa8fb1bc466599e"},
{file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8d6a14a4d93b5b3c2891fca94fa9d41b2322a68194422bef0dd5ec1e57d7d298"},
@@ -128,6 +130,7 @@ version = "2.8.3"
description = "Simple retry client for aiohttp"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "aiohttp_retry-2.8.3-py3-none-any.whl", hash = "sha256:3aeeead8f6afe48272db93ced9440cf4eda8b6fd7ee2abb25357b7eb28525b45"},
{file = "aiohttp_retry-2.8.3.tar.gz", hash = "sha256:9a8e637e31682ad36e1ff9f8bcba912fcfc7d7041722bc901a4b948da4d71ea9"},
@@ -142,6 +145,7 @@ version = "1.3.1"
description = "aiosignal: a list of registered asynchronous callbacks"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"},
{file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"},
@@ -156,6 +160,7 @@ version = "5.2.0"
description = "Low-level AMQP client for Python (fork of amqplib)."
optional = false
python-versions = ">=3.6"
+groups = ["main"]
files = [
{file = "amqp-5.2.0-py3-none-any.whl", hash = "sha256:827cb12fb0baa892aad844fd95258143bce4027fdac4fccddbc43330fd281637"},
{file = "amqp-5.2.0.tar.gz", hash = "sha256:a1ecff425ad063ad42a486c902807d1482311481c8ad95a72694b2975e75f7fd"},
@@ -170,6 +175,7 @@ version = "0.7.0"
description = "Reusable constraint types to use with typing.Annotated"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
{file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
@@ -181,6 +187,7 @@ version = "4.4.0"
description = "High level compatibility layer for multiple asynchronous event loop implementations"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"},
{file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"},
@@ -201,6 +208,7 @@ version = "23.1.0"
description = "Argon2 for Python"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "argon2_cffi-23.1.0-py3-none-any.whl", hash = "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea"},
{file = "argon2_cffi-23.1.0.tar.gz", hash = "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08"},
@@ -221,6 +229,7 @@ version = "21.2.0"
description = "Low-level CFFI bindings for Argon2"
optional = false
python-versions = ">=3.6"
+groups = ["main"]
files = [
{file = "argon2-cffi-bindings-21.2.0.tar.gz", hash = "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3"},
{file = "argon2_cffi_bindings-21.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367"},
@@ -258,6 +267,7 @@ version = "3.8.1"
description = "ASGI specs, helper code, and adapters"
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47"},
{file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"},
@@ -272,6 +282,7 @@ 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"
optional = false
python-versions = "*"
+groups = ["main"]
files = [
{file = "asn1crypto-1.5.1-py2.py3-none-any.whl", hash = "sha256:db4e40728b728508912cbb3d44f19ce188f218e9eba635821bb4b68564f8fd67"},
{file = "asn1crypto-1.5.1.tar.gz", hash = "sha256:13ae38502be632115abf8a24cbe5f4da52e3b5231990aff31123c805306ccb9c"},
@@ -283,6 +294,7 @@ version = "23.2.0"
description = "Classes Without Boilerplate"
optional = false
python-versions = ">=3.7"
+groups = ["main", "dev"]
files = [
{file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"},
{file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"},
@@ -302,6 +314,7 @@ version = "23.6.2"
description = "WebSocket client & server library, WAMP real-time framework"
optional = false
python-versions = ">=3.9"
+groups = ["dev"]
files = [
{file = "autobahn-23.6.2.tar.gz", hash = "sha256:ec9421c52a2103364d1ef0468036e6019ee84f71721e86b36fe19ad6966c1181"},
]
@@ -330,6 +343,7 @@ version = "22.10.0"
description = "Self-service finite-state machines for the programmer on the go."
optional = false
python-versions = "*"
+groups = ["dev"]
files = [
{file = "Automat-22.10.0-py2.py3-none-any.whl", hash = "sha256:c3164f8742b9dc440f3682482d32aaff7bb53f71740dd018533f9de286b64180"},
{file = "Automat-22.10.0.tar.gz", hash = "sha256:e56beb84edad19dcc11d30e8d9b895f75deeb5ef5e96b84a467066b3b84bb04e"},
@@ -348,6 +362,7 @@ version = "2.2.212"
description = "A library that contains the AWS CLI for use in Lambda Layers"
optional = false
python-versions = "~=3.8"
+groups = ["dev"]
files = [
{file = "aws_cdk.asset_awscli_v1-2.2.212-py3-none-any.whl", hash = "sha256:12161e2d528698957bc2c0f53d2f5e81de54f8ad0e4b94316634bdc1db50f539"},
{file = "aws_cdk_asset_awscli_v1-2.2.212.tar.gz", hash = "sha256:3a4374562f37c9cd3f59cb45173a18ef0f781c0f1df187773662a1dd14cc18fd"},
@@ -364,6 +379,7 @@ version = "2.1.3"
description = "A Lambda Layer that contains kubectl v1.20"
optional = false
python-versions = "~=3.8"
+groups = ["dev"]
files = [
{file = "aws_cdk.asset_kubectl_v20-2.1.3-py3-none-any.whl", hash = "sha256:d5612e5bd03c215a28ce53193b1144ecf4e93b3b6779563c046a8a74d83a3979"},
{file = "aws_cdk_asset_kubectl_v20-2.1.3.tar.gz", hash = "sha256:237cd8530d9e8be0bbc7159af927dbb6b7f91bf3f4099c8ef4d9a213b34264be"},
@@ -380,6 +396,7 @@ version = "2.1.0"
description = "@aws-cdk/asset-node-proxy-agent-v6"
optional = false
python-versions = "~=3.8"
+groups = ["dev"]
files = [
{file = "aws_cdk.asset_node_proxy_agent_v6-2.1.0-py3-none-any.whl", hash = "sha256:24a388b69a44d03bae6dbf864c4e25ba650d4b61c008b4568b94ffbb9a69e40e"},
{file = "aws_cdk_asset_node_proxy_agent_v6-2.1.0.tar.gz", hash = "sha256:1f292c0631f86708ba4ee328b3a2b229f7e46ea1c79fbde567ee9eb119c2b0e2"},
@@ -396,6 +413,7 @@ version = "39.2.6"
description = "Cloud Assembly Schema"
optional = false
python-versions = "~=3.8"
+groups = ["dev"]
files = [
{file = "aws_cdk.cloud_assembly_schema-39.2.6-py3-none-any.whl", hash = "sha256:23b6db157c6914515d8a5679a1c90f88122920d6f2f1fdcf762b27b78174ee4e"},
{file = "aws_cdk_cloud_assembly_schema-39.2.6.tar.gz", hash = "sha256:5e0d3d4939f141b3632c253089bb84a86782b5707ec1bbe11bbf4e27bcaeb8b2"},
@@ -412,6 +430,7 @@ version = "2.178.2"
description = "Version 2 of the AWS Cloud Development Kit library"
optional = false
python-versions = "~=3.8"
+groups = ["dev"]
files = [
{file = "aws_cdk_lib-2.178.2-py3-none-any.whl", hash = "sha256:624383e57fe2b32f7d0fc098b78b4cd21d19ae3af3f24b01f32ec4795baaee25"},
{file = "aws_cdk_lib-2.178.2.tar.gz", hash = "sha256:c00757885b74023350bb34f388f6447155e802ecf827e595bda917098a4925fe"},
@@ -433,6 +452,7 @@ version = "1.30.2"
description = "Microsoft Azure Core Library for Python"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "azure-core-1.30.2.tar.gz", hash = "sha256:a14dc210efcd608821aa472d9fb8e8d035d29b68993819147bc290a8ac224472"},
{file = "azure_core-1.30.2-py3-none-any.whl", hash = "sha256:cf019c1ca832e96274ae85abd3d9f752397194d9fea3b41487290562ac8abe4a"},
@@ -452,6 +472,7 @@ version = "1.17.1"
description = "Microsoft Azure Identity Library for Python"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "azure-identity-1.17.1.tar.gz", hash = "sha256:32ecc67cc73f4bd0595e4f64b1ca65cd05186f4fe6f98ed2ae9f1aa32646efea"},
{file = "azure_identity-1.17.1-py3-none-any.whl", hash = "sha256:db8d59c183b680e763722bfe8ebc45930e6c57df510620985939f7f3191e0382"},
@@ -470,6 +491,7 @@ version = "1.8.2"
description = "Security oriented static analyser for python code."
optional = false
python-versions = ">=3.9"
+groups = ["dev"]
files = [
{file = "bandit-1.8.2-py3-none-any.whl", hash = "sha256:df6146ad73dd30e8cbda4e29689ddda48364e36ff655dbfc86998401fcf1721f"},
{file = "bandit-1.8.2.tar.gz", hash = "sha256:e00ad5a6bc676c0954669fe13818024d66b70e42cf5adb971480cf3b671e835f"},
@@ -494,6 +516,7 @@ version = "4.2.0"
description = "Modern password hashing for your software and your servers"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "bcrypt-4.2.0-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:096a15d26ed6ce37a14c1ac1e48119660f21b24cba457f160a4b830f3fe6b5cb"},
{file = "bcrypt-4.2.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c02d944ca89d9b1922ceb8a46460dd17df1ba37ab66feac4870f6862a1533c00"},
@@ -534,6 +557,7 @@ version = "4.2.0"
description = "Python multiprocessing fork with improvements and bugfixes"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "billiard-4.2.0-py3-none-any.whl", hash = "sha256:07aa978b308f334ff8282bd4a746e681b3513db5c9a514cbdd810cbbdc19714d"},
{file = "billiard-4.2.0.tar.gz", hash = "sha256:9a3c3184cb275aa17a732f93f65b20c525d3d9f253722d26a82194803ade5a2c"},
@@ -545,6 +569,7 @@ version = "25.1.0"
description = "The uncompromising code formatter."
optional = false
python-versions = ">=3.9"
+groups = ["dev"]
files = [
{file = "black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32"},
{file = "black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da"},
@@ -589,6 +614,7 @@ version = "1.34.150"
description = "The AWS SDK for Python"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "boto3-1.34.150-py3-none-any.whl", hash = "sha256:ad648c89a4935590a69341e5430fc42a021489a22de171ee3fd7bb204f9ef0fa"},
{file = "boto3-1.34.150.tar.gz", hash = "sha256:894b222f7850b870a7ac63d7e378ac36c5c34375da24ddc30e131d9fafe369dc"},
@@ -608,6 +634,7 @@ version = "1.34.150"
description = "Low-level, data-driven core of boto 3."
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "botocore-1.34.150-py3-none-any.whl", hash = "sha256:b988d47f4d502df85befce11a48002421e4e6ea4289997b5e0261bac5fa76ce6"},
{file = "botocore-1.34.150.tar.gz", hash = "sha256:4d23387e0f076d87b637a2a35c0ff2b8daca16eace36b63ce27f65630c6b375a"},
@@ -627,6 +654,7 @@ version = "1.0.1"
description = "Version-bump your software with a single command!"
optional = false
python-versions = ">=3.5"
+groups = ["dev"]
files = [
{file = "bump2version-1.0.1-py2.py3-none-any.whl", hash = "sha256:37f927ea17cde7ae2d7baf832f8e80ce3777624554a653006c9144f8017fe410"},
{file = "bump2version-1.0.1.tar.gz", hash = "sha256:762cb2bfad61f4ec8e2bdf452c7c267416f8c70dd9ecb1653fd0bbb01fa936e6"},
@@ -638,6 +666,7 @@ version = "5.4.0"
description = "Extensible memoizing collections and decorators"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "cachetools-5.4.0-py3-none-any.whl", hash = "sha256:3ae3b49a3d5e28a77a0be2b37dbcb89005058959cb2323858c2657c4a8cab474"},
{file = "cachetools-5.4.0.tar.gz", hash = "sha256:b8adc2e7c07f105ced7bc56dbb6dfbe7c4a00acce20e2227b3f355be89bc6827"},
@@ -649,6 +678,7 @@ version = "24.1.2"
description = "Composable complex class support for attrs and dataclasses."
optional = false
python-versions = ">=3.8"
+groups = ["dev"]
files = [
{file = "cattrs-24.1.2-py3-none-any.whl", hash = "sha256:67c7495b760168d931a10233f979b28dc04daf853b30752246f4f8471c6d68d0"},
{file = "cattrs-24.1.2.tar.gz", hash = "sha256:8028cfe1ff5382df59dd36474a86e02d817b06eaf8af84555441bac915d2ef85"},
@@ -673,6 +703,7 @@ version = "5.6.5"
description = "CBOR (de)serializer with extensive tag support"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "cbor2-5.6.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e16c4a87fc999b4926f5c8f6c696b0d251b4745bc40f6c5aee51d69b30b15ca2"},
{file = "cbor2-5.6.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:87026fc838370d69f23ed8572939bd71cea2b3f6c8f8bb8283f573374b4d7f33"},
@@ -731,6 +762,7 @@ version = "5.4.0"
description = "Distributed Task Queue."
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "celery-5.4.0-py3-none-any.whl", hash = "sha256:369631eb580cf8c51a82721ec538684994f8277637edde2dfc0dacd73ed97f64"},
{file = "celery-5.4.0.tar.gz", hash = "sha256:504a19140e8d3029d5acad88330c541d4c3f64c789d85f94756762d8bca7e706"},
@@ -787,6 +819,7 @@ version = "2024.7.4"
description = "Python package for providing Mozilla's CA Bundle."
optional = false
python-versions = ">=3.6"
+groups = ["main", "dev"]
files = [
{file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"},
{file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"},
@@ -798,6 +831,7 @@ version = "1.16.0"
description = "Foreign Function Interface for Python calling C code."
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"},
{file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"},
@@ -852,6 +886,7 @@ files = [
{file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"},
{file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"},
]
+markers = {dev = "os_name == \"nt\" and implementation_name != \"pypy\" or platform_python_implementation != \"PyPy\""}
[package.dependencies]
pycparser = "*"
@@ -862,6 +897,7 @@ version = "4.2.0"
description = "Brings async, event-driven capabilities to Django."
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "channels-4.2.0-py3-none-any.whl", hash = "sha256:6b75bc8d6888fb7236e7e7bf1948520b72d296ad08216a242fc56b1db0ffde1a"},
{file = "channels-4.2.0.tar.gz", hash = "sha256:d9e707487431ba5dbce9af982970dab3b0efd786580fadb99e45dca5e39fdd59"},
@@ -882,6 +918,7 @@ version = "4.2.1"
description = "Redis-backed ASGI channel layer implementation"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "channels_redis-4.2.1-py3-none-any.whl", hash = "sha256:2ca33105b3a04b5a327a9c47dd762b546f30b76a0cd3f3f593a23d91d346b6f4"},
{file = "channels_redis-4.2.1.tar.gz", hash = "sha256:8375e81493e684792efe6e6eca60ef3d7782ef76c6664057d2e5c31e80d636dd"},
@@ -903,6 +940,7 @@ version = "3.3.2"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
optional = false
python-versions = ">=3.7.0"
+groups = ["main", "dev"]
files = [
{file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"},
@@ -1002,6 +1040,7 @@ version = "8.1.7"
description = "Composable command line interface toolkit"
optional = false
python-versions = ">=3.7"
+groups = ["main", "dev"]
files = [
{file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
{file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
@@ -1016,6 +1055,7 @@ version = "0.3.1"
description = "Enables git-like *did-you-mean* feature in click"
optional = false
python-versions = ">=3.6.2"
+groups = ["main"]
files = [
{file = "click_didyoumean-0.3.1-py3-none-any.whl", hash = "sha256:5c4bb6007cfea5f2fd6583a2fb6701a22a41eb98957e63d0fac41c10e7c3117c"},
{file = "click_didyoumean-0.3.1.tar.gz", hash = "sha256:4f82fdff0dbe64ef8ab2279bd6aa3f6a99c3b28c05aa09cbfc07c9d7fbb5a463"},
@@ -1030,6 +1070,7 @@ version = "1.1.1"
description = "An extension module for click to enable registering CLI commands via setuptools entry-points."
optional = false
python-versions = "*"
+groups = ["main"]
files = [
{file = "click-plugins-1.1.1.tar.gz", hash = "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b"},
{file = "click_plugins-1.1.1-py2.py3-none-any.whl", hash = "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8"},
@@ -1047,6 +1088,7 @@ version = "0.3.0"
description = "REPL plugin for Click"
optional = false
python-versions = ">=3.6"
+groups = ["main"]
files = [
{file = "click-repl-0.3.0.tar.gz", hash = "sha256:17849c23dba3d667247dc4defe1757fff98694e90fe37474f3feebb69ced26a9"},
{file = "click_repl-0.3.0-py3-none-any.whl", hash = "sha256:fb7e06deb8da8de86180a33a9da97ac316751c094c6899382da7feeeeb51b812"},
@@ -1065,6 +1107,7 @@ version = "2.4.1"
description = "Fix common misspellings in text files"
optional = false
python-versions = ">=3.8"
+groups = ["dev"]
files = [
{file = "codespell-2.4.1-py3-none-any.whl", hash = "sha256:3dadafa67df7e4a3dbf51e0d7315061b80d265f9552ebd699b3dd6834b47e425"},
{file = "codespell-2.4.1.tar.gz", hash = "sha256:299fcdcb09d23e81e35a671bbe746d5ad7e8385972e65dbb833a2eaac33c01e5"},
@@ -1082,6 +1125,7 @@ version = "0.4.6"
description = "Cross-platform colored terminal text."
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+groups = ["main", "dev"]
files = [
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
@@ -1093,6 +1137,7 @@ version = "23.10.4"
description = "Symbolic constants in Python"
optional = false
python-versions = ">=3.8"
+groups = ["dev"]
files = [
{file = "constantly-23.10.4-py3-none-any.whl", hash = "sha256:3fd9b4d1c3dc1ec9757f3c52aef7e53ad9323dbe39f51dfd4c43853b68dfa3f9"},
{file = "constantly-23.10.4.tar.gz", hash = "sha256:aa92b70a33e2ac0bb33cd745eb61776594dc48764b06c35e0efd050b7f1c7cbd"},
@@ -1104,6 +1149,7 @@ version = "10.4.2"
description = "A programming model for software-defined state"
optional = false
python-versions = "~=3.8"
+groups = ["dev"]
files = [
{file = "constructs-10.4.2-py3-none-any.whl", hash = "sha256:1f0f59b004edebfde0f826340698b8c34611f57848139b7954904c61645f13c1"},
{file = "constructs-10.4.2.tar.gz", hash = "sha256:ce54724360fffe10bab27d8a081844eb81f5ace7d7c62c84b719c49f164d5307"},
@@ -1120,6 +1166,7 @@ version = "7.6.12"
description = "Code coverage measurement for Python"
optional = false
python-versions = ">=3.9"
+groups = ["dev"]
files = [
{file = "coverage-7.6.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:704c8c8c6ce6569286ae9622e534b4f5b9759b6f2cd643f1c1a61f666d534fe8"},
{file = "coverage-7.6.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ad7525bf0241e5502168ae9c643a2f6c219fa0a283001cee4cf23a9b7da75879"},
@@ -1195,6 +1242,7 @@ version = "44.0.1"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
optional = false
python-versions = "!=3.9.0,!=3.9.1,>=3.7"
+groups = ["main", "dev"]
files = [
{file = "cryptography-44.0.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf688f615c29bfe9dfc44312ca470989279f0e94bb9f631f85e3459af8efc009"},
{file = "cryptography-44.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd7c7e2d71d908dc0f8d2027e1604102140d84b155e658c20e8ad1304317691f"},
@@ -1248,6 +1296,7 @@ version = "1.9.2"
description = "Simple creation of data classes from dictionaries."
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "dacite-1.9.2-py3-none-any.whl", hash = "sha256:053f7c3f5128ca2e9aceb66892b1a3c8936d02c686e707bee96e19deef4bc4a0"},
{file = "dacite-1.9.2.tar.gz", hash = "sha256:6ccc3b299727c7aa17582f0021f6ae14d5de47c7227932c47fec4cdfefd26f09"},
@@ -1262,6 +1311,7 @@ version = "4.1.2"
description = "Django ASGI (HTTP/WebSocket) server"
optional = false
python-versions = ">=3.8"
+groups = ["dev"]
files = [
{file = "daphne-4.1.2-py3-none-any.whl", hash = "sha256:618d1322bb4d875342b99dd2a10da2d9aae7ee3645f765965fdc1e658ea5290a"},
{file = "daphne-4.1.2.tar.gz", hash = "sha256:fcbcace38eb86624ae247c7ffdc8ac12f155d7d19eafac4247381896d6f33761"},
@@ -1281,6 +1331,7 @@ version = "1.8.12"
description = "An implementation of the Debug Adapter Protocol for Python"
optional = false
python-versions = ">=3.8"
+groups = ["dev"]
files = [
{file = "debugpy-1.8.12-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:a2ba7ffe58efeae5b8fad1165357edfe01464f9aef25e814e891ec690e7dd82a"},
{file = "debugpy-1.8.12-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbbd4149c4fc5e7d508ece083e78c17442ee13b0e69bfa6bd63003e486770f45"},
@@ -1316,6 +1367,7 @@ version = "5.1.1"
description = "Decorators for Humans"
optional = false
python-versions = ">=3.5"
+groups = ["main"]
files = [
{file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"},
{file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"},
@@ -1327,6 +1379,7 @@ version = "2.0"
description = "A toolset for deeply merging Python dictionaries."
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "deepmerge-2.0-py3-none-any.whl", hash = "sha256:6de9ce507115cff0bed95ff0ce9ecc31088ef50cbdf09bc90a09349a318b3d00"},
{file = "deepmerge-2.0.tar.gz", hash = "sha256:5c3d86081fbebd04dd5de03626a0607b809a98fb6ccba5770b62466fe940ff20"},
@@ -1341,6 +1394,7 @@ version = "0.7.1"
description = "XML bomb protection for Python stdlib modules"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+groups = ["main"]
files = [
{file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"},
{file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"},
@@ -1352,6 +1406,7 @@ version = "1.2.14"
description = "Python @deprecated decorator to deprecate old python classes, functions or methods."
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+groups = ["main"]
files = [
{file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"},
{file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"},
@@ -1369,6 +1424,7 @@ version = "5.0.12"
description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design."
optional = false
python-versions = ">=3.10"
+groups = ["main", "dev"]
files = [
{file = "Django-5.0.12-py3-none-any.whl", hash = "sha256:3566604af111f586a1c9d49cb14ba6c607a0ccbbf87f57d98872cd8aae7d48ad"},
{file = "Django-5.0.12.tar.gz", hash = "sha256:05097ea026cceb2db4db0655ecf77cc96b0753ac6a367280e458e603f6556f53"},
@@ -1389,6 +1445,7 @@ version = "7.6.1"
description = "Provides a country field for Django models."
optional = false
python-versions = "*"
+groups = ["main"]
files = [
{file = "django-countries-7.6.1.tar.gz", hash = "sha256:c772d4e3e54afcc5f97a018544e96f246c6d9f1db51898ab0c15cd57e19437cf"},
{file = "django_countries-7.6.1-py3-none-any.whl", hash = "sha256:1ed20842fe0f6194f91faca21076649513846a8787c9eb5aeec3cbe1656b8acc"},
@@ -1410,6 +1467,7 @@ version = "1.3.3"
description = "Common Table Expressions (CTE) for Django"
optional = false
python-versions = "*"
+groups = ["main"]
files = [
{file = "django-cte-1.3.3.tar.gz", hash = "sha256:0c1aeef067278a22886151c1d27f6f665a303952d058900e5ca82a24cde40697"},
{file = "django_cte-1.3.3-py2.py3-none-any.whl", hash = "sha256:85bbc3efb30c2f8c9ae3080ca6f0b9570e43d2cb4b6be10846c8ef9f046873fa"},
@@ -1421,6 +1479,7 @@ version = "25.1"
description = "Django-filter is a reusable Django application for allowing users to filter querysets dynamically."
optional = false
python-versions = ">=3.9"
+groups = ["main"]
files = [
{file = "django_filter-25.1-py3-none-any.whl", hash = "sha256:4fa48677cf5857b9b1347fed23e355ea792464e0fe07244d1fdfb8a806215b80"},
{file = "django_filter-25.1.tar.gz", hash = "sha256:1ec9eef48fa8da1c0ac9b411744b16c3f4c31176c867886e4c48da369c407153"},
@@ -1435,6 +1494,7 @@ version = "2.4.0"
description = "Implementation of per object permissions for Django."
optional = false
python-versions = ">=3.5"
+groups = ["main"]
files = [
{file = "django-guardian-2.4.0.tar.gz", hash = "sha256:c58a68ae76922d33e6bdc0e69af1892097838de56e93e78a8361090bcd9f89a0"},
{file = "django_guardian-2.4.0-py3-none-any.whl", hash = "sha256:440ca61358427e575323648b25f8384739e54c38b3d655c81d75e0cd0d61b697"},
@@ -1449,6 +1509,7 @@ version = "5.0.0"
description = "Django model mixins and utilities"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "django_model_utils-5.0.0-py3-none-any.whl", hash = "sha256:fec78e6c323d565a221f7c4edc703f4567d7bb1caeafe1acd16a80c5ff82056b"},
{file = "django_model_utils-5.0.0.tar.gz", hash = "sha256:041cdd6230d2fbf6cd943e1969318bce762272077f4ecd333ab2263924b4e5eb"},
@@ -1463,6 +1524,7 @@ version = "1.4.1"
description = "Monitor, kill, and analyze Postgres queries."
optional = false
python-versions = "<4,>=3.8.0"
+groups = ["main"]
files = [
{file = "django_pgactivity-1.4.1-py3-none-any.whl", hash = "sha256:e7affa4dc08e7650092a582375729081362a3103f1148e34e8406ddf114eeb95"},
{file = "django_pgactivity-1.4.1.tar.gz", hash = "sha256:00da0f0156daa37f5f113c7a6d9378a6f6d111e44f20d3b30b367d5428e18b07"},
@@ -1477,6 +1539,7 @@ version = "1.7.1"
description = "Postgres locking routines and lock table access."
optional = false
python-versions = "<4,>=3.9.0"
+groups = ["main"]
files = [
{file = "django_pglock-1.7.1-py3-none-any.whl", hash = "sha256:15db418fb56bee37fc8707038495b5085af9b8c203ebfa300202572127bdb3f0"},
{file = "django_pglock-1.7.1.tar.gz", hash = "sha256:69050bdb522fd34585d49bb8a4798dbfbab9ec4754dd1927b1b9eef2ec0edadf"},
@@ -1492,6 +1555,7 @@ version = "2.3.1"
description = "Django middlewares to monitor your application with Prometheus.io."
optional = false
python-versions = "*"
+groups = ["main"]
files = [
{file = "django-prometheus-2.3.1.tar.gz", hash = "sha256:f9c8b6c780c9419ea01043c63a437d79db2c33353451347894408184ad9c3e1e"},
{file = "django_prometheus-2.3.1-py2.py3-none-any.whl", hash = "sha256:cf9b26f7ba2e4568f08f8f91480a2882023f5908579681bcf06a4d2465f12168"},
@@ -1506,6 +1570,7 @@ version = "5.4.0"
description = "Full featured redis cache backend for Django."
optional = false
python-versions = ">=3.6"
+groups = ["main"]
files = [
{file = "django-redis-5.4.0.tar.gz", hash = "sha256:6a02abaa34b0fea8bf9b707d2c363ab6adc7409950b2db93602e6cb292818c42"},
{file = "django_redis-5.4.0-py3-none-any.whl", hash = "sha256:ebc88df7da810732e2af9987f7f426c96204bf89319df4c6da6ca9a2942edd5b"},
@@ -1524,6 +1589,7 @@ version = "1.14.5"
description = "Support for many storage backends in Django"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "django_storages-1.14.5-py3-none-any.whl", hash = "sha256:5ce9c69426f24f379821fd688442314e4aa03de87ae43183c4e16915f4c165d4"},
{file = "django_storages-1.14.5.tar.gz", hash = "sha256:ace80dbee311258453e30cd5cfd91096b834180ccf09bc1f4d2cb6d38d68571a"},
@@ -1548,6 +1614,7 @@ version = "3.6.1"
description = "Tenant support for Django using PostgreSQL schemas."
optional = false
python-versions = "*"
+groups = ["main"]
files = []
develop = false
@@ -1566,6 +1633,7 @@ version = "3.14.0"
description = "Web APIs for Django, made easy."
optional = false
python-versions = ">=3.6"
+groups = ["main", "dev"]
files = [
{file = "djangorestframework-3.14.0-py3-none-any.whl", hash = "sha256:eb63f58c9f218e1a7d064d17a70751f528ed4e1d35547fdade9aaf4cd103fd08"},
{file = "djangorestframework-3.14.0.tar.gz", hash = "sha256:579a333e6256b09489cbe0a067e66abe55c6595d8926be6b99423786334350c8"},
@@ -1581,6 +1649,7 @@ version = "0.3.0"
description = "django-guardian support for Django REST Framework"
optional = false
python-versions = "*"
+groups = ["main"]
files = [
{file = "djangorestframework-guardian-0.3.0.tar.gz", hash = "sha256:1883756452d9bfcc2a51fb4e039a6837a8f6697c756447aa83af085749b59330"},
{file = "djangorestframework_guardian-0.3.0-py2.py3-none-any.whl", hash = "sha256:3bd3dd6ea58e1bceca5048faf6f8b1a93bb5dcff30ba5eb91b9a0e190a48a0c7"},
@@ -1597,6 +1666,7 @@ version = "2.6.1"
description = "DNS toolkit"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "dnspython-2.6.1-py3-none-any.whl", hash = "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50"},
{file = "dnspython-2.6.1.tar.gz", hash = "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc"},
@@ -1617,6 +1687,7 @@ version = "7.1.0"
description = "A Python library for the Docker Engine API."
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0"},
{file = "docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c"},
@@ -1639,6 +1710,7 @@ version = "3.0.0"
description = "JSON Schema support for Django REST Framework"
optional = false
python-versions = ">=3.10"
+groups = ["dev"]
files = [
{file = "drf_jsonschema_serializer-3.0.0-py3-none-any.whl", hash = "sha256:d0e5cce095a5638b0bb7867aa060ed59ab9eed2f54ba5058dd9b483c9c887ed5"},
{file = "drf_jsonschema_serializer-3.0.0.tar.gz", hash = "sha256:8a42c6079225f789cd55321897073b576d15db3406d008e92f44febb017a232a"},
@@ -1662,6 +1734,7 @@ version = "1.7.3"
description = "Django RestFramework JSON Renderer Backed by orjson"
optional = false
python-versions = ">=3.6.0"
+groups = ["main"]
files = [
{file = "drf_orjson_renderer-1.7.3-py3-none-any.whl", hash = "sha256:9c3fe521b0e8c641b334c40bb81ecadb14519a27599a495d360385abe193a4b4"},
{file = "drf_orjson_renderer-1.7.3.tar.gz", hash = "sha256:0c49760fc415df8096c1ef05f029802f2e5862d4e15fe96066289b8c526835f1"},
@@ -1678,6 +1751,7 @@ version = "0.28.0"
description = "Sane and flexible OpenAPI 3 schema generation for Django REST framework"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "drf_spectacular-0.28.0-py3-none-any.whl", hash = "sha256:856e7edf1056e49a4245e87a61e8da4baff46c83dbc25be1da2df77f354c7cb4"},
{file = "drf_spectacular-0.28.0.tar.gz", hash = "sha256:2c778a47a40ab2f5078a7c42e82baba07397bb35b074ae4680721b2805943061"},
@@ -1701,6 +1775,7 @@ version = "1.2.5.post1"
description = "Simple wrapper script which proxies signals to a child"
optional = false
python-versions = "*"
+groups = ["main"]
files = [
{file = "dumb-init-1.2.5.post1.tar.gz", hash = "sha256:6510538a975e0de10658b0210ec2ad62dc3617543af5c6fbd29a3af111eae981"},
{file = "dumb_init-1.2.5.post1-py2.py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d6b1fe9b8efcdbbdcb670efe7a55f9117251ee9648d35ffd0c487fd79515ea5"},
@@ -1715,6 +1790,7 @@ version = "5.3.0"
description = "Reference client for Duo Security APIs"
optional = false
python-versions = "*"
+groups = ["main"]
files = [
{file = "duo_client-5.3.0-py3-none-any.whl", hash = "sha256:85614bb684cef96285268aef0c1e858df939f6e8a190fb2c707d700bb0215766"},
{file = "duo_client-5.3.0.tar.gz", hash = "sha256:afa5ef98a42f06965a2702ca41dba9c85c483abd945e0a440f0ec4871b7593bf"},
@@ -1730,6 +1806,7 @@ version = "0.7"
description = "Module for converting between datetime.timedelta and Go's Duration strings."
optional = false
python-versions = "*"
+groups = ["main"]
files = [
{file = "durationpy-0.7.tar.gz", hash = "sha256:8447c43df4f1a0b434e70c15a38d77f5c9bd17284bfc1ff1d430f233d5083732"},
]
@@ -1740,6 +1817,7 @@ version = "2.2.0"
description = "A robust email address syntax and deliverability validation library."
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "email_validator-2.2.0-py3-none-any.whl", hash = "sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631"},
{file = "email_validator-2.2.0.tar.gz", hash = "sha256:cb690f344c617a714f22e66ae771445a1ceb46821152df8e165c5f9a364582b7"},
@@ -1755,6 +1833,7 @@ version = "1.2.0"
description = "FIDO2/WebAuthn library for implementing clients and servers."
optional = false
python-versions = "<4.0,>=3.8"
+groups = ["main"]
files = [
{file = "fido2-1.2.0-py3-none-any.whl", hash = "sha256:f7c8ee62e359aa980a45773f9493965bb29ede1b237a9218169dbfe60c80e130"},
{file = "fido2-1.2.0.tar.gz", hash = "sha256:e39f95920122d64283fda5e5581d95a206e704fa42846bfa4662f86aa0d3333b"},
@@ -1772,6 +1851,7 @@ version = "2.0.1"
description = "Celery Flower"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "flower-2.0.1-py2.py3-none-any.whl", hash = "sha256:9db2c621eeefbc844c8dd88be64aef61e84e2deb29b271e02ab2b5b9f01068e2"},
{file = "flower-2.0.1.tar.gz", hash = "sha256:5ab717b979530770c16afb48b50d2a98d23c3e9fe39851dcf6bc4d01845a02a0"},
@@ -1790,6 +1870,7 @@ version = "1.5.1"
description = "Let your Python tests travel through time"
optional = false
python-versions = ">=3.7"
+groups = ["dev"]
files = [
{file = "freezegun-1.5.1-py3-none-any.whl", hash = "sha256:bf111d7138a8abe55ab48a71755673dbaa4ab87f4cff5634a4442dfec34c15f1"},
{file = "freezegun-1.5.1.tar.gz", hash = "sha256:b29dedfcda6d5e8e083ce71b2b542753ad48cfec44037b3fc79702e2980a89e9"},
@@ -1804,6 +1885,7 @@ version = "1.4.1"
description = "A list-like structure which implements collections.abc.MutableSequence"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"},
{file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"},
@@ -1884,12 +1966,25 @@ files = [
{file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"},
]
+[[package]]
+name = "geographiclib"
+version = "2.0"
+description = "The geodesic routines from GeographicLib"
+optional = false
+python-versions = ">=3.7"
+groups = ["main"]
+files = [
+ {file = "geographiclib-2.0-py3-none-any.whl", hash = "sha256:6b7225248e45ff7edcee32becc4e0a1504c606ac5ee163a5656d482e0cd38734"},
+ {file = "geographiclib-2.0.tar.gz", hash = "sha256:f7f41c85dc3e1c2d3d935ec86660dc3b2c848c83e17f9a9e51ba9d5146a15859"},
+]
+
[[package]]
name = "geoip2"
version = "5.0.1"
description = "MaxMind GeoIP2 API"
optional = false
python-versions = ">=3.9"
+groups = ["main"]
files = [
{file = "geoip2-5.0.1-py3-none-any.whl", hash = "sha256:128b7c9e6b55fb66178428a9400bd4f8b011cf64f147b1ed9e3a4766e61a9b78"},
{file = "geoip2-5.0.1.tar.gz", hash = "sha256:90af8b6d3687f3bef251f2708ad017b30d627d1144c0040eabc4c9017a807d86"},
@@ -1903,12 +1998,37 @@ requests = ">=2.24.0,<3.0.0"
[package.extras]
test = ["pytest-httpserver (>=1.0.10)"]
+[[package]]
+name = "geopy"
+version = "2.4.1"
+description = "Python Geocoding Toolbox"
+optional = false
+python-versions = ">=3.7"
+groups = ["main"]
+files = [
+ {file = "geopy-2.4.1-py3-none-any.whl", hash = "sha256:ae8b4bc5c1131820f4d75fce9d4aaaca0c85189b3aa5d64c3dcaf5e3b7b882a7"},
+ {file = "geopy-2.4.1.tar.gz", hash = "sha256:50283d8e7ad07d89be5cb027338c6365a32044df3ae2556ad3f52f4840b3d0d1"},
+]
+
+[package.dependencies]
+geographiclib = ">=1.52,<3"
+
+[package.extras]
+aiohttp = ["aiohttp"]
+dev = ["coverage", "flake8 (>=5.0,<5.1)", "isort (>=5.10.0,<5.11.0)", "pytest (>=3.10)", "pytest-asyncio (>=0.17)", "readme-renderer", "sphinx (<=4.3.2)", "sphinx-issues", "sphinx-rtd-theme (>=0.5.0)"]
+dev-docs = ["readme-renderer", "sphinx (<=4.3.2)", "sphinx-issues", "sphinx-rtd-theme (>=0.5.0)"]
+dev-lint = ["flake8 (>=5.0,<5.1)", "isort (>=5.10.0,<5.11.0)"]
+dev-test = ["coverage", "pytest (>=3.10)", "pytest-asyncio (>=0.17)", "sphinx (<=4.3.2)"]
+requests = ["requests (>=2.16.2)", "urllib3 (>=1.24.2)"]
+timezone = ["pytz"]
+
[[package]]
name = "google-api-core"
version = "2.19.1"
description = "Google API client core library"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "google-api-core-2.19.1.tar.gz", hash = "sha256:f4695f1e3650b316a795108a76a1c416e6afb036199d1c1f1f110916df479ffd"},
{file = "google_api_core-2.19.1-py3-none-any.whl", hash = "sha256:f12a9b8309b5e21d92483bbd47ce2c445861ec7d269ef6784ecc0ea8c1fa6125"},
@@ -1932,6 +2052,7 @@ version = "2.161.0"
description = "Google API Client Library for Python"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "google_api_python_client-2.161.0-py2.py3-none-any.whl", hash = "sha256:9476a5a4f200bae368140453df40f9cda36be53fa7d0e9a9aac4cdb859a26448"},
{file = "google_api_python_client-2.161.0.tar.gz", hash = "sha256:324c0cce73e9ea0a0d2afd5937e01b7c2d6a4d7e2579cdb6c384f9699d6c9f37"},
@@ -1950,6 +2071,7 @@ version = "2.32.0"
description = "Google Authentication Library"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "google_auth-2.32.0-py2.py3-none-any.whl", hash = "sha256:53326ea2ebec768070a94bee4e1b9194c9646ea0c2bd72422785bd0f9abfad7b"},
{file = "google_auth-2.32.0.tar.gz", hash = "sha256:49315be72c55a6a37d62819e3573f6b416aca00721f7e3e31a008d928bf64022"},
@@ -1973,6 +2095,7 @@ version = "0.2.0"
description = "Google Authentication Library: httplib2 transport"
optional = false
python-versions = "*"
+groups = ["main"]
files = [
{file = "google-auth-httplib2-0.2.0.tar.gz", hash = "sha256:38aa7badf48f974f1eb9861794e9c0cb2a0511a4ec0679b1f886d108f5640e05"},
{file = "google_auth_httplib2-0.2.0-py2.py3-none-any.whl", hash = "sha256:b65a0a2123300dd71281a7bf6e64d65a0759287df52729bdd1ae2e47dc311a3d"},
@@ -1988,6 +2111,7 @@ version = "1.63.2"
description = "Common protobufs used in Google APIs"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "googleapis-common-protos-1.63.2.tar.gz", hash = "sha256:27c5abdffc4911f28101e635de1533fb4cfd2c37fbaa9174587c799fac90aa87"},
{file = "googleapis_common_protos-1.63.2-py2.py3-none-any.whl", hash = "sha256:27a2499c7e8aff199665b22741997e485eccc8645aa9176c7c988e6fae507945"},
@@ -2005,6 +2129,7 @@ version = "1.9.0"
description = "Python GSSAPI Wrapper"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "gssapi-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:261e00ac426d840055ddb2199f4989db7e3ce70fa18b1538f53e392b4823e8f1"},
{file = "gssapi-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:14a1ae12fdf1e4c8889206195ba1843de09fe82587fa113112887cd5894587c6"},
@@ -2042,6 +2167,7 @@ version = "23.0.0"
description = "WSGI HTTP Server for UNIX"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "gunicorn-23.0.0-py3-none-any.whl", hash = "sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d"},
{file = "gunicorn-23.0.0.tar.gz", hash = "sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec"},
@@ -2063,6 +2189,7 @@ version = "0.14.0"
description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
optional = false
python-versions = ">=3.7"
+groups = ["main", "dev"]
files = [
{file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
@@ -2074,6 +2201,7 @@ version = "4.1.0"
description = "HTTP/2 State-Machine based protocol implementation"
optional = false
python-versions = ">=3.6.1"
+groups = ["main"]
files = [
{file = "h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d"},
{file = "h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb"},
@@ -2089,6 +2217,7 @@ version = "4.0.0"
description = "Pure-Python HPACK header compression"
optional = false
python-versions = ">=3.6.1"
+groups = ["main"]
files = [
{file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"},
{file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"},
@@ -2100,6 +2229,7 @@ version = "1.0.5"
description = "A minimal low-level HTTP client."
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"},
{file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"},
@@ -2121,6 +2251,7 @@ version = "0.22.0"
description = "A comprehensive HTTP client library."
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+groups = ["main"]
files = [
{file = "httplib2-0.22.0-py3-none-any.whl", hash = "sha256:14ae0a53c1ba8f3d37e9e27cf37eabb0fb9980f435ba405d546948b009dd64dc"},
{file = "httplib2-0.22.0.tar.gz", hash = "sha256:d7a10bc5ef5ab08322488bde8c726eeee5c8618723fdb399597ec58f3d82df81"},
@@ -2135,6 +2266,7 @@ version = "0.6.4"
description = "A collection of framework independent HTTP protocol utils."
optional = false
python-versions = ">=3.8.0"
+groups = ["main"]
files = [
{file = "httptools-0.6.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3c73ce323711a6ffb0d247dcd5a550b8babf0f757e86a52558fe5b86d6fefcc0"},
{file = "httptools-0.6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:345c288418f0944a6fe67be8e6afa9262b18c7626c3ef3c28adc5eabc06a68da"},
@@ -2190,6 +2322,7 @@ version = "0.27.0"
description = "The next generation HTTP client."
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"},
{file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"},
@@ -2215,6 +2348,7 @@ version = "4.10.0"
description = "Python humanize utilities"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "humanize-4.10.0-py3-none-any.whl", hash = "sha256:39e7ccb96923e732b5c2e27aeaa3b10a8dfeeba3eb965ba7b74a3eb0e30040a6"},
{file = "humanize-4.10.0.tar.gz", hash = "sha256:06b6eb0293e4b85e8d385397c5868926820db32b9b654b932f57fa41c23c9978"},
@@ -2229,6 +2363,7 @@ version = "6.0.1"
description = "HTTP/2 framing layer for Python"
optional = false
python-versions = ">=3.6.1"
+groups = ["main"]
files = [
{file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"},
{file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"},
@@ -2240,6 +2375,7 @@ version = "21.0.0"
description = "A featureful, immutable, and correct URL for Python."
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+groups = ["dev"]
files = [
{file = "hyperlink-21.0.0-py2.py3-none-any.whl", hash = "sha256:e6b14c37ecb73e89c77d78cdb4c2cc8f3fb59a885c5b3f819ff4ed80f25af1b4"},
{file = "hyperlink-21.0.0.tar.gz", hash = "sha256:427af957daa58bc909471c6c40f74c5450fa123dd093fc53efd2e91d2705a56b"},
@@ -2254,6 +2390,7 @@ version = "3.7"
description = "Internationalized Domain Names in Applications (IDNA)"
optional = false
python-versions = ">=3.5"
+groups = ["main", "dev"]
files = [
{file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"},
{file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"},
@@ -2265,6 +2402,7 @@ version = "8.5.0"
description = "Read metadata from Python packages"
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"},
{file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"},
@@ -2288,6 +2426,7 @@ version = "6.4.0"
description = "Read resources from Python packages"
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "importlib_resources-6.4.0-py3-none-any.whl", hash = "sha256:50d10f043df931902d4194ea07ec57960f66a80449ff867bfe782b4c486ba78c"},
{file = "importlib_resources-6.4.0.tar.gz", hash = "sha256:cdb2b453b8046ca4e3798eb1d84f3cce1446a0e8e7b5ef4efb600f19fc398145"},
@@ -2303,6 +2442,7 @@ version = "24.7.2"
description = "A small library that versions your Python projects."
optional = false
python-versions = ">=3.8"
+groups = ["dev"]
files = [
{file = "incremental-24.7.2-py3-none-any.whl", hash = "sha256:8cb2c3431530bec48ad70513931a760f446ad6c25e8333ca5d95e24b0ed7b8fe"},
{file = "incremental-24.7.2.tar.gz", hash = "sha256:fb4f1d47ee60efe87d4f6f0ebb5f70b9760db2b2574c59c8e8912be4ebd464c9"},
@@ -2320,6 +2460,7 @@ version = "0.5.1"
description = "A port of Ruby on Rails inflector to Python"
optional = false
python-versions = ">=3.5"
+groups = ["main"]
files = [
{file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"},
{file = "inflection-0.5.1.tar.gz", hash = "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417"},
@@ -2331,6 +2472,7 @@ version = "2.0.0"
description = "brain-dead simple config-ini parsing"
optional = false
python-versions = ">=3.7"
+groups = ["dev"]
files = [
{file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
@@ -2342,6 +2484,7 @@ version = "3.1.5"
description = "A very fast and expressive template engine."
optional = false
python-versions = ">=3.7"
+groups = ["dev"]
files = [
{file = "jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"},
{file = "jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb"},
@@ -2359,6 +2502,7 @@ version = "1.0.1"
description = "JSON Matching Expressions"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"},
{file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"},
@@ -2370,6 +2514,7 @@ version = "1.106.0"
description = "Python client for jsii runtime"
optional = false
python-versions = "~=3.8"
+groups = ["dev"]
files = [
{file = "jsii-1.106.0-py3-none-any.whl", hash = "sha256:5a44d7c3a5a326fa3d9befdb3770b380057e0a61e3804e7c4907f70d76afaaa2"},
{file = "jsii-1.106.0.tar.gz", hash = "sha256:c79c47899f53a7c3c4b20f80d3cd306628fe9ed1852eee970324c71eba1d974e"},
@@ -2390,6 +2535,7 @@ version = "1.33"
description = "Apply JSON-Patches (RFC 6902)"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*"
+groups = ["main"]
files = [
{file = "jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade"},
{file = "jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c"},
@@ -2404,6 +2550,7 @@ version = "3.0.0"
description = "Identify specific nodes in a JSON document (RFC 6901)"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942"},
{file = "jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef"},
@@ -2415,6 +2562,7 @@ version = "4.23.0"
description = "An implementation of JSON Schema validation for Python"
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566"},
{file = "jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4"},
@@ -2436,6 +2584,7 @@ version = "2023.12.1"
description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry"
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"},
{file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"},
@@ -2450,6 +2599,7 @@ version = "1.5.6"
description = "Implementation of JOSE Web standards"
optional = false
python-versions = ">= 3.8"
+groups = ["main"]
files = [
{file = "jwcrypto-1.5.6-py3-none-any.whl", hash = "sha256:150d2b0ebbdb8f40b77f543fb44ffd2baeff48788be71f67f03566692fd55789"},
{file = "jwcrypto-1.5.6.tar.gz", hash = "sha256:771a87762a0c081ae6166958a954f80848820b2ab066937dc8b8379d65b1b039"},
@@ -2465,6 +2615,7 @@ version = "0.10.4"
description = "A library for testing Python applications in self-contained Kerberos 5 environments"
optional = false
python-versions = ">=3.6"
+groups = ["dev"]
files = [
{file = "k5test-0.10.4-py2.py3-none-any.whl", hash = "sha256:33de7ff10bf99155fe8ee5d5976798ad1db6237214306dadf5a0ae9d6bb0ad03"},
{file = "k5test-0.10.4.tar.gz", hash = "sha256:e152491e6602f6a93b3d533d387bd4590f2476093b6842170ff0b93de64bef30"},
@@ -2479,6 +2630,7 @@ version = "5.3.7"
description = "Messaging library for Python."
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "kombu-5.3.7-py3-none-any.whl", hash = "sha256:5634c511926309c7f9789f1433e9ed402616b56836ef9878f01bd59267b4c7a9"},
{file = "kombu-5.3.7.tar.gz", hash = "sha256:011c4cd9a355c14a1de8d35d257314a1d2456d52b7140388561acac3cf1a97bf"},
@@ -2511,6 +2663,7 @@ version = "32.0.0"
description = "Kubernetes python client"
optional = false
python-versions = ">=3.6"
+groups = ["main"]
files = [
{file = "kubernetes-32.0.0-py2.py3-none-any.whl", hash = "sha256:60fd8c29e8e43d9c553ca4811895a687426717deba9c0a66fb2dcc3f5ef96692"},
{file = "kubernetes-32.0.0.tar.gz", hash = "sha256:319fa840345a482001ac5d6062222daeb66ec4d1bcb3087402aed685adf0aecb"},
@@ -2538,6 +2691,7 @@ version = "2.9.1"
description = "A strictly RFC 4510 conforming LDAP V3 pure Python client library"
optional = false
python-versions = "*"
+groups = ["main"]
files = [
{file = "ldap3-2.9.1-py2.py3-none-any.whl", hash = "sha256:5869596fc4948797020d3f03b7939da938778a0f9e2009f7a072ccf92b8e8d70"},
{file = "ldap3-2.9.1.tar.gz", hash = "sha256:f3e7fc4718e3f09dda568b57100095e0ce58633bcabbed8667ce3f8fbaa4229f"},
@@ -2552,6 +2706,7 @@ version = "5.3.1"
description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API."
optional = false
python-versions = ">=3.6"
+groups = ["main"]
files = [
{file = "lxml-5.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a4058f16cee694577f7e4dd410263cd0ef75644b43802a689c2b3c2a7e69453b"},
{file = "lxml-5.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:364de8f57d6eda0c16dcfb999af902da31396949efa0e583e12675d09709881b"},
@@ -2706,6 +2861,7 @@ version = "3.0.0"
description = "Python port of markdown-it. Markdown parsing, done right!"
optional = false
python-versions = ">=3.8"
+groups = ["dev"]
files = [
{file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"},
{file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"},
@@ -2730,6 +2886,7 @@ version = "2.1.5"
description = "Safely add untrusted strings to HTML/XML markup."
optional = false
python-versions = ">=3.7"
+groups = ["dev"]
files = [
{file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"},
{file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"},
@@ -2799,6 +2956,7 @@ version = "2.6.2"
description = "Reader for the MaxMind DB format"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "maxminddb-2.6.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7cfdf5c29a2739610700b9fea7f8d68ce81dcf30bb8016f1a1853ef889a2624b"},
{file = "maxminddb-2.6.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:05e873eb82281cef6e787bd40bd1d58b2e496a21b3689346f0d0420988b3cbb1"},
@@ -2877,6 +3035,7 @@ version = "0.1.2"
description = "Markdown URL utilities"
optional = false
python-versions = ">=3.7"
+groups = ["dev"]
files = [
{file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"},
{file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"},
@@ -2888,6 +3047,7 @@ version = "1.9.2"
description = "Core abstractions for kiota generated libraries in Python"
optional = false
python-versions = "<4.0,>=3.9"
+groups = ["main"]
files = [
{file = "microsoft_kiota_abstractions-1.9.2-py3-none-any.whl", hash = "sha256:a8853d272a84da59d6a2fe11a76c28e9c55bdab268a345ba48e918cb6822b607"},
{file = "microsoft_kiota_abstractions-1.9.2.tar.gz", hash = "sha256:29cdafe8d0672f23099556e0b120dca6231c752cca9393e1e0092fa9ca594572"},
@@ -2904,6 +3064,7 @@ version = "1.9.2"
description = "Core abstractions for kiota generated libraries in Python"
optional = false
python-versions = "<4.0,>=3.9"
+groups = ["main"]
files = [
{file = "microsoft_kiota_authentication_azure-1.9.2-py3-none-any.whl", hash = "sha256:56840f8b15df8aedfd143fb2deb7cc7fae4ac0bafb1a50546b7313a7b3ab4ca0"},
{file = "microsoft_kiota_authentication_azure-1.9.2.tar.gz", hash = "sha256:171045f522a93d9340fbddc4cabb218f14f1d9d289e82e535b3d9291986c3d5a"},
@@ -2922,6 +3083,7 @@ version = "1.9.2"
description = "Core abstractions for kiota generated libraries in Python"
optional = false
python-versions = "<4.0,>=3.9"
+groups = ["main"]
files = [
{file = "microsoft_kiota_http-1.9.2-py3-none-any.whl", hash = "sha256:3a2d930a70d0184d9f4848473f929ee892462cae1acfaf33b2d193f1828c76c2"},
{file = "microsoft_kiota_http-1.9.2.tar.gz", hash = "sha256:2ba3d04a3d1d5d600736eebc1e33533d54d87799ac4fbb92c9cce4a97809af61"},
@@ -2939,6 +3101,7 @@ version = "1.9.2"
description = "Core abstractions for kiota generated libraries in Python"
optional = false
python-versions = "<4.0,>=3.9"
+groups = ["main"]
files = [
{file = "microsoft_kiota_serialization_form-1.9.2-py3-none-any.whl", hash = "sha256:7b997efb2c8750b1d4fbc00878ba2a3e6e1df3fcefc8815226c90fcc9c54f218"},
{file = "microsoft_kiota_serialization_form-1.9.2.tar.gz", hash = "sha256:badfbe65d8ec3369bd58b01022d13ef590edf14babeef94188efe3f4ec24fe41"},
@@ -2953,6 +3116,7 @@ version = "1.9.2"
description = "Core abstractions for kiota generated libraries in Python"
optional = false
python-versions = "<4.0,>=3.9"
+groups = ["main"]
files = [
{file = "microsoft_kiota_serialization_json-1.9.2-py3-none-any.whl", hash = "sha256:8f4ecf485607fff3df5ce8fa9b9c957bc7f4bff1658b183703e180af753098e3"},
{file = "microsoft_kiota_serialization_json-1.9.2.tar.gz", hash = "sha256:19f7beb69c67b2cb77ca96f77824ee78a693929e20237bb5476ea54f69118bf1"},
@@ -2967,6 +3131,7 @@ version = "1.9.2"
description = "Core abstractions for kiota generated libraries in Python"
optional = false
python-versions = "<4.0,>=3.9"
+groups = ["main"]
files = [
{file = "microsoft_kiota_serialization_multipart-1.9.2-py3-none-any.whl", hash = "sha256:641ad374046f1c7adff90d110bdc68d77418adb1e479a716f4ffea3647f0ead6"},
{file = "microsoft_kiota_serialization_multipart-1.9.2.tar.gz", hash = "sha256:b1851409205668d83f5c7a35a8b6fca974b341985b4a92841e95aaec93b7ca0a"},
@@ -2981,6 +3146,7 @@ version = "1.9.2"
description = "Core abstractions for kiota generated libraries in Python"
optional = false
python-versions = "<4.0,>=3.9"
+groups = ["main"]
files = [
{file = "microsoft_kiota_serialization_text-1.9.2-py3-none-any.whl", hash = "sha256:6e63129ea29eb9b976f4ed56fc6595d204e29fc309958b639299e9f9f4e5edb4"},
{file = "microsoft_kiota_serialization_text-1.9.2.tar.gz", hash = "sha256:4289508ebac0cefdc4fa21c545051769a9409913972355ccda9116b647f978f2"},
@@ -2995,6 +3161,7 @@ version = "1.30.0"
description = "The Microsoft Authentication Library (MSAL) for Python library enables your app to access the Microsoft Cloud by supporting authentication of users with Microsoft Azure Active Directory accounts (AAD) and Microsoft Accounts (MSA) using industry standard OAuth2 and OpenID Connect."
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "msal-1.30.0-py3-none-any.whl", hash = "sha256:423872177410cb61683566dc3932db7a76f661a5d2f6f52f02a047f101e1c1de"},
{file = "msal-1.30.0.tar.gz", hash = "sha256:b4bf00850092e465157d814efa24a18f788284c9a479491024d62903085ea2fb"},
@@ -3014,6 +3181,7 @@ version = "1.2.0"
description = "Microsoft Authentication Library extensions (MSAL EX) provides a persistence API that can save your data on disk, encrypted on Windows, macOS and Linux. Concurrent data access will be coordinated by a file lock mechanism."
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "msal_extensions-1.2.0-py3-none-any.whl", hash = "sha256:cf5ba83a2113fa6dc011a254a72f1c223c88d7dfad74cc30617c4679a417704d"},
{file = "msal_extensions-1.2.0.tar.gz", hash = "sha256:6f41b320bfd2933d631a215c91ca0dd3e67d84bd1a2f50ce917d5874ec646bef"},
@@ -3029,6 +3197,7 @@ version = "1.0.8"
description = "MessagePack serializer"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "msgpack-1.0.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:505fe3d03856ac7d215dbe005414bc28505d26f0c128906037e66d98c4e95868"},
{file = "msgpack-1.0.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b7842518a63a9f17107eb176320960ec095a8ee3b4420b5f688e24bf50c53c"},
@@ -3094,6 +3263,7 @@ version = "1.3.1"
description = "Core component of the Microsoft Graph Python SDK"
optional = false
python-versions = ">=3.9"
+groups = ["main"]
files = [
{file = "msgraph_core-1.3.1-py3-none-any.whl", hash = "sha256:a6e3c19c36d43d00edfb49225647a357f8189351c226c3b7c020c5dfaa24171b"},
{file = "msgraph_core-1.3.1.tar.gz", hash = "sha256:91c721b4c741d0e9a536e3c43e1cbd2254928b4d207e4f994e9cc7cb7a25bd74"},
@@ -3114,6 +3284,7 @@ version = "1.21.0"
description = "The Microsoft Graph Python SDK"
optional = false
python-versions = ">=3.9"
+groups = ["main"]
files = [
{file = "msgraph_sdk-1.21.0-py3-none-any.whl", hash = "sha256:d8564b3d76a0c76960af94b916fc6ab3af2d11d2263ab08fafb136c334f66c0e"},
{file = "msgraph_sdk-1.21.0.tar.gz", hash = "sha256:f45db4c1bffb22e0b54876defd06d582291f7ca2e737f0ab519e43a18cf90df4"},
@@ -3136,6 +3307,7 @@ version = "6.0.5"
description = "multidict implementation"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"},
{file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"},
@@ -3235,6 +3407,7 @@ version = "1.0.0"
description = "Type system extensions for programs checked with the mypy type checker."
optional = false
python-versions = ">=3.5"
+groups = ["dev"]
files = [
{file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
@@ -3246,6 +3419,7 @@ version = "1.3.0"
description = "A network address manipulation library for Python"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "netaddr-1.3.0-py3-none-any.whl", hash = "sha256:c2c6a8ebe5554ce33b7d5b3a306b71bbb373e000bbbf2350dd5213cc56e3dbbe"},
{file = "netaddr-1.3.0.tar.gz", hash = "sha256:5c3c3d9895b551b763779ba7db7a03487dc1f8e3b385af819af341ae9ef6e48a"},
@@ -3260,6 +3434,7 @@ version = "3.2.2"
description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic"
optional = false
python-versions = ">=3.6"
+groups = ["main"]
files = [
{file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"},
{file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"},
@@ -3276,6 +3451,7 @@ version = "0.0.14"
description = "Python module for oci specifications"
optional = false
python-versions = "*"
+groups = ["main"]
files = []
develop = false
@@ -3291,6 +3467,7 @@ version = "1.28.0"
description = "OpenTelemetry Python API"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "opentelemetry_api-1.28.0-py3-none-any.whl", hash = "sha256:8457cd2c59ea1bd0988560f021656cecd254ad7ef6be4ba09dbefeca2409ce52"},
{file = "opentelemetry_api-1.28.0.tar.gz", hash = "sha256:578610bcb8aa5cdcb11169d136cc752958548fb6ccffb0969c1036b0ee9e5353"},
@@ -3306,6 +3483,7 @@ version = "1.28.0"
description = "OpenTelemetry Python SDK"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "opentelemetry_sdk-1.28.0-py3-none-any.whl", hash = "sha256:4b37da81d7fad67f6683c4420288c97f4ed0d988845d5886435f428ec4b8429a"},
{file = "opentelemetry_sdk-1.28.0.tar.gz", hash = "sha256:41d5420b2e3fb7716ff4981b510d551eff1fc60eb5a95cf7335b31166812a893"},
@@ -3322,6 +3500,7 @@ version = "0.49b0"
description = "OpenTelemetry Semantic Conventions"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "opentelemetry_semantic_conventions-0.49b0-py3-none-any.whl", hash = "sha256:0458117f6ead0b12e3221813e3e511d85698c31901cac84682052adb9c17c7cd"},
{file = "opentelemetry_semantic_conventions-0.49b0.tar.gz", hash = "sha256:dbc7b28339e5390b6b28e022835f9bac4e134a80ebf640848306d3c5192557e8"},
@@ -3337,6 +3516,7 @@ version = "3.10.6"
description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "orjson-3.10.6-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:fb0ee33124db6eaa517d00890fc1a55c3bfe1cf78ba4a8899d71a06f2d6ff5c7"},
{file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c1c4b53b24a4c06547ce43e5fee6ec4e0d8fe2d597f4647fc033fd205707365"},
@@ -3399,6 +3579,7 @@ version = "1.3.0.post0"
description = "Capture the outcome of Python function calls."
optional = false
python-versions = ">=3.7"
+groups = ["dev"]
files = [
{file = "outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b"},
{file = "outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8"},
@@ -3413,6 +3594,7 @@ version = "24.2"
description = "Core utilities for Python packages"
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"},
{file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"},
@@ -3424,6 +3606,7 @@ version = "3.5.1"
description = "SSH2 protocol library"
optional = false
python-versions = ">=3.6"
+groups = ["main"]
files = [
{file = "paramiko-3.5.1-py3-none-any.whl", hash = "sha256:43b9a0501fc2b5e70680388d9346cf252cfb7d00b0667c39e80eb43a408b8f61"},
{file = "paramiko-3.5.1.tar.gz", hash = "sha256:b2c665bc45b2b215bd7d7f039901b14b067da00f3a11e6640995fd58f2664822"},
@@ -3445,6 +3628,7 @@ version = "0.12.1"
description = "Utility library for gitignore style pattern matching of file paths."
optional = false
python-versions = ">=3.8"
+groups = ["dev"]
files = [
{file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
{file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
@@ -3456,6 +3640,7 @@ version = "6.0.0"
description = "Python Build Reasonableness"
optional = false
python-versions = ">=2.6"
+groups = ["dev"]
files = [
{file = "pbr-6.0.0-py2.py3-none-any.whl", hash = "sha256:4a7317d5e3b17a3dccb6a8cfe67dab65b20551404c52c8ed41279fa4f0cb4cda"},
{file = "pbr-6.0.0.tar.gz", hash = "sha256:d1377122a5a00e2f940ee482999518efe16d745d423a670c27773dfbc3c9a7d9"},
@@ -3467,6 +3652,7 @@ version = "15.0.1"
description = "API Documentation for Python Projects"
optional = false
python-versions = ">=3.9"
+groups = ["dev"]
files = [
{file = "pdoc-15.0.1-py3-none-any.whl", hash = "sha256:fd437ab8eb55f9b942226af7865a3801e2fb731665199b74fd9a44737dbe20f9"},
{file = "pdoc-15.0.1.tar.gz", hash = "sha256:3b08382c9d312243ee6c2a1813d0ff517a6ab84d596fa2c6c6b5255b17c3d666"},
@@ -3483,6 +3669,7 @@ version = "4.2.2"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
optional = false
python-versions = ">=3.8"
+groups = ["dev"]
files = [
{file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"},
{file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"},
@@ -3499,6 +3686,7 @@ version = "1.5.0"
description = "plugin and hook calling mechanisms for python"
optional = false
python-versions = ">=3.8"
+groups = ["dev"]
files = [
{file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
{file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
@@ -3514,6 +3702,7 @@ version = "2.10.1"
description = "Wraps the portalocker recipe for easy usage"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "portalocker-2.10.1-py3-none-any.whl", hash = "sha256:53a5984ebc86a025552264b459b46a2086e269b21823cb572f8f28ee759e45bf"},
{file = "portalocker-2.10.1.tar.gz", hash = "sha256:ef1bf844e878ab08aee7e40184156e1151f228f103aa5c6bd0724cc330960f8f"},
@@ -3533,6 +3722,7 @@ version = "0.20.0"
description = "Python client for the Prometheus monitoring system."
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "prometheus_client-0.20.0-py3-none-any.whl", hash = "sha256:cde524a85bce83ca359cc837f28b8c0db5cac7aa653a588fd7e84ba061c329e7"},
{file = "prometheus_client-0.20.0.tar.gz", hash = "sha256:287629d00b147a32dcb2be0b9df905da599b2d82f80377083ec8463309a4bb89"},
@@ -3547,6 +3737,7 @@ version = "3.0.47"
description = "Library for building powerful interactive command lines in Python"
optional = false
python-versions = ">=3.7.0"
+groups = ["main"]
files = [
{file = "prompt_toolkit-3.0.47-py3-none-any.whl", hash = "sha256:0d7bfa67001d5e39d02c224b663abc33687405033a8c422d0d675a5a13361d10"},
{file = "prompt_toolkit-3.0.47.tar.gz", hash = "sha256:1e1b29cb58080b1e69f207c893a1a7bf16d127a5c30c9d17a25a5d77792e5360"},
@@ -3561,6 +3752,7 @@ version = "0.2.0"
description = "Accelerated property cache"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "propcache-0.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c5869b8fd70b81835a6f187c5fdbe67917a04d7e52b6e7cc4e5fe39d55c39d58"},
{file = "propcache-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:952e0d9d07609d9c5be361f33b0d6d650cd2bae393aabb11d9b719364521984b"},
@@ -3668,6 +3860,7 @@ version = "1.24.0"
description = "Beautiful, Pythonic protocol buffers."
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "proto-plus-1.24.0.tar.gz", hash = "sha256:30b72a5ecafe4406b0d339db35b56c4059064e69227b8c3bda7462397f966445"},
{file = "proto_plus-1.24.0-py3-none-any.whl", hash = "sha256:402576830425e5f6ce4c2a6702400ac79897dab0b4343821aa5188b0fab81a12"},
@@ -3685,6 +3878,7 @@ version = "5.27.2"
description = ""
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "protobuf-5.27.2-cp310-abi3-win32.whl", hash = "sha256:354d84fac2b0d76062e9b3221f4abbbacdfd2a4d8af36bab0474f3a0bb30ab38"},
{file = "protobuf-5.27.2-cp310-abi3-win_amd64.whl", hash = "sha256:0e341109c609749d501986b835f667c6e1e24531096cff9d34ae411595e26505"},
@@ -3705,6 +3899,7 @@ version = "3.2.4"
description = "PostgreSQL database adapter for Python"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "psycopg-3.2.4-py3-none-any.whl", hash = "sha256:43665368ccd48180744cab26b74332f46b63b7e06e8ce0775547a3533883d381"},
{file = "psycopg-3.2.4.tar.gz", hash = "sha256:f26f1346d6bf1ef5f5ef1714dd405c67fb365cfd1c6cea07de1792747b167b92"},
@@ -3729,6 +3924,8 @@ version = "3.2.4"
description = "PostgreSQL database adapter for Python -- C optimisation distribution"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
+markers = "implementation_name != \"pypy\""
files = [
{file = "psycopg_c-3.2.4.tar.gz", hash = "sha256:22097a04263efb2efd2cc8b00a51fa90e23f9cd4a2e09903fe4d9c6923dac17a"},
]
@@ -3739,6 +3936,7 @@ version = "0.0.3"
description = "Publication helps you maintain public-api-friendly modules by preventing unintentional access to private implementation details via introspection."
optional = false
python-versions = "*"
+groups = ["dev"]
files = [
{file = "publication-0.0.3-py2.py3-none-any.whl", hash = "sha256:0248885351febc11d8a1098d5c8e3ab2dabcf3e8c0c96db1e17ecd12b53afbe6"},
{file = "publication-0.0.3.tar.gz", hash = "sha256:68416a0de76dddcdd2930d1c8ef853a743cc96c82416c4e4d3b5d901c6276dc4"},
@@ -3750,6 +3948,7 @@ version = "0.6.0"
description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)"
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "pyasn1-0.6.0-py2.py3-none-any.whl", hash = "sha256:cca4bb0f2df5504f02f6f8a775b6e416ff9b0b3b16f7ee80b5a3153d9b804473"},
{file = "pyasn1-0.6.0.tar.gz", hash = "sha256:3a35ab2c4b5ef98e17dfdec8ab074046fbda76e281c5a706ccd82328cfc8f64c"},
@@ -3761,6 +3960,7 @@ version = "0.4.0"
description = "A collection of ASN.1-based protocols modules"
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "pyasn1_modules-0.4.0-py3-none-any.whl", hash = "sha256:be04f15b66c206eed667e0bb5ab27e2b1855ea54a842e5037738099e8ca4ae0b"},
{file = "pyasn1_modules-0.4.0.tar.gz", hash = "sha256:831dbcea1b177b28c9baddf4c6d1013c24c3accd14a1873fffaa6a2e905f17b6"},
@@ -3775,10 +3975,12 @@ version = "2.22"
description = "C parser in Python"
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"},
{file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"},
]
+markers = {dev = "os_name == \"nt\" and implementation_name != \"pypy\" or platform_python_implementation != \"PyPy\""}
[[package]]
name = "pydantic"
@@ -3786,6 +3988,7 @@ version = "2.10.6"
description = "Data validation using Python type hints"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"},
{file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"},
@@ -3807,6 +4010,7 @@ version = "2.27.2"
description = "Core functionality for Pydantic validation and serialization"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"},
{file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"},
@@ -3919,6 +4123,7 @@ version = "0.0.8"
description = "Pydantic types for SCIM"
optional = false
python-versions = ">=3.8.0"
+groups = ["main"]
files = [
{file = "pydantic-scim-0.0.8.tar.gz", hash = "sha256:b6c62031126e8c54f0fc7df837678e63934a5b068533fc52e5dfb6cfc24d59e9"},
{file = "pydantic_scim-0.0.8-py3-none-any.whl", hash = "sha256:407b3bf55240947155c77a6dd839881d63368c61d64076d6b167ef124ceac79a"},
@@ -3936,6 +4141,7 @@ version = "2.18.0"
description = "Pygments is a syntax highlighting package written in Python."
optional = false
python-versions = ">=3.8"
+groups = ["dev"]
files = [
{file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"},
{file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"},
@@ -3950,6 +4156,7 @@ version = "2.10.1"
description = "JSON Web Token implementation in Python"
optional = false
python-versions = ">=3.9"
+groups = ["main"]
files = [
{file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"},
{file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"},
@@ -3970,6 +4177,7 @@ version = "1.5.0"
description = "Python binding to the Networking and Cryptography (NaCl) library"
optional = false
python-versions = ">=3.6"
+groups = ["main"]
files = [
{file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"},
{file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"},
@@ -3996,6 +4204,7 @@ version = "24.3.0"
description = "Python wrapper module around the OpenSSL library"
optional = false
python-versions = ">=3.7"
+groups = ["main", "dev"]
files = [
{file = "pyOpenSSL-24.3.0-py3-none-any.whl", hash = "sha256:e474f5a473cd7f92221cc04976e48f4d11502804657a08a989fb3be5514c904a"},
{file = "pyopenssl-24.3.0.tar.gz", hash = "sha256:49f7a019577d834746bc55c5fce6ecbcec0f2b4ec5ce1cf43a9a173b8138bb36"},
@@ -4014,6 +4223,7 @@ version = "3.1.2"
description = "pyparsing module - Classes and methods to define and execute parsing grammars"
optional = false
python-versions = ">=3.6.8"
+groups = ["main"]
files = [
{file = "pyparsing-3.1.2-py3-none-any.whl", hash = "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742"},
{file = "pyparsing-3.1.2.tar.gz", hash = "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad"},
@@ -4028,6 +4238,7 @@ version = "2.4"
description = "RADIUS tools"
optional = false
python-versions = "*"
+groups = ["main"]
files = [
{file = "pyrad-2.4-py3-none-any.whl", hash = "sha256:233de3aefa383875c5bddfdecfd4819d1b1fbac41aa43f6bebe4f81e63dca363"},
{file = "pyrad-2.4.tar.gz", hash = "sha256:057de4b7e89d8da57ba782c1bde45c63ebee720ae2c0b0a69beaff15c47e30d9"},
@@ -4043,6 +4254,7 @@ version = "1.7.1"
description = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information."
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+groups = ["dev"]
files = [
{file = "PySocks-1.7.1-py27-none-any.whl", hash = "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299"},
{file = "PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5"},
@@ -4055,6 +4267,7 @@ version = "8.3.4"
description = "pytest: simple powerful testing with Python"
optional = false
python-versions = ">=3.8"
+groups = ["dev"]
files = [
{file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"},
{file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"},
@@ -4075,6 +4288,7 @@ version = "4.10.0"
description = "A Django plugin for pytest."
optional = false
python-versions = ">=3.8"
+groups = ["dev"]
files = [
{file = "pytest_django-4.10.0-py3-none-any.whl", hash = "sha256:57c74ef3aa9d89cae5a5d73fbb69a720a62673ade7ff13b9491872409a3f5918"},
{file = "pytest_django-4.10.0.tar.gz", hash = "sha256:1091b20ea1491fd04a310fc9aaff4c01b4e8450e3b157687625e16a6b5f3a366"},
@@ -4093,6 +4307,7 @@ version = "0.3.0"
description = "pytest plugin to annotate failed tests with a workflow command for GitHub Actions"
optional = false
python-versions = ">=3.8"
+groups = ["dev"]
files = [
{file = "pytest_github_actions_annotate_failures-0.3.0-py3-none-any.whl", hash = "sha256:41ea558ba10c332c0bfc053daeee0c85187507b2034e990f21e4f7e5fef044cf"},
{file = "pytest_github_actions_annotate_failures-0.3.0.tar.gz", hash = "sha256:d4c3177c98046c3900a7f8ddebb22ea54b9f6822201b5d3ab8fcdea51e010db7"},
@@ -4107,6 +4322,7 @@ version = "3.16.0"
description = "Pytest plugin to randomly order tests and control random.seed."
optional = false
python-versions = ">=3.9"
+groups = ["dev"]
files = [
{file = "pytest_randomly-3.16.0-py3-none-any.whl", hash = "sha256:8633d332635a1a0983d3bba19342196807f6afb17c3eef78e02c2f85dade45d6"},
{file = "pytest_randomly-3.16.0.tar.gz", hash = "sha256:11bf4d23a26484de7860d82f726c0629837cf4064b79157bd18ec9d41d7feb26"},
@@ -4121,6 +4337,7 @@ version = "2.3.1"
description = "pytest plugin to abort hanging tests"
optional = false
python-versions = ">=3.7"
+groups = ["dev"]
files = [
{file = "pytest-timeout-2.3.1.tar.gz", hash = "sha256:12397729125c6ecbdaca01035b9e5239d4db97352320af155b3f5de1ba5165d9"},
{file = "pytest_timeout-2.3.1-py3-none-any.whl", hash = "sha256:68188cb703edfc6a18fad98dc25a3c61e9f24d644b0b70f33af545219fc7813e"},
@@ -4135,6 +4352,7 @@ version = "2.9.0.post0"
description = "Extensions to the standard Python datetime module"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
+groups = ["main", "dev"]
files = [
{file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"},
{file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"},
@@ -4149,6 +4367,7 @@ version = "1.0.1"
description = "Read key-value pairs from a .env file and set them as environment variables"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"},
{file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"},
@@ -4163,6 +4382,7 @@ version = "0.5.3"
description = "Python interface to the Kerberos administration interface (kadm5)"
optional = false
python-versions = "<3.14,>=3.9"
+groups = ["main"]
files = [
{file = "python_kadmin_rs-0.5.3-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:21f61723687f6fc3f57a8d47f89db0c0eb2394049c6910b3e4b42a77ff4a4d93"},
{file = "python_kadmin_rs-0.5.3-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:24e88e19a1774355e573a71a4bae9387459bdf11c0de86078ae69411e6046067"},
@@ -4209,6 +4429,7 @@ version = "2024.1"
description = "World timezone definitions, modern and historical"
optional = false
python-versions = "*"
+groups = ["main", "dev"]
files = [
{file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"},
{file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"},
@@ -4220,6 +4441,8 @@ version = "306"
description = "Python for Window Extensions"
optional = false
python-versions = "*"
+groups = ["main"]
+markers = "sys_platform == \"win32\" or platform_system == \"Windows\""
files = [
{file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"},
{file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"},
@@ -4243,6 +4466,7 @@ version = "6.0.2"
description = "YAML parser and emitter for Python"
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"},
{file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"},
@@ -4305,6 +4529,7 @@ version = "5.0.7"
description = "Python client for Redis database and key-value store"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "redis-5.0.7-py3-none-any.whl", hash = "sha256:0e479e24da960c690be5d9b96d21f7b918a98c0cf49af3b6fafaa0753f93a0db"},
{file = "redis-5.0.7.tar.gz", hash = "sha256:8f611490b93c8109b50adc317b31bfd84fff31def3475b92e7e80bf39f48175b"},
@@ -4320,6 +4545,7 @@ version = "0.35.1"
description = "JSON Referencing + Python"
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de"},
{file = "referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c"},
@@ -4335,6 +4561,7 @@ version = "2.32.3"
description = "Python HTTP for Humans."
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
{file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
@@ -4356,6 +4583,7 @@ version = "1.12.1"
description = "Mock out responses from the requests package"
optional = false
python-versions = ">=3.5"
+groups = ["dev"]
files = [
{file = "requests-mock-1.12.1.tar.gz", hash = "sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401"},
{file = "requests_mock-1.12.1-py2.py3-none-any.whl", hash = "sha256:b1e37054004cdd5e56c84454cc7df12b25f90f382159087f4b6915aaeef39563"},
@@ -4373,6 +4601,7 @@ version = "2.0.0"
description = "OAuthlib authentication support for Requests."
optional = false
python-versions = ">=3.4"
+groups = ["main"]
files = [
{file = "requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9"},
{file = "requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36"},
@@ -4391,6 +4620,7 @@ version = "13.7.1"
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
optional = false
python-versions = ">=3.7.0"
+groups = ["dev"]
files = [
{file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"},
{file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"},
@@ -4409,6 +4639,7 @@ version = "0.19.1"
description = "Python bindings to Rust's persistent data structures (rpds)"
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "rpds_py-0.19.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:aaf71f95b21f9dc708123335df22e5a2fef6307e3e6f9ed773b2e0938cc4d491"},
{file = "rpds_py-0.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ca0dda0c5715efe2ab35bb83f813f681ebcd2840d8b1b92bfc6fe3ab382fae4a"},
@@ -4521,6 +4752,7 @@ version = "4.9"
description = "Pure-Python RSA implementation"
optional = false
python-versions = ">=3.6,<4"
+groups = ["main"]
files = [
{file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"},
{file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"},
@@ -4535,6 +4767,7 @@ version = "0.9.6"
description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false
python-versions = ">=3.7"
+groups = ["dev"]
files = [
{file = "ruff-0.9.6-py3-none-linux_armv6l.whl", hash = "sha256:2f218f356dd2d995839f1941322ff021c72a492c470f0b26a34f844c29cdf5ba"},
{file = "ruff-0.9.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b908ff4df65dad7b251c9968a2e4560836d8f5487c2f0cc238321ed951ea0504"},
@@ -4562,6 +4795,7 @@ version = "0.10.2"
description = "An Amazon S3 Transfer Manager"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "s3transfer-0.10.2-py3-none-any.whl", hash = "sha256:eca1c20de70a39daee580aef4986996620f365c4e0fda6a86100231d62f1bf69"},
{file = "s3transfer-0.10.2.tar.gz", hash = "sha256:0711534e9356d3cc692fdde846b4a1e4b0cb6519971860796e6bc4c7aea00ef6"},
@@ -4579,6 +4813,7 @@ version = "0.7.0"
description = "A customizable parser/transpiler for SCIM2.0 filters."
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "scim2_filter_parser-0.7.0-py3-none-any.whl", hash = "sha256:a74f90a2d52a77e0f1bc4d77e84b79f88749469f6f7192d64a4f92e4fe50ab69"},
{file = "scim2_filter_parser-0.7.0.tar.gz", hash = "sha256:1e11dbe2e186fc1be6d93732b467a3bbaa9deff272dfeb3a0540394cfab7030c"},
@@ -4596,6 +4831,7 @@ version = "4.28.1"
description = "Official Python bindings for Selenium WebDriver"
optional = false
python-versions = ">=3.9"
+groups = ["dev"]
files = [
{file = "selenium-4.28.1-py3-none-any.whl", hash = "sha256:4238847e45e24e4472cfcf3554427512c7aab9443396435b1623ef406fff1cc1"},
{file = "selenium-4.28.1.tar.gz", hash = "sha256:0072d08670d7ec32db901bd0107695a330cecac9f196e3afb3fa8163026e022a"},
@@ -4615,6 +4851,7 @@ version = "2.21.0"
description = "Python client for Sentry (https://sentry.io)"
optional = false
python-versions = ">=3.6"
+groups = ["main"]
files = [
{file = "sentry_sdk-2.21.0-py2.py3-none-any.whl", hash = "sha256:7623cfa9e2c8150948a81ca253b8e2bfe4ce0b96ab12f8cd78e3ac9c490fd92f"},
{file = "sentry_sdk-2.21.0.tar.gz", hash = "sha256:a6d38e0fb35edda191acf80b188ec713c863aaa5ad8d5798decb8671d02077b6"},
@@ -4670,6 +4907,7 @@ version = "24.2.0"
description = "Service identity verification for pyOpenSSL & cryptography."
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "service_identity-24.2.0-py3-none-any.whl", hash = "sha256:6b047fbd8a84fd0bb0d55ebce4031e400562b9196e1e0d3e0fe2b8a59f6d4a85"},
{file = "service_identity-24.2.0.tar.gz", hash = "sha256:b8683ba13f0d39c6cd5d625d2c5f65421d6d707b013b375c355751557cbe8e09"},
@@ -4694,6 +4932,7 @@ version = "1.3.4"
description = "A Python module to customize the process title"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "setproctitle-1.3.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0f6661a69c68349172ba7b4d5dd65fec2b0917abc99002425ad78c3e58cf7595"},
{file = "setproctitle-1.3.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:754bac5e470adac7f7ec2239c485cd0b75f8197ca8a5b86ffb20eb3a3676cc42"},
@@ -4791,6 +5030,7 @@ version = "72.1.0"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "setuptools-72.1.0-py3-none-any.whl", hash = "sha256:5a03e1860cf56bb6ef48ce186b0e557fdba433237481a9a625176c2831be15d1"},
{file = "setuptools-72.1.0.tar.gz", hash = "sha256:8d243eff56d095e5817f796ede6ae32941278f542e0f941867cc05ae52b162ec"},
@@ -4807,6 +5047,7 @@ version = "1.16.0"
description = "Python 2 and 3 compatibility utilities"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+groups = ["main", "dev"]
files = [
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
@@ -4818,6 +5059,7 @@ version = "0.5"
description = "\"SLY - Sly Lex Yacc\""
optional = false
python-versions = "*"
+groups = ["main"]
files = [
{file = "sly-0.5-py3-none-any.whl", hash = "sha256:20485483259eec7f6ba85ff4d2e96a4e50c6621902667fc2695cc8bc2a3e5133"},
{file = "sly-0.5.tar.gz", hash = "sha256:251d42015e8507158aec2164f06035df4a82b0314ce6450f457d7125e7649024"},
@@ -4829,6 +5071,7 @@ version = "1.3.1"
description = "Sniff out which async library your code is running under"
optional = false
python-versions = ">=3.7"
+groups = ["main", "dev"]
files = [
{file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
{file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
@@ -4840,6 +5083,7 @@ version = "2.4.0"
description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set"
optional = false
python-versions = "*"
+groups = ["dev"]
files = [
{file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"},
{file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"},
@@ -4851,6 +5095,7 @@ version = "0.5.1"
description = "A non-validating SQL parser."
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "sqlparse-0.5.1-py3-none-any.whl", hash = "sha256:773dcbf9a5ab44a090f3441e2180efe2560220203dc2f8c0b0fa141e18b505e4"},
{file = "sqlparse-0.5.1.tar.gz", hash = "sha256:bb6b4df465655ef332548e24f08e205afc81b9ab86cb1c45657a7ff173a3a00e"},
@@ -4866,6 +5111,7 @@ version = "2.0.2"
description = "std-uritemplate implementation for Python"
optional = false
python-versions = "<4.0,>=3.8"
+groups = ["main"]
files = [
{file = "std_uritemplate-2.0.2-py3-none-any.whl", hash = "sha256:44063f97dffb6a4fa94d60c5a9301862a8729596b39a0376235c4eac11be68d0"},
{file = "std_uritemplate-2.0.2.tar.gz", hash = "sha256:16e6b75d13803ddb81ba7b5fd1414698103b5c5c2fca1fb03dbc98f9fca80a92"},
@@ -4877,6 +5123,7 @@ version = "5.2.0"
description = "Manage dynamic plugins for Python applications"
optional = false
python-versions = ">=3.8"
+groups = ["dev"]
files = [
{file = "stevedore-5.2.0-py3-none-any.whl", hash = "sha256:1c15d95766ca0569cad14cb6272d4d31dae66b011a929d7c18219c176ea1b5c9"},
{file = "stevedore-5.2.0.tar.gz", hash = "sha256:46b93ca40e1114cea93d738a6c1e365396981bb6bb78c27045b7587c9473544d"},
@@ -4891,6 +5138,7 @@ version = "25.1.0"
description = "Structured Logging for Python"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "structlog-25.1.0-py3-none-any.whl", hash = "sha256:843fe4f254540329f380812cbe612e1af5ec5b8172205ae634679cd35a6d6321"},
{file = "structlog-25.1.0.tar.gz", hash = "sha256:2ef2a572e0e27f09664965d31a576afe64e46ac6084ef5cec3c2b8cd6e4e3ad3"},
@@ -4908,6 +5156,7 @@ version = "3.0.4"
description = "Validation of Swagger specifications"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "swagger_spec_validator-3.0.4-py2.py3-none-any.whl", hash = "sha256:1a2a4f4f7076479ae7835d892dd53952ccca9414efa172c440c775cf0ac01f48"},
{file = "swagger_spec_validator-3.0.4.tar.gz", hash = "sha256:637ac6d865270bfcd07df24605548e6e1f1d9c39adcfd855da37fa3fdebfed4b"},
@@ -4925,6 +5174,7 @@ version = "3.0.0"
description = "Celery integration for django-tenant-schemas and django-tenants"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "tenant_schemas_celery-3.0.0-py3-none-any.whl", hash = "sha256:ca0f69e78ef698eb4813468231df5a0ab6a660c08e657b65f5ac92e16887eec8"},
{file = "tenant_schemas_celery-3.0.0.tar.gz", hash = "sha256:6be3ae1a5826f262f0f3dd343c6a85a34a1c59b89e04ae37de018f36562fed55"},
@@ -4939,6 +5189,7 @@ version = "6.4.2"
description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed."
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "tornado-6.4.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e828cce1123e9e44ae2a50a9de3055497ab1d0aeb440c5ac23064d9e44880da1"},
{file = "tornado-6.4.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:072ce12ada169c5b00b7d92a99ba089447ccc993ea2143c9ede887e0937aa803"},
@@ -4959,6 +5210,7 @@ version = "0.26.0"
description = "A friendly Python library for async concurrency and I/O"
optional = false
python-versions = ">=3.8"
+groups = ["dev"]
files = [
{file = "trio-0.26.0-py3-none-any.whl", hash = "sha256:bb9c1b259591af941fccfbabbdc65bc7ed764bd2db76428454c894cd5e3d2032"},
{file = "trio-0.26.0.tar.gz", hash = "sha256:67c5ec3265dd4abc7b1d1ab9ca4fe4c25b896f9c93dac73713778adab487f9c4"},
@@ -4978,6 +5230,7 @@ version = "0.11.1"
description = "WebSocket library for Trio"
optional = false
python-versions = ">=3.7"
+groups = ["dev"]
files = [
{file = "trio-websocket-0.11.1.tar.gz", hash = "sha256:18c11793647703c158b1f6e62de638acada927344d534e3c7628eedcb746839f"},
{file = "trio_websocket-0.11.1-py3-none-any.whl", hash = "sha256:520d046b0d030cf970b8b2b2e00c4c2245b3807853ecd44214acd33d74581638"},
@@ -4993,6 +5246,7 @@ version = "9.4.5"
description = "Twilio API client and TwiML generator"
optional = false
python-versions = ">=3.7.0"
+groups = ["main"]
files = [
{file = "twilio-9.4.5-py2.py3-none-any.whl", hash = "sha256:284295946a5dcdaae65de9116c35db9065e1f3bd237d81da05b89fe1825013c6"},
{file = "twilio-9.4.5.tar.gz", hash = "sha256:8db69103a850cd05aaaa6bfb6952ef7a5d784aaff83f01d9a0c594b5ce784cd1"},
@@ -5010,6 +5264,7 @@ version = "24.7.0"
description = "An asynchronous networking framework written in Python"
optional = false
python-versions = ">=3.8.0"
+groups = ["dev"]
files = [
{file = "twisted-24.7.0-py3-none-any.whl", hash = "sha256:734832ef98108136e222b5230075b1079dad8a3fc5637319615619a7725b0c81"},
{file = "twisted-24.7.0.tar.gz", hash = "sha256:5a60147f044187a127ec7da96d170d49bcce50c6fd36f594e60f4587eff4d394"},
@@ -5048,6 +5303,7 @@ version = "23.1.1"
description = "Compatibility API between asyncio/Twisted/Trollius"
optional = false
python-versions = ">=3.7"
+groups = ["dev"]
files = [
{file = "txaio-23.1.1-py2.py3-none-any.whl", hash = "sha256:aaea42f8aad50e0ecfb976130ada140797e9dcb85fad2cf72b0f37f8cefcb490"},
{file = "txaio-23.1.1.tar.gz", hash = "sha256:f9a9216e976e5e3246dfd112ad7ad55ca915606b60b84a757ac769bd404ff704"},
@@ -5064,6 +5320,7 @@ version = "2.13.3"
description = "Run-time type checker for Python"
optional = false
python-versions = ">=3.5.3"
+groups = ["dev"]
files = [
{file = "typeguard-2.13.3-py3-none-any.whl", hash = "sha256:5e3e3be01e887e7eafae5af63d1f36c849aaa94e3a0112097312aabfa16284f1"},
{file = "typeguard-2.13.3.tar.gz", hash = "sha256:00edaa8da3a133674796cf5ea87d9f4b4c367d77476e185e80251cc13dfbb8c4"},
@@ -5079,6 +5336,7 @@ version = "4.12.2"
description = "Backported and Experimental Type Hints for Python 3.8+"
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
@@ -5090,10 +5348,12 @@ version = "2024.1"
description = "Provider of IANA time zone data"
optional = false
python-versions = ">=2"
+groups = ["main", "dev"]
files = [
{file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"},
{file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"},
]
+markers = {dev = "sys_platform == \"win32\""}
[[package]]
name = "ua-parser"
@@ -5101,6 +5361,7 @@ version = "1.0.1"
description = "Python port of Browserscope's user agent parser"
optional = false
python-versions = ">=3.9"
+groups = ["main"]
files = [
{file = "ua_parser-1.0.1-py3-none-any.whl", hash = "sha256:b059f2cb0935addea7e551251cbbf42e9a8872f86134163bc1a4f79e0945ffea"},
{file = "ua_parser-1.0.1.tar.gz", hash = "sha256:f9d92bf19d4329019cef91707aecc23c6d65143ad7e29a233f0580fb0d15547d"},
@@ -5120,6 +5381,7 @@ version = "0.18.0"
description = "Precompiled rules for User Agent Parser"
optional = false
python-versions = ">=3.9"
+groups = ["main"]
files = [
{file = "ua_parser_builtins-0.18.0-py3-none-any.whl", hash = "sha256:51cbc3d6ab9c533fc12fc7cededbef503c8d04e465d0aff20d869e15320b5ca9"},
]
@@ -5133,6 +5395,7 @@ version = "1.3.8"
description = "ASCII transliterations of Unicode text"
optional = false
python-versions = ">=3.5"
+groups = ["main"]
files = [
{file = "Unidecode-1.3.8-py3-none-any.whl", hash = "sha256:d130a61ce6696f8148a3bd8fe779c99adeb4b870584eeb9526584e9aa091fd39"},
{file = "Unidecode-1.3.8.tar.gz", hash = "sha256:cfdb349d46ed3873ece4586b96aa75258726e2fa8ec21d6f00a591d98806c2f4"},
@@ -5144,6 +5407,7 @@ version = "4.1.1"
description = "Implementation of RFC 6570 URI Templates"
optional = false
python-versions = ">=3.6"
+groups = ["main"]
files = [
{file = "uritemplate-4.1.1-py2.py3-none-any.whl", hash = "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e"},
{file = "uritemplate-4.1.1.tar.gz", hash = "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0"},
@@ -5155,6 +5419,7 @@ version = "2.3.0"
description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false
python-versions = ">=3.9"
+groups = ["main", "dev"]
files = [
{file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"},
{file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"},
@@ -5175,6 +5440,7 @@ version = "0.34.0"
description = "The lightning-fast ASGI server."
optional = false
python-versions = ">=3.9"
+groups = ["main"]
files = [
{file = "uvicorn-0.34.0-py3-none-any.whl", hash = "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4"},
{file = "uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9"},
@@ -5200,6 +5466,8 @@ version = "0.19.0"
description = "Fast implementation of asyncio event loop on top of libuv"
optional = false
python-versions = ">=3.8.0"
+groups = ["main"]
+markers = "(sys_platform != \"win32\" and sys_platform != \"cygwin\") and platform_python_implementation != \"PyPy\""
files = [
{file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e"},
{file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428"},
@@ -5244,6 +5512,7 @@ version = "5.1.0"
description = "Python promises."
optional = false
python-versions = ">=3.6"
+groups = ["main"]
files = [
{file = "vine-5.1.0-py3-none-any.whl", hash = "sha256:40fdf3c48b2cfe1c38a49e9ae2da6fda88e4794c810050a728bd7413811fb1dc"},
{file = "vine-5.1.0.tar.gz", hash = "sha256:8b62e981d35c41049211cf62a0a1242d8c1ee9bd15bb196ce38aefd6799e61e0"},
@@ -5255,6 +5524,7 @@ version = "6.0.0"
description = "Filesystem events monitoring"
optional = false
python-versions = ">=3.9"
+groups = ["main"]
files = [
{file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26"},
{file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112"},
@@ -5297,6 +5567,7 @@ version = "0.22.0"
description = "Simple, modern and high performance file watching and code reload in python."
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "watchfiles-0.22.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:da1e0a8caebf17976e2ffd00fa15f258e14749db5e014660f53114b676e68538"},
{file = "watchfiles-0.22.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61af9efa0733dc4ca462347becb82e8ef4945aba5135b1638bfc20fad64d4f0e"},
@@ -5384,6 +5655,7 @@ version = "0.2.13"
description = "Measures the displayed width of unicode strings in a terminal"
optional = false
python-versions = "*"
+groups = ["main"]
files = [
{file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"},
{file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"},
@@ -5395,6 +5667,7 @@ version = "2.5.1"
description = "Pythonic WebAuthn"
optional = false
python-versions = "*"
+groups = ["main"]
files = [
{file = "webauthn-2.5.1-py3-none-any.whl", hash = "sha256:86d1faa11ec26ebe49b9388d8c3d09bff4dca6c23d3c7e2dd066e99896d694f0"},
{file = "webauthn-2.5.1.tar.gz", hash = "sha256:f1b7447bae1056e110a9e71ff287f639d05d4d14589911d75fea255c3a03aff0"},
@@ -5412,6 +5685,7 @@ version = "1.8.0"
description = "WebSocket client for Python with low level API options"
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526"},
{file = "websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da"},
@@ -5428,6 +5702,7 @@ version = "12.0"
description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374"},
{file = "websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be"},
@@ -5509,6 +5784,7 @@ version = "1.16.0"
description = "Module for decorators, wrappers and monkey patching."
optional = false
python-versions = ">=3.6"
+groups = ["main"]
files = [
{file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"},
{file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"},
@@ -5588,6 +5864,7 @@ version = "1.2.0"
description = "WebSockets state-machine based protocol implementation"
optional = false
python-versions = ">=3.7.0"
+groups = ["main", "dev"]
files = [
{file = "wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"},
{file = "wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065"},
@@ -5602,6 +5879,7 @@ version = "1.3.14"
description = "Python bindings for the XML Security Library"
optional = false
python-versions = ">=3.5"
+groups = ["main"]
files = [
{file = "xmlsec-1.3.14-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4dea6df3ffcb65d0b215678c3a0fe7bbc66785d6eae81291296e372498bad43a"},
{file = "xmlsec-1.3.14-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fa1311f7489d050dde9028f5a2b5849c2927bb09c9a93491cb2f28fdc563912"},
@@ -5672,6 +5950,7 @@ version = "1.17.2"
description = "Yet another URL library"
optional = false
python-versions = ">=3.9"
+groups = ["main"]
files = [
{file = "yarl-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:93771146ef048b34201bfa382c2bf74c524980870bb278e6df515efaf93699ff"},
{file = "yarl-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8281db240a1616af2f9c5f71d355057e73a1409c4648c8949901396dc0a3c151"},
@@ -5768,6 +6047,7 @@ version = "3.20.2"
description = "Backport of pathlib-compatible object wrapper for zip files"
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350"},
{file = "zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"},
@@ -5787,6 +6067,7 @@ version = "6.4.post2"
description = "Interfaces for Python"
optional = false
python-versions = ">=3.7"
+groups = ["dev"]
files = [
{file = "zope.interface-6.4.post2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2eccd5bef45883802848f821d940367c1d0ad588de71e5cabe3813175444202c"},
{file = "zope.interface-6.4.post2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:762e616199f6319bb98e7f4f27d254c84c5fb1c25c908c2a9d0f92b92fb27530"},
@@ -5840,11 +6121,12 @@ version = "4.4.28"
description = ""
optional = false
python-versions = "*"
+groups = ["main"]
files = [
{file = "zxcvbn-4.4.28.tar.gz", hash = "sha256:151bd816817e645e9064c354b13544f85137ea3320ca3be1fb6873ea75ef7dc1"},
]
[metadata]
-lock-version = "2.0"
+lock-version = "2.1"
python-versions = "~3.12"
-content-hash = "a3915ac2ef2bb53f7cd67070912cdaf717c3bf73ed972fa337a9b07fce162451"
+content-hash = "8a6bfd4833e415a9f4f613ab4f33e60c8332b9f5743583222cdb7190f6286216"
diff --git a/pyproject.toml b/pyproject.toml
index 2fb4649d4b..e4312479f9 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -113,6 +113,7 @@ duo-client = "*"
fido2 = "*"
flower = "*"
geoip2 = "*"
+geopy = "*"
google-api-python-client = "*"
gunicorn = "*"
gssapi = "*"
diff --git a/schema.yml b/schema.yml
index ebb6732b40..c59deac6f7 100644
--- a/schema.yml
+++ b/schema.yml
@@ -44006,6 +44006,27 @@ components:
items:
$ref: '#/components/schemas/DetailedCountryField'
readOnly: true
+ check_history_distance:
+ type: boolean
+ history_max_distance_km:
+ type: integer
+ maximum: 9223372036854775807
+ minimum: 0
+ format: int64
+ distance_tolerance_km:
+ type: integer
+ maximum: 2147483647
+ minimum: 0
+ history_login_count:
+ type: integer
+ maximum: 2147483647
+ minimum: 0
+ check_impossible_travel:
+ type: boolean
+ impossible_tolerance_km:
+ type: integer
+ maximum: 2147483647
+ minimum: 0
required:
- bound_to
- component
@@ -44038,6 +44059,27 @@ components:
items:
$ref: '#/components/schemas/CountryCodeEnum'
maxItems: 249
+ check_history_distance:
+ type: boolean
+ history_max_distance_km:
+ type: integer
+ maximum: 9223372036854775807
+ minimum: 0
+ format: int64
+ distance_tolerance_km:
+ type: integer
+ maximum: 2147483647
+ minimum: 0
+ history_login_count:
+ type: integer
+ maximum: 2147483647
+ minimum: 0
+ check_impossible_travel:
+ type: boolean
+ impossible_tolerance_km:
+ type: integer
+ maximum: 2147483647
+ minimum: 0
required:
- countries
- name
@@ -50557,6 +50599,27 @@ components:
items:
$ref: '#/components/schemas/CountryCodeEnum'
maxItems: 249
+ check_history_distance:
+ type: boolean
+ history_max_distance_km:
+ type: integer
+ maximum: 9223372036854775807
+ minimum: 0
+ format: int64
+ distance_tolerance_km:
+ type: integer
+ maximum: 2147483647
+ minimum: 0
+ history_login_count:
+ type: integer
+ maximum: 2147483647
+ minimum: 0
+ check_impossible_travel:
+ type: boolean
+ impossible_tolerance_km:
+ type: integer
+ maximum: 2147483647
+ minimum: 0
PatchedGoogleWorkspaceProviderMappingRequest:
type: object
description: GoogleWorkspaceProviderMapping Serializer
diff --git a/web/src/admin/policies/geoip/GeoIPPolicyForm.ts b/web/src/admin/policies/geoip/GeoIPPolicyForm.ts
index 440323a430..1b5119ae2b 100644
--- a/web/src/admin/policies/geoip/GeoIPPolicyForm.ts
+++ b/web/src/admin/policies/geoip/GeoIPPolicyForm.ts
@@ -1,5 +1,6 @@
import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
+import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/ak-dual-select";
import { DataProvision, DualSelectPair } from "@goauthentik/elements/ak-dual-select/types";
import "@goauthentik/elements/forms/FormGroup";
@@ -46,7 +47,7 @@ export class GeoIPPolicyForm extends BasePolicyForm {
}
renderForm(): TemplateResult {
- return html`
+ return html`
${msg(
"Ensure the user satisfies requirements of geography or network topology, based on IP address. If any of the configured values match, the policy passes.",
)}
@@ -79,13 +80,125 @@ export class GeoIPPolicyForm extends BasePolicyForm {
)}
-
- ${msg("Policy-specific settings")}
+
+ ${msg("Distance settings")}
+
+
+
+ ${msg("Distance settings (Impossible travel)")}
+
+
+
+ ${msg("Static rule settings")}