add get_items

This commit is contained in:
2025-04-08 13:44:06 -03:00
parent 68ff6f282b
commit 6450e5fa7c
18 changed files with 393 additions and 195 deletions

View File

@@ -13,7 +13,7 @@ from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools.utilities.typing import LambdaContext
from middlewares import AuthorizerMiddleware
from routes import courses, enrollments, lookup, orders, settings, users, webhooks
from routes import courses, enrollments, lookup, orders, orgs, settings, users, webhooks
tracer = Tracer()
logger = Logger(__name__)
@@ -33,6 +33,7 @@ app.include_router(courses.router, prefix='/courses')
app.include_router(enrollments.router, prefix='/enrollments')
app.include_router(orders.router, prefix='/orders')
app.include_router(users.router, prefix='/users')
app.include_router(orgs.router, prefix='/orgs')
app.include_router(webhooks.router, prefix='/webhooks')
app.include_router(settings.router, prefix='/settings')
app.include_router(lookup.router, prefix='/lookup')

View File

@@ -15,7 +15,7 @@ def create_course(
transact.put(
item={
'sk': '0',
'tenant:org_id': {org.id},
'tenant__org_id': {org.id},
'create_date': current_time,
**course.model_dump(),
}
@@ -41,7 +41,7 @@ def update_course(
current_time = now()
transact = TransactItems(persistence_layer.table_name)
transact.update(
key=KeyPair(course.id, '0'), # type: ignore
key=KeyPair(id, '0'),
update_expr='SET #name = :name, access_period = :access_period, cert = :cert, update_date = :update_date',
expr_attr_names={
'#name': 'name',

View File

@@ -1,21 +1,25 @@
import json
from http import HTTPStatus
from aws_lambda_powertools.event_handler import Response, content_types
from aws_lambda_powertools.event_handler.api_gateway import Router
from aws_lambda_powertools.event_handler.exceptions import NotFoundError
from elasticsearch import Elasticsearch
from layercake.dynamodb import DynamoDBCollection, DynamoDBPersistenceLayer, KeyPair
from meilisearch import Client as Meilisearch
import elastic
from boto3clients import dynamodb_client
from course import create_course, update_course
from middlewares import AuditLogMiddleware, Tenant, TenantMiddleware
from models import Course, Org
from settings import COURSE_TABLE, ELASTIC_CONN, USER_TABLE
from settings import (
COURSE_TABLE,
MEILISEARCH_API_KEY,
MEILISEARCH_HOST,
USER_TABLE,
)
router = Router()
elastic_client = Elasticsearch(**ELASTIC_CONN)
meili_client = Meilisearch(MEILISEARCH_HOST, MEILISEARCH_API_KEY)
course_layer = DynamoDBPersistenceLayer(COURSE_TABLE, dynamodb_client)
user_layer = DynamoDBPersistenceLayer(USER_TABLE, dynamodb_client)
user_collect = DynamoDBCollection(user_layer)
@@ -30,14 +34,19 @@ course_collect = DynamoDBCollection(course_layer)
)
def get_courses():
event = router.current_event
query = event.get_query_string_value('query', '{}')
page_size = event.get_query_string_value('page_size', '25')
query = event.get_query_string_value('query', '')
sort = event.get_query_string_value('sort', '')
page = int(event.get_query_string_value('page', '1'))
hits_per_page = int(event.get_query_string_value('hitsPerPage', '25'))
return elastic.search(
index=COURSE_TABLE,
page_size=int(page_size),
query=json.loads(query),
elastic_client=elastic_client,
return meili_client.index(COURSE_TABLE).search(
query,
{
'sort': [sort],
'locales': ['pt'],
'page': page,
'hitsPerPage': hits_per_page,
},
)

View File

@@ -1,12 +1,23 @@
import json
from aws_lambda_powertools.event_handler.api_gateway import Router
from aws_lambda_powertools.event_handler.exceptions import (
BadRequestError,
)
from elasticsearch import Elasticsearch
from layercake.dynamodb import (
DynamoDBCollection,
DynamoDBPersistenceLayer,
KeyPair,
)
import elastic
from boto3clients import dynamodb_client
from settings import ELASTIC_CONN, ORDER_TABLE
router = Router()
order_layer = DynamoDBPersistenceLayer(ORDER_TABLE, dynamodb_client)
order_collect = DynamoDBCollection(order_layer, exception_cls=BadRequestError)
elastic_client = Elasticsearch(**ELASTIC_CONN)
@@ -22,3 +33,13 @@ def get_orders():
query=json.loads(query),
elastic_client=elastic_client,
)
@router.get(
'/<id>',
compress=True,
tags=['Order'],
summary='Get order',
)
def get_order(id: str):
return order_collect.get_item(KeyPair(id, '0'))

View File

@@ -1,2 +1,64 @@
{"id": {"S": "90d7f0d2-d9a4-4467-a31c-f9a7955964cf"},"sk": {"S": "0"},"access_period": {"N": "365"},"cert": {"M": {"id": {"S": "certs#ADu8ZacrZ5ZunbYWii6NFJ"},"exp_interval": {"N": "730"},"s3_uri": {"S": ""}}},"create_date": {"S": "2024-12-30T00:00:33.088916-03:00"},"konviva:class_id": {"N": "21"},"name": {"S": "NR-10 Básico"},"tenant:org_id": {"SS": ["*"]}}
{"id": {"S": "90d7f0d2-d9a4-4467-a31c-f9a7955964cf"},"sk": {"S": "tenant"},"create_date": {"S": "2025-03-29T12:10:59.494251-03:00"},"name": {"S": "default"},"org_id": {"S": "*"}}
{"id": {"S": "439e9a43-ab92-469a-a849-b6e824370f80"}, "access_period": {"S": "360"}, "name": {"S": "No\u00e7\u00f5es em Primeiros Socorros"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:06:33.088916-03:00"}, "betaeducacao__course_id": {"S": "2c1e724a-58c6-4c20-90df-18b5660d6304"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "94"}}
{"id": {"S": "15ee05a3-4ceb-4b7e-9979-db75b28c9ade"}, "access_period": {"S": "360"}, "name": {"S": "Reciclagem de NR-10 SEP 08 horas"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:02:33.088916-03:00"}, "betaeducacao__course_id": {"S": "1d86444e-36d6-4ed7-8cea-24a4df9ca15f"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "276"}}
{"id": {"S": "4ea2498a-a6a9-4293-94d0-ceeb248e64b7"}, "access_period": {"S": "720"}, "name": {"S": "NR-10 B\u00e1sico"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:07:33.088916-03:00"}, "betaeducacao__course_id": {"S": "38"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "21"}}
{"id": {"S": "e1c44881-2fe3-484e-ada2-12b6bf5b9398"}, "access_period": {"S": "720"}, "name": {"S": "NR-35 Seguran\u00e7a nos Trabalhos em Altura (Te\u00f3rico)"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:11:33.088916-03:00"}, "betaeducacao__course_id": {"S": "42"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "1"}}
{"id": {"S": "281198c2-f293-4acc-b96e-e4a2d5f6b73c"}, "access_period": {"S": "360"}, "name": {"S": "CIPA"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:10:33.088916-03:00"}, "betaeducacao__course_id": {"S": "41"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "3"}}
{"id": {"S": "4866c068-577a-45b0-b41a-41a7dc6b9ab7"}, "access_period": {"S": "360"}, "name": {"S": "Combate a Inc\u00eandio"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:17:33.088916-03:00"}, "betaeducacao__course_id": {"S": "53"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "18"}}
{"id": {"S": "f10c3283-7722-41c6-ba5d-222f9f4f48af"}, "access_period": {"S": "360"}, "name": {"S": "NR-11 Operador de Empilhadeira"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:13:33.088916-03:00"}, "betaeducacao__course_id": {"S": "49"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "23"}}
{"id": {"S": "39f89a69-3d94-4dd6-9049-66e540fb2f32"}, "access_period": {"S": "720"}, "name": {"S": "Reciclagem em NR-10 Complementar (SEP)"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:20:33.088916-03:00"}, "betaeducacao__course_id": {"S": "56"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "36"}}
{"id": {"S": "38d8ba20-49a4-4c69-b674-b70a985eb76a"}, "access_period": {"S": "720"}, "name": {"S": "CIPA Grau de Risco 4"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:21:33.088916-03:00"}, "betaeducacao__course_id": {"S": "56771ce5-4680-4ce4-b257-8f2362975494"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "218"}}
{"id": {"S": "d800d2a9-ae76-46de-be82-3e06ae6afcee"}, "access_period": {"S": "720"}, "name": {"S": "NR-20 B\u00e1sico"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:29:33.088916-03:00"}, "betaeducacao__course_id": {"S": "70"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "28"}}
{"id": {"S": "3c27ea9c-9464-46a1-9717-8c1441793186"}, "access_period": {"S": "720"}, "name": {"S": "CIPA Grau de Risco 1"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:28:33.088916-03:00"}, "betaeducacao__course_id": {"S": "6f6fbc20-57f1-4d68-bf00-00119141894f"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "200"}}
{"id": {"S": "96c2553a-d087-42ad-be5e-e960ea673c3d"}, "access_period": {"S": "360"}, "name": {"S": "NR-18 Sinaleiro e Amarrador de Cargas para I\u00e7amento"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:30:33.088916-03:00"}, "betaeducacao__course_id": {"S": "711bad57-2a03-43ff-91d0-31d151063897"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "270"}}
{"id": {"S": "5c119d4b-573c-4d8d-a99d-63756af2f4c5"}, "access_period": {"S": "360"}, "name": {"S": "NR-06 - Equipamento de Prote\u00e7\u00e3o Individual - EPI"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:32:33.088916-03:00"}, "betaeducacao__course_id": {"S": "78"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "34"}}
{"id": {"S": "7f7905aa-ec6d-4189-b884-50fa9b1bd0b8"}, "access_period": {"S": "360"}, "name": {"S": "NR-10 Reciclagem: 08 horas"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:01:33.088916-03:00"}, "betaeducacao__course_id": {"S": "005f262d-9eda-4304-8639-31a86efb3086"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "275"}}
{"id": {"S": "07da69f2-2a2c-4771-b766-633295476ad7"}, "access_period": {"S": "360"}, "name": {"S": "NR-26 Sinaliza\u00e7\u00e3o de Seguran\u00e7a"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:05:33.088916-03:00"}, "betaeducacao__course_id": {"S": "29b46896-eb93-40ab-8439-25d5129d108a"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "123"}}
{"id": {"S": "d6520884-89e7-4843-b77f-7777c5376d50"}, "access_period": {"S": "360"}, "name": {"S": "Reciclagem em NR-13 Operador de Caldeiras"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:03:33.088916-03:00"}, "betaeducacao__course_id": {"S": "1eac1304-6b5a-4fe1-884f-ef2dec753313"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "261"}}
{"id": {"S": "9301601e-385a-4525-a65a-4054f669632f"}, "access_period": {"S": "360"}, "name": {"S": "Reciclagem em NR-13 Vasos de Press\u00e3o e Unidades de Processo"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:12:33.088916-03:00"}, "betaeducacao__course_id": {"S": "452f8158-4ed9-4ca5-a53f-c82db430e990"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "262"}}
{"id": {"S": "52b4a909-b6a9-456e-a7b9-c0b3c18ebe00"}, "access_period": {"S": "360"}, "name": {"S": "NR-12 M\u00e1quinas e Equipamentos"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:25:33.088916-03:00"}, "betaeducacao__course_id": {"S": "62"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "24"}}
{"id": {"S": "b23493dd-6359-4352-97be-12dca3a21ca6"}, "access_period": {"S": "360"}, "name": {"S": "NR-33 Trabalhadores Autorizados e Vigias em Espa\u00e7o Confinado"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:18:33.088916-03:00"}, "betaeducacao__course_id": {"S": "54"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "32"}}
{"id": {"S": "5c53656d-9557-4ef9-8e05-08d3190bb115"}, "access_period": {"S": "360"}, "name": {"S": "NR-13 Operador de Caldeiras"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:26:33.088916-03:00"}, "betaeducacao__course_id": {"S": "63"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "25"}}
{"id": {"S": "124ca098-b609-4550-a83c-6b9120a2db42"}, "access_period": {"S": "360"}, "name": {"S": "Reciclagem em NR-11 Transpaleteiras"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:34:33.088916-03:00"}, "betaeducacao__course_id": {"S": "7d6e413e-800b-48b6-9b60-f8ac5d3ee730"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "265"}}
{"id": {"S": "6dd8f711-5c5a-477a-971f-122cbac4ce48"}, "access_period": {"S": "720"}, "name": {"S": "NR-35 Supervisor de Trabalho em Altura"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:27:33.088916-03:00"}, "betaeducacao__course_id": {"S": "64"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "33"}}
{"id": {"S": "4e52d4e9-0566-4f8c-8307-1db770e4c33c"}, "access_period": {"S": "360"}, "name": {"S": "NR-17 Ergonomia"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:31:33.088916-03:00"}, "betaeducacao__course_id": {"S": "723534ae-36ae-4253-bb73-966c8268779d"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "105"}}
{"id": {"S": "863214e8-26e2-440b-854b-a0ced0164bbf"}, "access_period": {"S": "360"}, "name": {"S": "CIPA Grau de Risco 3 (te\u00f3rico)"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:09:33.088916-03:00"}, "betaeducacao__course_id": {"S": "4079b429-aac4-4a41-937a-38bd6101d875"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "259"}}
{"id": {"S": "7aba7598-83b2-4df7-938c-d075ffef47ca"}, "access_period": {"S": "360"}, "name": {"S": "NR-18 - Constru\u00e7\u00e3o Civil"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:16:33.088916-03:00"}, "betaeducacao__course_id": {"S": "52"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "27"}}
{"id": {"S": "2e1c93c2-1779-482b-9552-c04e09db8349"}, "access_period": {"S": "720"}, "name": {"S": "NR-10 Complementar (SEP)"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:19:33.088916-03:00"}, "betaeducacao__course_id": {"S": "55"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "22"}}
{"id": {"S": "70827c13-1db5-4499-977f-9a6623e45161"}, "access_period": {"S": "360"}, "name": {"S": "NR-11 Seguran\u00e7a na Opera\u00e7\u00e3o de Rebocadores"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:22:33.088916-03:00"}, "betaeducacao__course_id": {"S": "56d1c710-36b1-4db5-8a7a-dacb7098dbad"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "154"}}
{"id": {"S": "4a0c4652-fcb3-4362-8fff-bc5ac3ba1cf3"}, "access_period": {"S": "360"}, "name": {"S": "Reciclagem em NR-11 Plataforma de Trabalho Elevat\u00f3ria (PTA)"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:04:33.088916-03:00"}, "betaeducacao__course_id": {"S": "2706ca6d-2b1b-47aa-8f02-5d39c8833b9d"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "166"}}
{"id": {"S": "c01ec8a2-0359-4351-befb-76c3577339e0"}, "access_period": {"S": "720"}, "name": {"S": "Reciclagem em NR-10 B\u00e1sico"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:08:33.088916-03:00"}, "betaeducacao__course_id": {"S": "40"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "35"}}
{"id": {"S": "a1a8727c-0519-4692-93e7-81dbe66e167f"}, "access_period": {"S": "360"}, "name": {"S": "Dire\u00e7\u00e3o Defensiva (20 horas)"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:15:33.088916-03:00"}, "betaeducacao__course_id": {"S": "50"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "19"}}
{"id": {"S": "eb19c520-5546-4c57-898d-029c86e59fb6"}, "access_period": {"S": "360"}, "name": {"S": "Reciclagem em NR-33 Supervisores em Espa\u00e7o Confinado"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:14:33.088916-03:00"}, "betaeducacao__course_id": {"S": "4ea8aaec-cfd3-4ec1-a15b-a72fac56b371"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "117"}}
{"id": {"S": "386f7086-2871-436f-85f5-31d632fbf624"}, "access_period": {"S": "360"}, "name": {"S": "Boas Pr\u00e1ticas em Manipula\u00e7\u00e3o de Alimentos"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:24:33.088916-03:00"}, "betaeducacao__course_id": {"S": "59"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "4"}}
{"id": {"S": "3f284753-85ce-4f53-8de7-cdfcdaf9515b"}, "access_period": {"S": "360"}, "name": {"S": "NR-33 Supervisor em Espa\u00e7o Confinado"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:23:33.088916-03:00"}, "betaeducacao__course_id": {"S": "57"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "31"}}
{"id": {"S": "00ebdd8d-b4db-4437-8814-274811a4c469"}, "access_period": {"S": "360"}, "name": {"S": "Dire\u00e7\u00e3o Defensiva (08 horas)"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:33:33.088916-03:00"}, "betaeducacao__course_id": {"S": "7ac2e34e-232a-427c-a3fc-32198e3a51c6"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "194"}}
{"id": {"S": "8efe00d2-38e2-4281-8f5e-b9113e91374b"}, "access_period": {"S": "1080"}, "name": {"S": "Reciclagem em NR-20 B\u00e1sico"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:43:33.088916-03:00"}, "betaeducacao__course_id": {"S": "91"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "39"}}
{"id": {"S": "a3c46d94-cf31-4b5f-8de3-6aa1c2d423f0"}, "access_period": {"S": "360"}, "name": {"S": "NR-17 Ergonomia para Teleatendimento/Telemarketing"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:48:33.088916-03:00"}, "betaeducacao__course_id": {"S": "94dc4c63-9f23-4101-a0d7-d42bfa527cbc"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "269"}}
{"id": {"S": "450a70ca-8ab5-4520-8a22-0e277359797d"}, "access_period": {"S": "365"}, "name": {"S": "NR-18 PEMT PTA"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:52:33.088916-03:00"}, "betaeducacao__course_id": {"S": "a6775b71-d68a-4263-8ab4-acb3a4f8a8b9"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "184"}}
{"id": {"S": "f05293f0-2ff4-4026-9e65-2f0f67d9f83b"}, "access_period": {"S": "360"}, "name": {"S": "Preven\u00e7\u00e3o e combate ao ass\u00e9dio sexual e \u00e0s demais formas de viol\u00eancia no trabalho"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T01:00:33.088916-03:00"}, "betaeducacao__course_id": {"S": "da03eac1-e328-49d0-8014-5cdd023cb543"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "260"}}
{"id": {"S": "446426ce-c0f0-4238-83ed-95e8c0434f45"}, "access_period": {"S": "360"}, "name": {"S": "Reciclagem de NR-11 Seguran\u00e7a na Opera\u00e7\u00e3o de Rebocadores"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T01:04:33.088916-03:00"}, "betaeducacao__course_id": {"S": "f78d2241-13fd-45ab-81cc-0acb781b4107"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "189"}}
{"id": {"S": "479516a7-5431-452e-8f28-228e34b86e0c"}, "access_period": {"S": "360"}, "name": {"S": "NR-11 Seguran\u00e7a em Transpaleteira"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T01:03:33.088916-03:00"}, "betaeducacao__course_id": {"S": "e39a8718-cf10-4dcc-a152-8c50b4b63e14"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "268"}}
{"id": {"S": "95a1fcb9-ba16-4b3c-a59d-047ca32078ff"}, "access_period": {"S": "360"}, "name": {"S": "NR-20 Inicia\u00e7\u00e3o"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:36:33.088916-03:00"}, "betaeducacao__course_id": {"S": "83"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "29"}}
{"id": {"S": "2b9a6e19-2e2d-4fc2-8924-b45d47057715"}, "access_period": {"S": "360"}, "name": {"S": "Reciclagem em NR-33 Trabalhos em Espa\u00e7os Confinados"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:42:33.088916-03:00"}, "betaeducacao__course_id": {"S": "90"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "38"}}
{"id": {"S": "76a5ba94-e11c-48f5-88eb-9326df9be264"}, "access_period": {"S": "360"}, "name": {"S": "Reciclagem de NR-12 M\u00e1quinas e Equipamentos"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:45:33.088916-03:00"}, "betaeducacao__course_id": {"S": "929960de-a62d-4669-91e5-8fef8d670103"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "273"}}
{"id": {"S": "0707270e-623f-486a-8dbd-d852377a208c"}, "access_period": {"S": "720"}, "name": {"S": "Reciclagem em NR-20 - Intermedi\u00e1rio"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:44:33.088916-03:00"}, "betaeducacao__course_id": {"S": "92"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "57"}}
{"id": {"S": "96c03c32-089c-4ccb-8aa1-73b0f49228b9"}, "access_period": {"S": "360"}, "name": {"S": "Lei Lucas: Primeiros Socorros nas Escolas"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:49:33.088916-03:00"}, "betaeducacao__course_id": {"S": "9bb3fe7d-e29d-4a2f-91d9-87910152152b"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "278"}}
{"id": {"S": "6a403773-aeac-4e6a-ac39-dc958e4be52a"}, "access_period": {"S": "360"}, "name": {"S": "Reciclagem em NR-11 - Operador de Empilhadeira"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:47:33.088916-03:00"}, "betaeducacao__course_id": {"S": "94"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "63"}}
{"id": {"S": "0e39c7af-a812-49aa-ac12-72f4e0ede8c9"}, "access_period": {"S": "360"}, "name": {"S": "Reciclagem de NR-18 Plataforma de Trabalho A\u00e9reo PEMT"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:51:33.088916-03:00"}, "betaeducacao__course_id": {"S": "a52eb5c5-4a5c-404b-96fe-e34037805d1e"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "272"}}
{"id": {"S": "99bb3b60-4ded-4a8e-937c-ba2d78ec6454"}, "access_period": {"S": "720"}, "name": {"S": "CIPA Grau de Risco 2"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:55:33.088916-03:00"}, "betaeducacao__course_id": {"S": "b4de57c8-59e8-43ad-a6fa-6735d4faa54b"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "206"}}
{"id": {"S": "801d1115-b4e8-4213-96b1-0b4f99bf202e"}, "access_period": {"S": "720"}, "name": {"S": "Reciclagem em NR-18 B\u00e1sico em seguran\u00e7a do trabalho"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:35:33.088916-03:00"}, "betaeducacao__course_id": {"S": "7e981a6b-8776-4747-bc3b-dcad638b5273"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "266"}}
{"id": {"S": "6689a04a-99c1-4150-b1ed-c131b6dc5bb5"}, "access_period": {"S": "720"}, "name": {"S": "NR-20 Intermedi\u00e1rio"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:37:33.088916-03:00"}, "betaeducacao__course_id": {"S": "84"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "30"}}
{"id": {"S": "c19cd7ee-3cc8-4f9c-95ff-dad7993f49b1"}, "access_period": {"S": "360"}, "name": {"S": "Gest\u00e3o da Cultura de Seguran\u00e7a"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:40:33.088916-03:00"}, "betaeducacao__course_id": {"S": "87"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "17"}}
{"id": {"S": "d9f9c3d6-ba97-4695-b1fb-e2539158b064"}, "access_period": {"S": "360"}, "name": {"S": "Reciclagem em NR-20 Avan\u00e7ado II"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:50:33.088916-03:00"}, "betaeducacao__course_id": {"S": "a3dd23e1-09a0-4c24-a042-08ed65e07fc1"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "131"}}
{"id": {"S": "b945be62-408d-4099-a75c-4d1dda929659"}, "access_period": {"S": "360"}, "name": {"S": "NR-11 Seguran\u00e7a na Opera\u00e7\u00e3o de Pontes Rolantes"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:56:33.088916-03:00"}, "betaeducacao__course_id": {"S": "bf8b81d6-f83a-4216-bcdb-31ba1e21ffcb"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "148"}}
{"id": {"S": "5c9c1ff1-361f-479d-bd2c-eb3b124a74fc"}, "access_period": {"S": "360"}, "name": {"S": "NR-31 CIPATR"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:54:33.088916-03:00"}, "betaeducacao__course_id": {"S": "b331f93b-9fc5-4791-bd81-fb10c8f5e401"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "137"}}
{"id": {"S": "80dfc302-4e05-4f23-944d-9a2768cb6c7d"}, "access_period": {"S": "360"}, "name": {"S": "LOTO Lockout e Tagout"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:58:33.088916-03:00"}, "betaeducacao__course_id": {"S": "d23d569e-51e8-499a-b407-bd782c64a6ac"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "271"}}
{"id": {"S": "c2d1362f-aa7f-40b0-bd15-37570bda5f25"}, "access_period": {"S": "360"}, "name": {"S": "PCA - Programa de Conserva\u00e7\u00e3o Auditiva"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T01:05:33.088916-03:00"}, "betaeducacao__course_id": {"S": "fa00bc23-d6b8-4dc5-86e7-dc0a9bdb2306"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "247"}}
{"id": {"S": "4682187a-cb5c-47a8-9597-ad9243a6d717"}, "access_period": {"S": "365"}, "name": {"S": "NR-11 Seguran\u00e7a na Opera\u00e7\u00e3o de Talhas"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T01:02:33.088916-03:00"}, "betaeducacao__course_id": {"S": "e2e25a9a-3104-47a7-90da-0be05a157d21"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "144"}}
{"id": {"S": "a810dd22-56c0-4d9b-8cd2-7e2ee9c45839"}, "access_period": {"N": "360"}, "name": {"S": "NR-11 \u2013 Transporte, movimenta\u00e7\u00e3o, armazenagem e manuseio de materiais"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T01:01:33.088916-03:00"}, "betaeducacao__course_id": {"S": "dc1a0428-47bf-4db1-a5da-24be49c9fda6"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "100"}, "cert": {"NULL": true}, "update_date": {"S": "2025-04-04T20:30:05.033976-03:00"}}
{"id": {"S": "1c7b1cf0-6973-4271-9407-6e974f0094e9"}, "access_period": {"S": "360"}, "name": {"S": "PPR Programa de Prote\u00e7\u00e3o Respirat\u00f3ria"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:39:33.088916-03:00"}, "betaeducacao__course_id": {"S": "86d310e8-a87d-4b38-9e43-3dd247c6a522"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "224"}}
{"id": {"S": "6d17d9cf-96be-42a4-bae5-75926e1e832a"}, "access_period": {"S": "720"}, "name": {"S": "Exposi\u00e7\u00e3o ao Benzeno - (Portaria 1109)"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:38:33.088916-03:00"}, "betaeducacao__course_id": {"S": "86"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "20"}}
{"id": {"S": "3b05b03c-8714-4f98-90e0-2a3ac4940035"}, "access_period": {"S": "720"}, "name": {"S": "NR-13 Vasos de Press\u00e3o e Unidades de Processo"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:41:33.088916-03:00"}, "betaeducacao__course_id": {"S": "89"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "26"}}
{"id": {"S": "30bb357f-2f48-4764-93d1-ffe219cbc5d3"}, "access_period": {"S": "720"}, "name": {"S": "Reciclagem em NR-35 Trabalhos em Altura ( Te\u00f3rico)"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:46:33.088916-03:00"}, "betaeducacao__course_id": {"S": "93"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "51"}}
{"id": {"S": "f7def039-bf27-496a-94ff-0667c9c0c0db"}, "access_period": {"S": "720"}, "name": {"S": "CIPA Grau de Risco 3"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:53:33.088916-03:00"}, "betaeducacao__course_id": {"S": "b09ca8da-f342-4a70-aaaa-67ac81569533"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "212"}}
{"id": {"S": "b3d0e345-a8e5-4dc2-a3b0-218bc894ee55"}, "access_period": {"S": "360"}, "name": {"S": "NR-10: No\u00e7\u00f5es do Risco El\u00e9trico"}, "sk": {"S": "0"}, "create_date": {"S": "2024-12-30T00:57:33.088916-03:00"}, "betaeducacao__course_id": {"S": "c5b683a3-f432-46e9-94e4-290a788d2ff6"}, "tenant__org_id": {"L": [{"S": "*"}]}, "konviva__class_id": {"S": "274"}}

View File

@@ -8,16 +8,24 @@ COURSE_TABLE: str = os.getenv('COURSE_TABLE') # type: ignore
KONVIVA_API_URL: str = os.getenv('KONVIVA_API_URL') # type: ignore
KONVIVA_SECRET_KEY: str = os.getenv('KONVIVA_SECRET_KEY') # type: ignore
MEILISEARCH_HOST: str = os.getenv('MEILISEARCH_HOST') # type: ignore
MEILISEARCH_API_KEY: str = os.getenv('MEILISEARCH_API_KEY') # type: ignore
match os.getenv('AWS_SAM_LOCAL'), os.getenv('PYTEST_VERSION'):
case str() as SAM_LOCAL, _ if SAM_LOCAL: # Only when running `sam local start-api`
MEILISEARCH_HOST = 'http://host.docker.internal:7700'
ELASTIC_CONN = {
'hosts': 'http://host.docker.internal:9200',
}
case _, str() as PYTEST if PYTEST: # Only when running `pytest`
MEILISEARCH_HOST = 'http://127.0.0.1:7700'
ELASTIC_CONN = {
'hosts': 'http://127.0.0.1:9200',
}
case _:
MEILISEARCH_HOST: str = os.getenv('MEILISEARCH_HOST') # type: ignore
ELASTIC_CLOUD_ID = os.getenv('ELASTIC_CLOUD_ID')
ELASTIC_AUTH_PASS = os.getenv('ELASTIC_AUTH_PASS')
ELASTIC_CONN = {

View File

@@ -80,6 +80,8 @@ Resources:
TableName: !Ref UserTable
- DynamoDBCrudPolicy:
TableName: !Ref CourseTable
- DynamoDBCrudPolicy:
TableName: !Ref OrderTable
Events:
Preflight:
Type: HttpApi

View File

@@ -14,6 +14,24 @@ from ..conftest import HttpApiProxy, LambdaContext
YEAR_DAYS = 365
def test_get_course(
mock_app,
dynamodb_seeds,
http_api_proxy: HttpApiProxy,
lambda_context: LambdaContext,
):
r = mock_app.lambda_handler(
http_api_proxy(
raw_path='/courses',
method=HTTPMethod.GET,
headers={'X-Tenant': '*'},
),
lambda_context,
)
print(r)
def test_post_course(
mock_app,
dynamodb_seeds,
@@ -72,9 +90,8 @@ def test_put_course(
),
lambda_context,
)
assert r['statusCode'] == HTTPStatus.OK
collect = DynamoDBCollection(dynamodb_persistence_layer)
course = collect.get_item(KeyPair('90d7f0d2-d9a4-4467-a31c-f9a7955964cf', '0'))
print(course)
assert r['statusCode'] == HTTPStatus.OK
assert course['name'] == 'pytest'

View File

@@ -7,5 +7,6 @@
{"id": {"S": "5OxmMjL-ujoR5IMGegQz"}, "sk": {"S": "orgs#cJtK9SsnJhKPyxESe7g3DG"}, "cnpj": {"S": "15608435000190"}, "create_date": {"S": "2025-03-13T16:36:50.073156-03:00"}, "name": {"S": "Beta Educação"}}
{"id": {"S": "log:5OxmMjL-ujoR5IMGegQz"}, "sk": {"S": "2024-02-08T16:42:33.776409-03:00"}, "action": {"S": "OPEN_EMAIL"}}
{"id": {"S": "log:5OxmMjL-ujoR5IMGegQz"}, "sk": {"S": "2019-03-25T00:00:00-03:00"}, "action": {"S": "CLICK_EMAIL"}}
{"id": {"S": "cJtK9SsnJhKPyxESe7g3DG"}, "sk": {"S": "0"}, "name": {"S": "EDUSEG"}, "cnpj": {"S": "15608435000190"}}
{"id": {"S": "90d7f0d2-d9a4-4467-a31c-f9a7955964cf"}, "sk": {"S": "0"}, "access_period": {"N": "720"}, "create_date": {"S": "2024-12-30T00:00:33.088916-03:00"},"konviva:class_id": {"N": "266"},"name": {"S": "Reciclagem em NR-18 Básico"},"tenant:org_id": {"SS": ["cJtK9SsnJhKPyxESe7g3DG"]}}
{"id": {"S": "cJtK9SsnJhKPyxESe7g3DG"}, "sk": {"S": "0"}, "name": {"S": "EDUSEG"}, "cnpj": {"S": "15608435000190"}, "email": {"S": "org+15608435000190@users.noreply.betaeducacao.com.br"}}
{"id": {"S": "cJtK9SsnJhKPyxESe7g3DG"}, "sk": {"S": "payment_policies"}, "due_days": {"N": "90"}}
{"id": {"S": "90d7f0d2-d9a4-4467-a31c-f9a7955964cf"}, "sk": {"S": "0"}, "access_period": {"N": "720"}, "create_date": {"S": "2024-12-30T00:00:33.088916-03:00"},"konviva__class_id": {"N": "266"},"name": {"S": "Reciclagem em NR-18 Básico"},"tenant__org_id": {"SS": ["cJtK9SsnJhKPyxESe7g3DG"]}}

122
http-api/uv.lock generated
View File

@@ -1,5 +1,5 @@
version = 1
requires-python = ">=3.12"
requires-python = ">=3.13"
[[package]]
name = "annotated-types"
@@ -122,24 +122,6 @@ version = "1.1.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/2f/c2/f9e977608bdf958650638c3f1e28f85a1b075f075ebbe77db8555463787b/Brotli-1.1.0.tar.gz", hash = "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724", size = 7372270 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5c/d0/5373ae13b93fe00095a58efcbce837fd470ca39f703a235d2a999baadfbc/Brotli-1.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:32d95b80260d79926f5fab3c41701dbb818fde1c9da590e77e571eefd14abe28", size = 815693 },
{ url = "https://files.pythonhosted.org/packages/8e/48/f6e1cdf86751300c288c1459724bfa6917a80e30dbfc326f92cea5d3683a/Brotli-1.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b760c65308ff1e462f65d69c12e4ae085cff3b332d894637f6273a12a482d09f", size = 422489 },
{ url = "https://files.pythonhosted.org/packages/06/88/564958cedce636d0f1bed313381dfc4b4e3d3f6015a63dae6146e1b8c65c/Brotli-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409", size = 873081 },
{ url = "https://files.pythonhosted.org/packages/58/79/b7026a8bb65da9a6bb7d14329fd2bd48d2b7f86d7329d5cc8ddc6a90526f/Brotli-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2", size = 446244 },
{ url = "https://files.pythonhosted.org/packages/e5/18/c18c32ecea41b6c0004e15606e274006366fe19436b6adccc1ae7b2e50c2/Brotli-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451", size = 2906505 },
{ url = "https://files.pythonhosted.org/packages/08/c8/69ec0496b1ada7569b62d85893d928e865df29b90736558d6c98c2031208/Brotli-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f4bf76817c14aa98cc6697ac02f3972cb8c3da93e9ef16b9c66573a68014f91", size = 2944152 },
{ url = "https://files.pythonhosted.org/packages/ab/fb/0517cea182219d6768113a38167ef6d4eb157a033178cc938033a552ed6d/Brotli-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0c5516f0aed654134a2fc936325cc2e642f8a0e096d075209672eb321cff408", size = 2919252 },
{ url = "https://files.pythonhosted.org/packages/c7/53/73a3431662e33ae61a5c80b1b9d2d18f58dfa910ae8dd696e57d39f1a2f5/Brotli-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c3020404e0b5eefd7c9485ccf8393cfb75ec38ce75586e046573c9dc29967a0", size = 2845955 },
{ url = "https://files.pythonhosted.org/packages/55/ac/bd280708d9c5ebdbf9de01459e625a3e3803cce0784f47d633562cf40e83/Brotli-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ed11165dd45ce798d99a136808a794a748d5dc38511303239d4e2363c0695dc", size = 2914304 },
{ url = "https://files.pythonhosted.org/packages/76/58/5c391b41ecfc4527d2cc3350719b02e87cb424ef8ba2023fb662f9bf743c/Brotli-1.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180", size = 2814452 },
{ url = "https://files.pythonhosted.org/packages/c7/4e/91b8256dfe99c407f174924b65a01f5305e303f486cc7a2e8a5d43c8bec3/Brotli-1.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248", size = 2938751 },
{ url = "https://files.pythonhosted.org/packages/5a/a6/e2a39a5d3b412938362bbbeba5af904092bf3f95b867b4a3eb856104074e/Brotli-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966", size = 2933757 },
{ url = "https://files.pythonhosted.org/packages/13/f0/358354786280a509482e0e77c1a5459e439766597d280f28cb097642fc26/Brotli-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:87a3044c3a35055527ac75e419dfa9f4f3667a1e887ee80360589eb8c90aabb9", size = 2936146 },
{ url = "https://files.pythonhosted.org/packages/80/f7/daf538c1060d3a88266b80ecc1d1c98b79553b3f117a485653f17070ea2a/Brotli-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c5529b34c1c9d937168297f2c1fde7ebe9ebdd5e121297ff9c043bdb2ae3d6fb", size = 2848055 },
{ url = "https://files.pythonhosted.org/packages/ad/cf/0eaa0585c4077d3c2d1edf322d8e97aabf317941d3a72d7b3ad8bce004b0/Brotli-1.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ca63e1890ede90b2e4454f9a65135a4d387a4585ff8282bb72964fab893f2111", size = 3035102 },
{ url = "https://files.pythonhosted.org/packages/d8/63/1c1585b2aa554fe6dbce30f0c18bdbc877fa9a1bf5ff17677d9cca0ac122/Brotli-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e79e6520141d792237c70bcd7a3b122d00f2613769ae0cb61c52e89fd3443839", size = 2930029 },
{ url = "https://files.pythonhosted.org/packages/5f/3b/4e3fd1893eb3bbfef8e5a80d4508bec17a57bb92d586c85c12d28666bb13/Brotli-1.1.0-cp312-cp312-win32.whl", hash = "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0", size = 333276 },
{ url = "https://files.pythonhosted.org/packages/3d/d5/942051b45a9e883b5b6e98c041698b1eb2012d25e5948c58d6bf85b1bb43/Brotli-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951", size = 357255 },
{ url = "https://files.pythonhosted.org/packages/0a/9f/fb37bb8ffc52a8da37b1c03c459a8cd55df7a57bdccd8831d500e994a0ca/Brotli-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8bf32b98b75c13ec7cf774164172683d6e7891088f6316e54425fde1efc276d5", size = 815681 },
{ url = "https://files.pythonhosted.org/packages/06/b3/dbd332a988586fefb0aa49c779f59f47cae76855c2d00f450364bb574cac/Brotli-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7bc37c4d6b87fb1017ea28c9508b36bbcb0c3d18b4260fcdf08b200c74a6aee8", size = 422475 },
{ url = "https://files.pythonhosted.org/packages/bb/80/6aaddc2f63dbcf2d93c2d204e49c11a9ec93a8c7c63261e2b4bd35198283/Brotli-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c0ef38c7a7014ffac184db9e04debe495d317cc9c6fb10071f7fefd93100a4f", size = 2906173 },
@@ -203,17 +185,6 @@ dependencies = [
]
sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178 },
{ url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840 },
{ url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803 },
{ url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850 },
{ url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729 },
{ url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256 },
{ url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424 },
{ url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568 },
{ url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736 },
{ url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448 },
{ url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976 },
{ url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989 },
{ url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802 },
{ url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792 },
@@ -233,19 +204,6 @@ version = "3.4.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/16/b0/572805e227f01586461c80e0fd25d65a2115599cc9dad142fee4b747c357/charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", size = 123188 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/0a/9a/dd1e1cdceb841925b7798369a09279bd1cf183cef0f9ddf15a3a6502ee45/charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545", size = 196105 },
{ url = "https://files.pythonhosted.org/packages/d3/8c/90bfabf8c4809ecb648f39794cf2a84ff2e7d2a6cf159fe68d9a26160467/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7", size = 140404 },
{ url = "https://files.pythonhosted.org/packages/ad/8f/e410d57c721945ea3b4f1a04b74f70ce8fa800d393d72899f0a40526401f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757", size = 150423 },
{ url = "https://files.pythonhosted.org/packages/f0/b8/e6825e25deb691ff98cf5c9072ee0605dc2acfca98af70c2d1b1bc75190d/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa", size = 143184 },
{ url = "https://files.pythonhosted.org/packages/3e/a2/513f6cbe752421f16d969e32f3583762bfd583848b763913ddab8d9bfd4f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d", size = 145268 },
{ url = "https://files.pythonhosted.org/packages/74/94/8a5277664f27c3c438546f3eb53b33f5b19568eb7424736bdc440a88a31f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616", size = 147601 },
{ url = "https://files.pythonhosted.org/packages/7c/5f/6d352c51ee763623a98e31194823518e09bfa48be2a7e8383cf691bbb3d0/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b", size = 141098 },
{ url = "https://files.pythonhosted.org/packages/78/d4/f5704cb629ba5ab16d1d3d741396aec6dc3ca2b67757c45b0599bb010478/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d", size = 149520 },
{ url = "https://files.pythonhosted.org/packages/c5/96/64120b1d02b81785f222b976c0fb79a35875457fa9bb40827678e54d1bc8/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a", size = 152852 },
{ url = "https://files.pythonhosted.org/packages/84/c9/98e3732278a99f47d487fd3468bc60b882920cef29d1fa6ca460a1fdf4e6/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9", size = 150488 },
{ url = "https://files.pythonhosted.org/packages/13/0e/9c8d4cb99c98c1007cc11eda969ebfe837bbbd0acdb4736d228ccaabcd22/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1", size = 146192 },
{ url = "https://files.pythonhosted.org/packages/b2/21/2b6b5b860781a0b49427309cb8670785aa543fb2178de875b87b9cc97746/charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35", size = 95550 },
{ url = "https://files.pythonhosted.org/packages/21/5b/1b390b03b1d16c7e382b561c5329f83cc06623916aab983e8ab9239c7d5c/charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f", size = 102785 },
{ url = "https://files.pythonhosted.org/packages/38/94/ce8e6f63d18049672c76d07d119304e1e2d7c6098f0841b51c666e9f44a0/charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda", size = 195698 },
{ url = "https://files.pythonhosted.org/packages/24/2e/dfdd9770664aae179a96561cc6952ff08f9a8cd09a908f259a9dfa063568/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313", size = 140162 },
{ url = "https://files.pythonhosted.org/packages/24/4e/f646b9093cff8fc86f2d60af2de4dc17c759de9d554f130b140ea4738ca6/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9", size = 150263 },
@@ -277,16 +235,6 @@ version = "7.7.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/6b/bf/3effb7453498de9c14a81ca21e1f92e6723ce7ebdc5402ae30e4dcc490ac/coverage-7.7.1.tar.gz", hash = "sha256:199a1272e642266b90c9f40dec7fd3d307b51bf639fa0d15980dc0b3246c1393", size = 810332 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cf/b0/4eaba302a86ec3528231d7cfc954ae1929ec5d42b032eb6f5b5f5a9155d2/coverage-7.7.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:eff187177d8016ff6addf789dcc421c3db0d014e4946c1cc3fbf697f7852459d", size = 211253 },
{ url = "https://files.pythonhosted.org/packages/fd/68/21b973e6780a3f2457e31ede1aca6c2f84bda4359457b40da3ae805dcf30/coverage-7.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2444fbe1ba1889e0b29eb4d11931afa88f92dc507b7248f45be372775b3cef4f", size = 211504 },
{ url = "https://files.pythonhosted.org/packages/d1/b4/c19e9c565407664390254252496292f1e3076c31c5c01701ffacc060e745/coverage-7.7.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:177d837339883c541f8524683e227adcaea581eca6bb33823a2a1fdae4c988e1", size = 245566 },
{ url = "https://files.pythonhosted.org/packages/7b/0e/f9829cdd25e5083638559c8c267ff0577c6bab19dacb1a4fcfc1e70e41c0/coverage-7.7.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:15d54ecef1582b1d3ec6049b20d3c1a07d5e7f85335d8a3b617c9960b4f807e0", size = 242455 },
{ url = "https://files.pythonhosted.org/packages/29/57/a3ada2e50a665bf6d9851b5eb3a9a07d7e38f970bdd4d39895f311331d56/coverage-7.7.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75c82b27c56478d5e1391f2e7b2e7f588d093157fa40d53fd9453a471b1191f2", size = 244713 },
{ url = "https://files.pythonhosted.org/packages/0f/d3/f15c7d45682a73eca0611427896016bad4c8f635b0fc13aae13a01f8ed9d/coverage-7.7.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:315ff74b585110ac3b7ab631e89e769d294f303c6d21302a816b3554ed4c81af", size = 244476 },
{ url = "https://files.pythonhosted.org/packages/19/3b/64540074e256082b220e8810fd72543eff03286c59dc91976281dc0a559c/coverage-7.7.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4dd532dac197d68c478480edde74fd4476c6823355987fd31d01ad9aa1e5fb59", size = 242695 },
{ url = "https://files.pythonhosted.org/packages/8a/c1/9cad25372ead7f9395a91bb42d8ae63e6cefe7408eb79fd38797e2b763eb/coverage-7.7.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:385618003e3d608001676bb35dc67ae3ad44c75c0395d8de5780af7bb35be6b2", size = 243888 },
{ url = "https://files.pythonhosted.org/packages/66/c6/c3e6c895bc5b95ccfe4cb5838669dbe5226ee4ad10604c46b778c304d6f9/coverage-7.7.1-cp312-cp312-win32.whl", hash = "sha256:63306486fcb5a827449464f6211d2991f01dfa2965976018c9bab9d5e45a35c8", size = 213744 },
{ url = "https://files.pythonhosted.org/packages/cc/8a/6df2fcb4c3e38ec6cd7e211ca8391405ada4e3b1295695d00aa07c6ee736/coverage-7.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:37351dc8123c154fa05b7579fdb126b9f8b1cf42fd6f79ddf19121b7bdd4aa04", size = 214546 },
{ url = "https://files.pythonhosted.org/packages/ec/2a/1a254eaadb01c163b29d6ce742aa380fc5cfe74a82138ce6eb944c42effa/coverage-7.7.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:eebd927b86761a7068a06d3699fd6c20129becf15bb44282db085921ea0f1585", size = 211277 },
{ url = "https://files.pythonhosted.org/packages/cf/00/9636028365efd4eb6db71cdd01d99e59f25cf0d47a59943dbee32dd1573b/coverage-7.7.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2a79c4a09765d18311c35975ad2eb1ac613c0401afdd9cb1ca4110aeb5dd3c4c", size = 211551 },
{ url = "https://files.pythonhosted.org/packages/6f/c8/14aed97f80363f055b6cd91e62986492d9fe3b55e06b4b5c82627ae18744/coverage-7.7.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b1c65a739447c5ddce5b96c0a388fd82e4bbdff7251396a70182b1d83631019", size = 245068 },
@@ -447,14 +395,6 @@ version = "4.57.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/03/2d/a9a0b6e3a0cf6bd502e64fc16d894269011930cabfc89aee20d1635b1441/fonttools-4.57.0.tar.gz", hash = "sha256:727ece10e065be2f9dd239d15dd5d60a66e17eac11aea47d447f9f03fdbc42de", size = 3492448 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cb/98/d4bc42d43392982eecaaca117d79845734d675219680cd43070bb001bc1f/fonttools-4.57.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:889e45e976c74abc7256d3064aa7c1295aa283c6bb19810b9f8b604dfe5c7f31", size = 2751824 },
{ url = "https://files.pythonhosted.org/packages/1a/62/7168030eeca3742fecf45f31e63b5ef48969fa230a672216b805f1d61548/fonttools-4.57.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0425c2e052a5f1516c94e5855dbda706ae5a768631e9fcc34e57d074d1b65b92", size = 2283072 },
{ url = "https://files.pythonhosted.org/packages/5d/82/121a26d9646f0986ddb35fbbaf58ef791c25b59ecb63ffea2aab0099044f/fonttools-4.57.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44c26a311be2ac130f40a96769264809d3b0cb297518669db437d1cc82974888", size = 4788020 },
{ url = "https://files.pythonhosted.org/packages/5b/26/e0f2fb662e022d565bbe280a3cfe6dafdaabf58889ff86fdef2d31ff1dde/fonttools-4.57.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84c41ba992df5b8d680b89fd84c6a1f2aca2b9f1ae8a67400c8930cd4ea115f6", size = 4859096 },
{ url = "https://files.pythonhosted.org/packages/9e/44/9075e323347b1891cdece4b3f10a3b84a8f4c42a7684077429d9ce842056/fonttools-4.57.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ea1e9e43ca56b0c12440a7c689b1350066595bebcaa83baad05b8b2675129d98", size = 4964356 },
{ url = "https://files.pythonhosted.org/packages/48/28/caa8df32743462fb966be6de6a79d7f30393859636d7732e82efa09fbbb4/fonttools-4.57.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:84fd56c78d431606332a0627c16e2a63d243d0d8b05521257d77c6529abe14d8", size = 5226546 },
{ url = "https://files.pythonhosted.org/packages/f6/46/95ab0f0d2e33c5b1a4fc1c0efe5e286ba9359602c0a9907adb1faca44175/fonttools-4.57.0-cp312-cp312-win32.whl", hash = "sha256:f4376819c1c778d59e0a31db5dc6ede854e9edf28bbfa5b756604727f7f800ac", size = 2146776 },
{ url = "https://files.pythonhosted.org/packages/06/5d/1be5424bb305880e1113631f49a55ea7c7da3a5fe02608ca7c16a03a21da/fonttools-4.57.0-cp312-cp312-win_amd64.whl", hash = "sha256:57e30241524879ea10cdf79c737037221f77cc126a8cdc8ff2c94d4a522504b9", size = 2193956 },
{ url = "https://files.pythonhosted.org/packages/e9/2f/11439f3af51e4bb75ac9598c29f8601aa501902dcedf034bdc41f47dd799/fonttools-4.57.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:408ce299696012d503b714778d89aa476f032414ae57e57b42e4b92363e0b8ef", size = 2739175 },
{ url = "https://files.pythonhosted.org/packages/25/52/677b55a4c0972dc3820c8dba20a29c358197a78229daa2ea219fdb19e5d5/fonttools-4.57.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bbceffc80aa02d9e8b99f2a7491ed8c4a783b2fc4020119dc405ca14fb5c758c", size = 2276583 },
{ url = "https://files.pythonhosted.org/packages/64/79/184555f8fa77b827b9460a4acdbbc0b5952bb6915332b84c615c3a236826/fonttools-4.57.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f022601f3ee9e1f6658ed6d184ce27fa5216cee5b82d279e0f0bde5deebece72", size = 4766437 },
@@ -649,20 +589,6 @@ version = "3.10.16"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/98/c7/03913cc4332174071950acf5b0735463e3f63760c80585ef369270c2b372/orjson-3.10.16.tar.gz", hash = "sha256:d2aaa5c495e11d17b9b93205f5fa196737ee3202f000aaebf028dc9a73750f10", size = 5410415 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5d/15/67ce9d4c959c83f112542222ea3b9209c1d424231d71d74c4890ea0acd2b/orjson-3.10.16-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:6d3444abbfa71ba21bb042caa4b062535b122248259fdb9deea567969140abca", size = 249325 },
{ url = "https://files.pythonhosted.org/packages/da/2c/1426b06f30a1b9ada74b6f512c1ddf9d2760f53f61cdb59efeb9ad342133/orjson-3.10.16-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:30245c08d818fdcaa48b7d5b81499b8cae09acabb216fe61ca619876b128e184", size = 133621 },
{ url = "https://files.pythonhosted.org/packages/9e/88/18d26130954bc73bee3be10f95371ea1dfb8679e0e2c46b0f6d8c6289402/orjson-3.10.16-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0ba1d0baa71bf7579a4ccdcf503e6f3098ef9542106a0eca82395898c8a500a", size = 138270 },
{ url = "https://files.pythonhosted.org/packages/4f/f9/6d8b64fcd58fae072e80ee7981be8ba0d7c26ace954e5cd1d027fc80518f/orjson-3.10.16-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb0beefa5ef3af8845f3a69ff2a4aa62529b5acec1cfe5f8a6b4141033fd46ef", size = 132346 },
{ url = "https://files.pythonhosted.org/packages/16/3f/2513fd5bc786f40cd12af569c23cae6381aeddbefeed2a98f0a666eb5d0d/orjson-3.10.16-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6daa0e1c9bf2e030e93c98394de94506f2a4d12e1e9dadd7c53d5e44d0f9628e", size = 136845 },
{ url = "https://files.pythonhosted.org/packages/6d/42/b0e7b36720f5ab722b48e8ccf06514d4f769358dd73c51abd8728ef58d0b/orjson-3.10.16-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9da9019afb21e02410ef600e56666652b73eb3e4d213a0ec919ff391a7dd52aa", size = 138078 },
{ url = "https://files.pythonhosted.org/packages/a3/a8/d220afb8a439604be74fc755dbc740bded5ed14745ca536b304ed32eb18a/orjson-3.10.16-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:daeb3a1ee17b69981d3aae30c3b4e786b0f8c9e6c71f2b48f1aef934f63f38f4", size = 142712 },
{ url = "https://files.pythonhosted.org/packages/8c/88/7e41e9883c00f84f92fe357a8371edae816d9d7ef39c67b5106960c20389/orjson-3.10.16-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80fed80eaf0e20a31942ae5d0728849862446512769692474be5e6b73123a23b", size = 133136 },
{ url = "https://files.pythonhosted.org/packages/e9/ca/61116095307ad0be828ea26093febaf59e38596d84a9c8d765c3c5e4934f/orjson-3.10.16-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73390ed838f03764540a7bdc4071fe0123914c2cc02fb6abf35182d5fd1b7a42", size = 135258 },
{ url = "https://files.pythonhosted.org/packages/dc/1b/09493cf7d801505f094c9295f79c98c1e0af2ac01c7ed8d25b30fcb19ada/orjson-3.10.16-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a22bba012a0c94ec02a7768953020ab0d3e2b884760f859176343a36c01adf87", size = 412326 },
{ url = "https://files.pythonhosted.org/packages/ea/02/125d7bbd7f7a500190ddc8ae5d2d3c39d87ed3ed28f5b37cfe76962c678d/orjson-3.10.16-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5385bbfdbc90ff5b2635b7e6bebf259652db00a92b5e3c45b616df75b9058e88", size = 152800 },
{ url = "https://files.pythonhosted.org/packages/f9/09/7658a9e3e793d5b3b00598023e0fb6935d0e7bbb8ff72311c5415a8ce677/orjson-3.10.16-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:02c6279016346e774dd92625d46c6c40db687b8a0d685aadb91e26e46cc33e1e", size = 137516 },
{ url = "https://files.pythonhosted.org/packages/29/87/32b7a4831e909d347278101a48d4cf9f3f25901b2295e7709df1651f65a1/orjson-3.10.16-cp312-cp312-win32.whl", hash = "sha256:7ca55097a11426db80f79378e873a8c51f4dde9ffc22de44850f9696b7eb0e8c", size = 141759 },
{ url = "https://files.pythonhosted.org/packages/35/ce/81a27e7b439b807bd393585271364cdddf50dc281fc57c4feef7ccb186a6/orjson-3.10.16-cp312-cp312-win_amd64.whl", hash = "sha256:86d127efdd3f9bf5f04809b70faca1e6836556ea3cc46e662b44dab3fe71f3d6", size = 133944 },
{ url = "https://files.pythonhosted.org/packages/87/b9/ff6aa28b8c86af9526160905593a2fe8d004ac7a5e592ee0b0ff71017511/orjson-3.10.16-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:148a97f7de811ba14bc6dbc4a433e0341ffd2cc285065199fb5f6a98013744bd", size = 249289 },
{ url = "https://files.pythonhosted.org/packages/6c/81/6d92a586149b52684ab8fd70f3623c91d0e6a692f30fd8c728916ab2263c/orjson-3.10.16-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:1d960c1bf0e734ea36d0adc880076de3846aaec45ffad29b78c7f1b7962516b8", size = 133640 },
{ url = "https://files.pythonhosted.org/packages/c2/88/b72443f4793d2e16039ab85d0026677932b15ab968595fb7149750d74134/orjson-3.10.16-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a318cd184d1269f68634464b12871386808dc8b7c27de8565234d25975a7a137", size = 138286 },
@@ -694,17 +620,6 @@ version = "11.1.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f3/af/c097e544e7bd278333db77933e535098c259609c4eb3b85381109602fb5b/pillow-11.1.0.tar.gz", hash = "sha256:368da70808b36d73b4b390a8ffac11069f8a5c85f29eff1f1b01bcf3ef5b2a20", size = 46742715 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/95/20/9ce6ed62c91c073fcaa23d216e68289e19d95fb8188b9fb7a63d36771db8/pillow-11.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2062ffb1d36544d42fcaa277b069c88b01bb7298f4efa06731a7fd6cc290b81a", size = 3226818 },
{ url = "https://files.pythonhosted.org/packages/b9/d8/f6004d98579a2596c098d1e30d10b248798cceff82d2b77aa914875bfea1/pillow-11.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a85b653980faad27e88b141348707ceeef8a1186f75ecc600c395dcac19f385b", size = 3101662 },
{ url = "https://files.pythonhosted.org/packages/08/d9/892e705f90051c7a2574d9f24579c9e100c828700d78a63239676f960b74/pillow-11.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9409c080586d1f683df3f184f20e36fb647f2e0bc3988094d4fd8c9f4eb1b3b3", size = 4329317 },
{ url = "https://files.pythonhosted.org/packages/8c/aa/7f29711f26680eab0bcd3ecdd6d23ed6bce180d82e3f6380fb7ae35fcf3b/pillow-11.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7fdadc077553621911f27ce206ffcbec7d3f8d7b50e0da39f10997e8e2bb7f6a", size = 4412999 },
{ url = "https://files.pythonhosted.org/packages/c8/c4/8f0fe3b9e0f7196f6d0bbb151f9fba323d72a41da068610c4c960b16632a/pillow-11.1.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:93a18841d09bcdd774dcdc308e4537e1f867b3dec059c131fde0327899734aa1", size = 4368819 },
{ url = "https://files.pythonhosted.org/packages/38/0d/84200ed6a871ce386ddc82904bfadc0c6b28b0c0ec78176871a4679e40b3/pillow-11.1.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9aa9aeddeed452b2f616ff5507459e7bab436916ccb10961c4a382cd3e03f47f", size = 4496081 },
{ url = "https://files.pythonhosted.org/packages/84/9c/9bcd66f714d7e25b64118e3952d52841a4babc6d97b6d28e2261c52045d4/pillow-11.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3cdcdb0b896e981678eee140d882b70092dac83ac1cdf6b3a60e2216a73f2b91", size = 4296513 },
{ url = "https://files.pythonhosted.org/packages/db/61/ada2a226e22da011b45f7104c95ebda1b63dcbb0c378ad0f7c2a710f8fd2/pillow-11.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:36ba10b9cb413e7c7dfa3e189aba252deee0602c86c309799da5a74009ac7a1c", size = 4431298 },
{ url = "https://files.pythonhosted.org/packages/e7/c4/fc6e86750523f367923522014b821c11ebc5ad402e659d8c9d09b3c9d70c/pillow-11.1.0-cp312-cp312-win32.whl", hash = "sha256:cfd5cd998c2e36a862d0e27b2df63237e67273f2fc78f47445b14e73a810e7e6", size = 2291630 },
{ url = "https://files.pythonhosted.org/packages/08/5c/2104299949b9d504baf3f4d35f73dbd14ef31bbd1ddc2c1b66a5b7dfda44/pillow-11.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:a697cd8ba0383bba3d2d3ada02b34ed268cb548b369943cd349007730c92bddf", size = 2626369 },
{ url = "https://files.pythonhosted.org/packages/37/f3/9b18362206b244167c958984b57c7f70a0289bfb59a530dd8af5f699b910/pillow-11.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:4dd43a78897793f60766563969442020e90eb7847463eca901e41ba186a7d4a5", size = 2375240 },
{ url = "https://files.pythonhosted.org/packages/b3/31/9ca79cafdce364fd5c980cd3416c20ce1bebd235b470d262f9d24d810184/pillow-11.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ae98e14432d458fc3de11a77ccb3ae65ddce70f730e7c76140653048c71bfcbc", size = 3226640 },
{ url = "https://files.pythonhosted.org/packages/ac/0f/ff07ad45a1f172a497aa393b13a9d81a32e1477ef0e869d030e3c1532521/pillow-11.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cc1331b6d5a6e144aeb5e626f4375f5b7ae9934ba620c0ac6b3e43d5e683a0f0", size = 3101437 },
{ url = "https://files.pythonhosted.org/packages/08/2f/9906fca87a68d29ec4530be1f893149e0cb64a86d1f9f70a7cfcdfe8ae44/pillow-11.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:758e9d4ef15d3560214cddbc97b8ef3ef86ce04d62ddac17ad39ba87e89bd3b1", size = 4326605 },
@@ -790,20 +705,6 @@ dependencies = [
]
sdist = { url = "https://files.pythonhosted.org/packages/fc/01/f3e5ac5e7c25833db5eb555f7b7ab24cd6f8c322d3a3ad2d67a952dc0abc/pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", size = 413443 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d6/74/51c8a5482ca447871c93e142d9d4a92ead74de6c8dc5e66733e22c9bba89/pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0", size = 1893127 },
{ url = "https://files.pythonhosted.org/packages/d3/f3/c97e80721735868313c58b89d2de85fa80fe8dfeeed84dc51598b92a135e/pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef", size = 1811340 },
{ url = "https://files.pythonhosted.org/packages/9e/91/840ec1375e686dbae1bd80a9e46c26a1e0083e1186abc610efa3d9a36180/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7", size = 1822900 },
{ url = "https://files.pythonhosted.org/packages/f6/31/4240bc96025035500c18adc149aa6ffdf1a0062a4b525c932065ceb4d868/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934", size = 1869177 },
{ url = "https://files.pythonhosted.org/packages/fa/20/02fbaadb7808be578317015c462655c317a77a7c8f0ef274bc016a784c54/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6", size = 2038046 },
{ url = "https://files.pythonhosted.org/packages/06/86/7f306b904e6c9eccf0668248b3f272090e49c275bc488a7b88b0823444a4/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c", size = 2685386 },
{ url = "https://files.pythonhosted.org/packages/8d/f0/49129b27c43396581a635d8710dae54a791b17dfc50c70164866bbf865e3/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2", size = 1997060 },
{ url = "https://files.pythonhosted.org/packages/0d/0f/943b4af7cd416c477fd40b187036c4f89b416a33d3cc0ab7b82708a667aa/pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4", size = 2004870 },
{ url = "https://files.pythonhosted.org/packages/35/40/aea70b5b1a63911c53a4c8117c0a828d6790483f858041f47bab0b779f44/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3", size = 1999822 },
{ url = "https://files.pythonhosted.org/packages/f2/b3/807b94fd337d58effc5498fd1a7a4d9d59af4133e83e32ae39a96fddec9d/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4", size = 2130364 },
{ url = "https://files.pythonhosted.org/packages/fc/df/791c827cd4ee6efd59248dca9369fb35e80a9484462c33c6649a8d02b565/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57", size = 2158303 },
{ url = "https://files.pythonhosted.org/packages/9b/67/4e197c300976af185b7cef4c02203e175fb127e414125916bf1128b639a9/pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc", size = 1834064 },
{ url = "https://files.pythonhosted.org/packages/1f/ea/cd7209a889163b8dcca139fe32b9687dd05249161a3edda62860430457a5/pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9", size = 1989046 },
{ url = "https://files.pythonhosted.org/packages/bc/49/c54baab2f4658c26ac633d798dab66b4c3a9bbf47cff5284e9c182f4137a/pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b", size = 1885092 },
{ url = "https://files.pythonhosted.org/packages/41/b1/9bc383f48f8002f99104e3acff6cba1231b29ef76cfa45d1506a5cad1f84/pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b", size = 1892709 },
{ url = "https://files.pythonhosted.org/packages/10/6c/e62b8657b834f3eb2961b49ec8e301eb99946245e70bf42c8817350cbefc/pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154", size = 1811273 },
{ url = "https://files.pythonhosted.org/packages/ba/15/52cfe49c8c986e081b863b102d6b859d9defc63446b642ccbbb3742bf371/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9", size = 1823027 },
@@ -1080,17 +981,6 @@ version = "1.17.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/c3/fc/e91cc220803d7bc4db93fb02facd8461c37364151b8494762cc88b0fbcef/wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3", size = 55531 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a1/bd/ab55f849fd1f9a58ed7ea47f5559ff09741b25f00c191231f9f059c83949/wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925", size = 53799 },
{ url = "https://files.pythonhosted.org/packages/53/18/75ddc64c3f63988f5a1d7e10fb204ffe5762bc663f8023f18ecaf31a332e/wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392", size = 38821 },
{ url = "https://files.pythonhosted.org/packages/48/2a/97928387d6ed1c1ebbfd4efc4133a0633546bec8481a2dd5ec961313a1c7/wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40", size = 38919 },
{ url = "https://files.pythonhosted.org/packages/73/54/3bfe5a1febbbccb7a2f77de47b989c0b85ed3a6a41614b104204a788c20e/wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d", size = 88721 },
{ url = "https://files.pythonhosted.org/packages/25/cb/7262bc1b0300b4b64af50c2720ef958c2c1917525238d661c3e9a2b71b7b/wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b", size = 80899 },
{ url = "https://files.pythonhosted.org/packages/2a/5a/04cde32b07a7431d4ed0553a76fdb7a61270e78c5fd5a603e190ac389f14/wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98", size = 89222 },
{ url = "https://files.pythonhosted.org/packages/09/28/2e45a4f4771fcfb109e244d5dbe54259e970362a311b67a965555ba65026/wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82", size = 86707 },
{ url = "https://files.pythonhosted.org/packages/c6/d2/dcb56bf5f32fcd4bd9aacc77b50a539abdd5b6536872413fd3f428b21bed/wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae", size = 79685 },
{ url = "https://files.pythonhosted.org/packages/80/4e/eb8b353e36711347893f502ce91c770b0b0929f8f0bed2670a6856e667a9/wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9", size = 87567 },
{ url = "https://files.pythonhosted.org/packages/17/27/4fe749a54e7fae6e7146f1c7d914d28ef599dacd4416566c055564080fe2/wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9", size = 36672 },
{ url = "https://files.pythonhosted.org/packages/15/06/1dbf478ea45c03e78a6a8c4be4fdc3c3bddea5c8de8a93bc971415e47f0f/wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991", size = 38865 },
{ url = "https://files.pythonhosted.org/packages/ce/b9/0ffd557a92f3b11d4c5d5e0c5e4ad057bd9eb8586615cdaf901409920b14/wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125", size = 53800 },
{ url = "https://files.pythonhosted.org/packages/c0/ef/8be90a0b7e73c32e550c73cfb2fa09db62234227ece47b0e80a05073b375/wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998", size = 38824 },
{ url = "https://files.pythonhosted.org/packages/36/89/0aae34c10fe524cce30fe5fc433210376bce94cf74d05b0d68344c8ba46e/wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5", size = 38920 },
@@ -1122,16 +1012,6 @@ version = "0.2.3.post1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/5e/7c/a8f6696e694709e2abcbccd27d05ef761e9b6efae217e11d977471555b62/zopfli-0.2.3.post1.tar.gz", hash = "sha256:96484dc0f48be1c5d7ae9f38ed1ce41e3675fd506b27c11a6607f14b49101e99", size = 175629 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/3f/ce/b6441cc01881d06e0b5883f32c44e7cc9772e0d04e3e59277f59f80b9a19/zopfli-0.2.3.post1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3f0197b6aa6eb3086ae9e66d6dd86c4d502b6c68b0ec490496348ae8c05ecaef", size = 295489 },
{ url = "https://files.pythonhosted.org/packages/93/f0/24dd708f00ae0a925bc5c9edae858641c80f6a81a516810dc4d21688a930/zopfli-0.2.3.post1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5fcfc0dc2761e4fcc15ad5d273b4d58c2e8e059d3214a7390d4d3c8e2aee644e", size = 163010 },
{ url = "https://files.pythonhosted.org/packages/65/57/0378eeeb5e3e1e83b1b0958616b2bf954f102ba5b0755b9747dafbd8cb72/zopfli-0.2.3.post1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cac2b37ab21c2b36a10b685b1893ebd6b0f83ae26004838ac817680881576567", size = 823649 },
{ url = "https://files.pythonhosted.org/packages/ab/8a/3ab8a616d4655acf5cf63c40ca84e434289d7d95518a1a42d28b4a7228f8/zopfli-0.2.3.post1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d5ab297d660b75c159190ce6d73035502310e40fd35170aed7d1a1aea7ddd65", size = 826557 },
{ url = "https://files.pythonhosted.org/packages/ed/4d/7f6820af119c4fec6efaf007bffee7bc9052f695853a711a951be7afd26b/zopfli-0.2.3.post1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ba214f4f45bec195ee8559651154d3ac2932470b9d91c5715fc29c013349f8c", size = 851127 },
{ url = "https://files.pythonhosted.org/packages/e1/db/1ef5353ab06f9f2fb0c25ed0cddf1418fe275cc2ee548bc4a29340c44fe1/zopfli-0.2.3.post1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c1e0ed5d84ffa2d677cc9582fc01e61dab2e7ef8b8996e055f0a76167b1b94df", size = 1754183 },
{ url = "https://files.pythonhosted.org/packages/39/03/44f8f39950354d330fa798e4bab1ac8e38ec787d3fde25d5b9c7770065a2/zopfli-0.2.3.post1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bfa1eb759e07d8b7aa7a310a2bc535e127ee70addf90dc8d4b946b593c3e51a8", size = 1905945 },
{ url = "https://files.pythonhosted.org/packages/74/7b/94b920c33cc64255f59e3cfc77c829b5c6e60805d189baeada728854a342/zopfli-0.2.3.post1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cd2c002f160502608dcc822ed2441a0f4509c52e86fcfd1a09e937278ed1ca14", size = 1835885 },
{ url = "https://files.pythonhosted.org/packages/ad/89/c869ac844351e285a6165e2da79b715b0619a122e3160d183805adf8ab45/zopfli-0.2.3.post1-cp312-cp312-win32.whl", hash = "sha256:7be5cc6732eb7b4df17305d8a7b293223f934a31783a874a01164703bc1be6cd", size = 82743 },
{ url = "https://files.pythonhosted.org/packages/29/e6/c98912fd3a589d8a7316c408fd91519f72c237805c4400b753e3942fda0b/zopfli-0.2.3.post1-cp312-cp312-win_amd64.whl", hash = "sha256:4e50ffac74842c1c1018b9b73875a0d0a877c066ab06bf7cccbaa84af97e754f", size = 99403 },
{ url = "https://files.pythonhosted.org/packages/2b/24/0e552e2efce9a20625b56e9609d1e33c2966be33fc008681121ec267daec/zopfli-0.2.3.post1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ecb7572df5372abce8073df078207d9d1749f20b8b136089916a4a0868d56051", size = 295485 },
{ url = "https://files.pythonhosted.org/packages/08/83/b2564369fb98797a617fe2796097b1d719a4937234375757ad2a3febc04b/zopfli-0.2.3.post1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a1cf720896d2ce998bc8e051d4b4ce0d8bec007aab6243102e8e1d22a0b2fb3f", size = 163000 },
{ url = "https://files.pythonhosted.org/packages/3c/55/81d419739c2aab35e19b58bce5498dcb58e6446e5eb69f2d3c748b1c9151/zopfli-0.2.3.post1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5aad740b4d4fcbaaae4887823925166ffd062db3b248b3f432198fc287381d1a", size = 823699 },

View File

@@ -14,6 +14,7 @@ from boto3.dynamodb.types import TypeDeserializer, TypeSerializer
from botocore.exceptions import ClientError
from .dateutils import now, timestamp
from .funcs import omit
TZ = os.getenv('TZ', 'UTC')
PK = os.getenv('DYNAMODB_PARTITION_KEY', 'pk')
@@ -124,6 +125,44 @@ else:
self.delimiter = delimiter
if TYPE_CHECKING:
@dataclass
class SortKey(str):
sk: str
table_name: str | None = None
else:
class SortKey(str):
def __new__(cls, sk: str, *, table_name: str | None = None) -> str:
return super().__new__(cls, sk)
def __init__(self, sk: str, *, table_name: str | None = None) -> None:
# __init__ is used to store the parameters for later reference.
# For immutable types like str, __init__ cannot change the instance's value.
self.sk = sk
self.table_name = table_name
@dataclass
class TransactKey:
"""
Example
-------
>>> TransactKey('e9bb7dc6-c7b2-4d34-8931-d298353758ec')
... + SortKey('0')
... + SortKey('tenant')
"""
pk: str
sk: tuple[SortKey, ...] = ()
def __add__(self, sk: SortKey) -> 'TransactKey':
if isinstance(sk, SortKey):
return TransactKey(pk=self.pk, sk=self.sk + (sk,))
raise TypeError('Can only add a SortKey to a TransactKey')
class Key(ABC, dict):
@abstractmethod
def expr_attr_name(self) -> dict: ...
@@ -485,7 +524,7 @@ class DynamoDBPersistenceLayer:
else:
return True
def transact_get_items(self, transact_items: TransactItems) -> list[dict]:
def transact_get_items(self, transact_items: TransactItems) -> list[dict[str, Any]]:
try:
response = self.dynamodb_client.transact_get_items(
TransactItems=transact_items.items
@@ -521,36 +560,6 @@ class PaginatedResult(TypedDict):
class DynamoDBCollection:
"""
Example
-------
**Get an item using a composed sort key**
collect = DynamoDBCollection(...)
collect.get_item(
KeyPair(
'b3511b5a-cb32-4833-a373-f8223f2088d4',
ComposeKey('sergio@somosbeta.com.br', prefix='emails'),
),
)
**Get items using a composed partition key**
collect = DynamoDBCollection(...)
collect.get_items(
PartitionKey(
ComposeKey('b3511b5a-cb32-4833-a373-f8223f2088d4', prefix='logs')
),
)
**Get items using a key pair**
collect = DynamoDBCollection(...)
collect.get_items(
KeyPair('b3511b5a-cb32-4833-a373-f8223f2088d4', 'emails'),
)
"""
def __init__(
self,
persistence_layer: DynamoDBPersistenceLayer,
@@ -572,6 +581,45 @@ class DynamoDBCollection:
default: Any = None,
delimiter: str = '#',
) -> Any:
"""Get an item with the given key.
Example
-------
**Get an item using a composed sort key**
collect = DynamoDBCollection(...)
collect.get_item(
KeyPair(
'b3511b5a-cb32-4833-a373-f8223f2088d4',
ComposeKey('username@domain.com', prefix='emails'),
),
)
Parameters
----------
key : Key
Key of the item to be retrieved.
path_spec : str, optional
A path specification for nested data extraction, default is None.
raise_on_error : bool, optional
If True, raises an exception when the item is not found, default is True.
exception_cls : Type[Exception], optional
Exception class to be used if the item is not found, default is MissingError.
default : Any, optional
Default value returned if the item is not found, default is None.
delimiter : str, optional
Delimiter used in key composition, default is '#'.
Returns
-------
Any
Data of the retrieved item or the default value if not found.
Raises
------
Exception
Raises the provided exception if the item is not found and raise_on_error is True.
"""
exc_cls = exception_cls or self.exception_cls
data = self.persistence_layer.get_item(key)
@@ -592,6 +640,22 @@ class DynamoDBCollection:
ttl: int | datetime | None = None,
**kwargs: Any,
) -> bool:
"""Creates a new item, or replaces an old item with a new item.
Parameters
----------
key : Key
Key for the item to be inserted or updated.
ttl : int or datetime, optional
Time-to-live for the item, specified as a timestamp integer or datetime object, default is None.
**kwargs
Additional data to be stored with the item.
Returns
-------
bool
True if the operation is successful, False otherwise.
"""
now_ = now(self.tz)
if isinstance(ttl, int):
@@ -620,6 +684,24 @@ class DynamoDBCollection:
expr_attr_names: dict | None = None,
expr_attr_values: dict | None = None,
) -> bool:
"""Deletes a single item in a table by key.
Parameters
----------
key : Key
Key of the item to be deleted.
cond_expr : str, optional
Conditional expression for deletion, default is None.
expr_attr_names : dict, optional
Mapping of attribute names for the expression, default is None.
expr_attr_values : dict, optional
Mapping of attribute values for the expression, default is None.
Returns
-------
bool
True if the item is successfully deleted, False otherwise.
"""
return self.persistence_layer.delete_item(
key=key,
cond_expr=cond_expr,
@@ -627,7 +709,57 @@ class DynamoDBCollection:
expr_attr_values=expr_attr_values,
)
def get_items(
def get_items(self, key: TransactKey) -> dict[str, Any]:
"""Get multiple items via a transaction based on the provided TransactKey.
Example
-------
**Get items using chained sort keys**
key = TransactKey('b3511b5a-cb32-4833-a373-f8223f2088d4') + SortKey('sk-1') + SortKey('sk-2')
collect = DynamoDBCollection(...)
items = collect.get_items(key)
Parameters
----------
key : TransactKey
A TransactKey instance that contains a partition key and one or more sort keys.
If no sort key is provided, the transaction is skipped.
Returns
-------
dict[str, Any]
A dict of items retrieved from the transaction.
"""
# If no sort key is provided, the query is skipped
if not key.sk:
return {}
table_name = self.persistence_layer.table_name
transact = TransactItems(table_name)
# Add a get operation for each sort key for the transaction
for sk in key.sk:
transact.get(
key=KeyPair(key.pk, sk),
table_name=sk.table_name,
)
data, *rest = self.persistence_layer.transact_get_items(transact)
return data | {
k: omit(
(
PK,
SK,
),
item,
)
for k, item in zip(key.sk[1:], rest)
if item
}
def query(
self,
key: PartitionKey | KeyPair,
*,
@@ -638,6 +770,52 @@ class DynamoDBCollection:
index_forward: bool = False,
limit: int = LIMIT,
) -> PaginatedResult:
"""Query returns all items with that partition key or key pair.
Example
-------
**Query using a composed partition key**
collect = DynamoDBCollection(...)
collect.query(
PartitionKey(
ComposeKey('b3511b5a-cb32-4833-a373-f8223f2088d4', prefix='logs')
),
)
**Query using a key pair**
collect = DynamoDBCollection(...)
collect.query(
KeyPair('b3511b5a-cb32-4833-a373-f8223f2088d4', 'emails'),
)
Parameters
----------
key : PartitionKey or KeyPair
Partition key or Key pair used for the query.
expr_attr_name : dict, optional
Additional mapping for attribute names, default is {}.
expr_attr_values : dict, optional
Additional mapping for attribute values, default is {}.
start_key : str, optional
Starting key for pagination, default is None.
filter_expr : str, optional
Filter expression for the query, default is None.
index_forward : bool, optional
Order of the results; True for ascending order, default is False.
limit : int, optional
Maximum number of items to return, default is LIMIT.
Returns
-------
PaginatedResult
Dict containing the queried items and the key for the next batch.
See Also
--------
DynamoDB.Client.query : https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/client/query.html
"""
key_cond_expr = (
'#pk = :pk AND begins_with(#sk, :sk)'
if isinstance(key, KeyPair)

View File

@@ -1,6 +1,6 @@
[project]
name = "layercake"
version = "0.1.16"
version = "0.2.0"
description = "Packages shared dependencies to optimize deployment and ensure consistency across functions."
readme = "README.md"
authors = [

View File

@@ -2,3 +2,6 @@
{"id": {"S": "5OxmMjL-ujoR5IMGegQz"}, "sk": {"S": "emails#sergio@somosbeta.com.br"}, "email_verified": {"BOOL": true}, "update_date": {"S": "2024-02-08T16:42:33.776409-03:00"}, "create_date": {"S": "2019-03-25T00:00:00-03:00"}, "email_primary": {"BOOL": true}, "mx_record_exists": {"BOOL": true}, "update_date": {"S": "2023-11-09T12:13:04.308986-03:00"}}
{"id": {"S": "logs#5OxmMjL-ujoR5IMGegQz"}, "sk": {"S": "2024-02-08T16:42:33.776409-03:00"}, "action": {"S": "OPEN_EMAIL"}}
{"id": {"S": "logs#5OxmMjL-ujoR5IMGegQz"}, "sk": {"S": "2019-03-25T00:00:00-03:00"}, "action": {"S": "CLICK_EMAIL"}}
{"id": {"S": "cJtK9SsnJhKPyxESe7g3DG"}, "sk": {"S": "0"}, "name": {"S": "EDUSEG"}, "cnpj": {"S": "15608435000190"}, "email": {"S": "org+15608435000190@users.noreply.betaeducacao.com.br"}}
{"id": {"S": "cJtK9SsnJhKPyxESe7g3DG"}, "sk": {"S": "payment_policy"}, "due_days": {"N": "90"}}
{"id": {"S": "cJtK9SsnJhKPyxESe7g3DG"}, "sk": {"S": "billing_policy"}, "billing_day": {"N": "1"}, "payment_method": {"S": "PIX"}}

View File

@@ -1,4 +1,5 @@
from datetime import datetime
from decimal import Decimal
from ipaddress import IPv4Address
import pytest
@@ -12,7 +13,9 @@ from layercake.dynamodb import (
KeyPair,
PartitionKey,
PrefixKey,
SortKey,
TransactItems,
TransactKey,
serialize,
)
@@ -189,14 +192,14 @@ def test_collection_delete_item(
)
def test_collection_get_items(
def test_collection_query(
dynamodb_seeds,
dynamodb_persistence_layer: DynamoDBPersistenceLayer,
):
collect = DynamoDBCollection(dynamodb_persistence_layer)
# This data was added from seeds
logs = collect.get_items(
logs = collect.query(
PartitionKey(
ComposeKey('5OxmMjL-ujoR5IMGegQz', prefix='logs'),
),
@@ -219,7 +222,7 @@ def test_collection_get_items(
}
# This data was added from seeds
emails = collect.get_items(
emails = collect.query(
KeyPair('5OxmMjL-ujoR5IMGegQz', PrefixKey('emails')),
)
assert emails == {
@@ -236,3 +239,27 @@ def test_collection_get_items(
],
'last_key': None,
}
def test_collection_get_items(
dynamodb_seeds,
dynamodb_persistence_layer: DynamoDBPersistenceLayer,
):
collect = DynamoDBCollection(dynamodb_persistence_layer)
doc = collect.get_items(
TransactKey('cJtK9SsnJhKPyxESe7g3DG')
+ SortKey('0')
+ SortKey('billing_policy')
+ SortKey('payment_policy')
)
assert doc == {
'sk': '0',
'name': 'EDUSEG',
'id': 'cJtK9SsnJhKPyxESe7g3DG',
'cnpj': '15608435000190',
'email': 'org+15608435000190@users.noreply.betaeducacao.com.br',
'billing_policy': {'billing_day': Decimal('1'), 'payment_method': 'PIX'},
'payment_policy': {'due_days': Decimal('90')},
}

2
layercake/uv.lock generated
View File

@@ -600,7 +600,7 @@ wheels = [
[[package]]
name = "layercake"
version = "0.1.16"
version = "0.2.0"
source = { editable = "." }
dependencies = [
{ name = "arnparse" },

View File

@@ -1,23 +1,15 @@
import meilisearch
from arnparse import arnparse
from aws_lambda_powertools.utilities.data_classes import (
DynamoDBStreamEvent,
event_source,
)
from aws_lambda_powertools.utilities.typing import LambdaContext
from meilisearch import Client as Meilisearch
from meili import Op
from settings import MEILISEARCH_API_KEY, MEILISEARCH_HOST
meili_client = meilisearch.Client(MEILISEARCH_HOST, MEILISEARCH_API_KEY)
INDEXES = {
'saladeaula_courses': 'courses',
'betaeducacao-prod-enrollments': 'enrollments',
'betaeducacao-prod-orders': 'orders',
'betaeducacao-prod-users_d2o3r5gmm4it7j': 'users',
}
meili_client = Meilisearch(MEILISEARCH_HOST, MEILISEARCH_API_KEY)
@event_source(data_class=DynamoDBStreamEvent)
@@ -26,8 +18,7 @@ def lambda_handler(event: DynamoDBStreamEvent, context: LambdaContext):
for record in event.records:
pk = record.dynamodb.keys['id'] # type: ignore
new_image = record.dynamodb.new_image # type: ignore
table_name = table_from_arn(record.event_source_arn) # type: ignore
index = INDEXES[table_name] # type: ignore
index = table_from_arn(record.event_source_arn) # type: ignore
op.append(
index,

View File

@@ -49,8 +49,6 @@ class Op:
return self.op[index][op].append(data)
def process(self) -> None: ...
class DecimalEncoder(json.JSONEncoder):
def default(self, o):

View File

@@ -24,7 +24,7 @@ Resources:
Properties:
RetentionInDays: 90
StreamIndexDocsFunction:
EventIndexDocsFunction:
Type: AWS::Serverless::Function
Properties:
Handler: events.index_docs.lambda_handler