├── .circleci └── config.yml ├── .flake8 ├── .gitignore ├── LICENSE ├── README.md ├── _kubernetes ├── base │ ├── deployment.yaml │ └── kustomization.yaml ├── overlays │ ├── development │ │ ├── deployment.yaml │ │ └── kustomization.yaml │ ├── production │ │ ├── deployment.yaml │ │ └── kustomization.yaml │ └── staging │ │ ├── deployment.yaml │ │ └── kustomization.yaml └── services │ ├── api │ ├── common │ │ ├── kustomization.yaml │ │ └── service.yaml │ ├── development │ │ └── kustomization.yaml │ ├── production │ │ └── kustomization.yaml │ └── staging │ │ └── kustomization.yaml │ └── handlers │ ├── development │ └── kustomization.yaml │ ├── production │ └── kustomization.yaml │ └── staging │ └── kustomization.yaml ├── bases └── example │ ├── consumer │ ├── __init__.py │ └── core.py │ ├── greet_api │ ├── __init__.py │ └── core.py │ ├── greet_aws_lambda │ ├── __init__.py │ └── core.py │ ├── greet_gcp_function │ ├── __init__.py │ └── core.py │ └── message_api │ ├── __init__.py │ └── core.py ├── components └── example │ ├── database │ ├── __init__.py │ ├── core.py │ └── message │ │ ├── crud.py │ │ └── model.py │ ├── dictionaries │ ├── __init__.py │ └── core.py │ ├── greeting │ ├── __init__.py │ └── core.py │ ├── kafka │ ├── __init__.py │ ├── consumer.py │ ├── core.py │ ├── parser.py │ └── producer.py │ ├── log │ ├── __init__.py │ └── core.py │ ├── message │ ├── __init__.py │ └── core.py │ └── schema │ ├── __init__.py │ └── message.py ├── development ├── __init__.py ├── ci │ ├── __init__.py │ └── utils.py ├── david.py └── kafka │ └── docker-compose.yml ├── mypy.ini ├── poetry.lock ├── poetry.toml ├── projects ├── consumer_project │ ├── poetry.lock │ └── pyproject.toml ├── message_fastapi_project │ ├── Dockerfile │ ├── README.md │ ├── poetry.lock │ └── pyproject.toml ├── my_aws_lambda_project │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── poetry.lock │ ├── pyproject.toml │ └── serverless.yml ├── my_fastapi_project │ ├── Dockerfile │ ├── README.md │ ├── kubernetes │ │ ├── development │ │ │ ├── deployment.yaml │ │ │ └── kustomization.yaml │ │ └── staging │ │ │ ├── deployment.yaml │ │ │ └── kustomization.yaml │ ├── poetry.lock │ └── pyproject.toml └── my_gcp_function_project │ ├── .gitignore │ ├── Makefile │ ├── poetry.lock │ └── pyproject.toml ├── pyproject.toml ├── test ├── bases │ └── example │ │ └── consumer │ │ ├── __init__.py │ │ └── test_core.py ├── components │ └── example │ │ ├── database │ │ ├── __init__.py │ │ └── test_core.py │ │ ├── dictionaries │ │ ├── __init__.py │ │ └── test_core.py │ │ ├── greeting │ │ ├── __init__.py │ │ └── test_core.py │ │ ├── kafka │ │ ├── __init__.py │ │ └── test_core.py │ │ └── log │ │ ├── __init__.py │ │ └── test_core.py └── conftest.py └── workspace.toml /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: '2.1' 2 | orbs: 3 | python: circleci/python@2.1.1 4 | 5 | jobs: 6 | test: 7 | executor: 8 | name: python/default 9 | tag: "3.11" 10 | steps: 11 | - checkout 12 | - python/install-packages: 13 | pkg-manager: poetry 14 | - lint 15 | - test-bricks 16 | - deploy-projects 17 | 18 | workflows: 19 | main: 20 | jobs: 21 | - test: 22 | pre-steps: 23 | - install-polylith 24 | 25 | commands: 26 | install-polylith: 27 | steps: 28 | - run: 29 | command: | 30 | poetry self add poetry-multiproject-plugin 31 | poetry self add poetry-polylith-plugin 32 | name: Install Poetry plugins 33 | test-bricks: 34 | steps: 35 | - run: 36 | command: | 37 | changes="$(poetry poly diff --bricks --short | tr -d '\n')" 38 | query="${changes//,/ or }" 39 | 40 | if [ -n "$query" ]; then 41 | poetry run pytest -k \<<< echo "$query" 42 | fi 43 | name: Run pytest 44 | lint: 45 | steps: 46 | - run: 47 | command: poetry run flake8 48 | type-check: 49 | steps: 50 | - run: 51 | command: poetry run mypy . 52 | deploy-projects: 53 | steps: 54 | - run: 55 | command: | 56 | diff="$(poetry poly diff --short | tr -d '\n')" 57 | IFS=',' projects=($diff) 58 | 59 | for project in "${projects[@]}"; do 60 | echo "The Project $project should be deployed" 61 | done 62 | name: Deploy projects 63 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 120 3 | exclude = 4 | .git, 5 | .github, 6 | __pycache__, 7 | .mypy_cache, 8 | dist, 9 | .venv, 10 | ./development/*.py, -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | .mypy_cache 4 | .venv 5 | __pycache__ 6 | 7 | .serverless 8 | node_modules 9 | 10 | dist 11 | 12 | sql_app.db 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 David Vujic 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python Polylith Example 2 | 3 | This is a repository with an example `Python` setup of the Polylith Architecture. 4 | Here you will find examples of code being shared between different kind of projects, and the developer tooling setup. 5 | 6 | ## Developer experience 7 | 8 | ### Mypy 9 | Have a look at the `mypy.ini` configuration file, to make `Mypy` work really well with this type of architecture. 10 | 11 | ``` ini 12 | [mypy] 13 | mypy_path = components, bases 14 | namespace_packages = True 15 | explicit_package_bases = True 16 | ``` 17 | 18 | #### The "loose" theme 19 | This repository is setup with the `loose` theme, a Python exclusive addition to the architecture. 20 | The theme is about the folder structure of components: 21 | 22 | `components//`, and a separate `tests` top folder. 23 | 24 | Currently, there is poor support in Mypy for the original Polylith component structure: 25 | 26 | `components/////` 27 | 28 | With the original Polylith structure, you will have to explicitly add each component path to the `mypy_path`. 29 | There is [a feature request](https://github.com/python/mypy/issues/9965) in the mypy repo about adding regex support to the `mypy_path` property. 30 | Hopefully it will be implemented in the future. :pray: 31 | 32 | ### .venv 33 | It is recommended to create the virtual environment locally, for a great code editor experience. 34 | By default, `Poetry` will create a `venv` outside of the repo. You can override that behaviour by adding a configuration in a `poetry.toml` file: 35 | 36 | ``` toml 37 | [virtualenvs] 38 | path = ".venv" 39 | in-project = true 40 | ``` 41 | 42 | ### Tooling support 43 | There's tooling support for using Polylith in Python. Have a look at this repository: 44 | [Python tools for the Polylith Architecture](https://github.com/DavidVujic/python-polylith) 45 | 46 | 47 | ### Tests 48 | 49 | Run tests with: 50 | 51 | ```bash 52 | poetry run pytest 53 | ``` 54 | 55 | ### Deployment 56 | 57 | The projects contain examples for packaging and deploying APIs and handlers with docker, 58 | AWS Lambdas and GCP functions. 59 | 60 | #### Kubernetes 61 | The _"My FastAPI project"_ includes an example setup for deploying into a __Kubernetes__ cluser, 62 | by using _kustomize_ to configure the deployments. 63 | 64 | Have a look at the [project-specific](./projects/my_fastapi_project/kubernetes) and the [shared](./_kubernetes) configurations. 65 | 66 | The configuration is structured as: 67 | - basic setup for all types of deployments 68 | - with overlays for different environments (development, staging, production) 69 | - service-specific setup, with overlays 70 | - APIs 71 | - handlers 72 | - project-specific setup, with overlays 73 | -------------------------------------------------------------------------------- /_kubernetes/base/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: app 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: app 10 | template: 11 | metadata: 12 | labels: 13 | app: app 14 | spec: 15 | containers: 16 | - name: app 17 | ports: 18 | - containerPort: 5000 19 | envFrom: 20 | - configMapRef: 21 | name: app-env 22 | -------------------------------------------------------------------------------- /_kubernetes/base/kustomization.yaml: -------------------------------------------------------------------------------- 1 | kind: Kustomization 2 | 3 | namePrefix: example-cluster- 4 | 5 | resources: 6 | - deployment.yaml 7 | 8 | configMapGenerator: 9 | - name: app-env 10 | literals: 11 | - LOG_LEVEL=info 12 | -------------------------------------------------------------------------------- /_kubernetes/overlays/development/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | 4 | metadata: 5 | name: app 6 | 7 | spec: 8 | template: 9 | spec: 10 | containers: 11 | - name: app 12 | imagePullPolicy: Never 13 | -------------------------------------------------------------------------------- /_kubernetes/overlays/development/kustomization.yaml: -------------------------------------------------------------------------------- 1 | kind: Kustomization 2 | 3 | namePrefix: development- 4 | 5 | resources: 6 | - ../../base 7 | 8 | patches: 9 | - path: deployment.yaml 10 | 11 | configMapGenerator: 12 | - name: app-env 13 | behavior: merge 14 | literals: 15 | - ENV=development 16 | - LOG_LEVEL=debug 17 | -------------------------------------------------------------------------------- /_kubernetes/overlays/production/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | 4 | metadata: 5 | name: app 6 | 7 | spec: 8 | template: 9 | spec: 10 | containers: 11 | - name: app 12 | imagePullPolicy: Always 13 | -------------------------------------------------------------------------------- /_kubernetes/overlays/production/kustomization.yaml: -------------------------------------------------------------------------------- 1 | kind: Kustomization 2 | 3 | namePrefix: production- 4 | 5 | resources: 6 | - ../../base 7 | 8 | patches: 9 | - path: deployment.yaml 10 | 11 | configMapGenerator: 12 | - name: app-env 13 | behavior: merge 14 | literals: 15 | - ENV=production 16 | -------------------------------------------------------------------------------- /_kubernetes/overlays/staging/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | 4 | metadata: 5 | name: app 6 | 7 | spec: 8 | template: 9 | spec: 10 | containers: 11 | - name: app 12 | imagePullPolicy: IfNotPresent 13 | -------------------------------------------------------------------------------- /_kubernetes/overlays/staging/kustomization.yaml: -------------------------------------------------------------------------------- 1 | kind: Kustomization 2 | 3 | namePrefix: staging- 4 | 5 | resources: 6 | - ../../base 7 | 8 | patches: 9 | - path: deployment.yaml 10 | 11 | configMapGenerator: 12 | - name: app-env 13 | behavior: merge 14 | literals: 15 | - ENV=staging 16 | -------------------------------------------------------------------------------- /_kubernetes/services/api/common/kustomization.yaml: -------------------------------------------------------------------------------- 1 | kind: Kustomization 2 | 3 | resources: 4 | - service.yaml 5 | 6 | -------------------------------------------------------------------------------- /_kubernetes/services/api/common/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: app 5 | spec: 6 | selector: 7 | app: app 8 | ports: 9 | - name: http 10 | port: 80 11 | targetPort: 8000 12 | -------------------------------------------------------------------------------- /_kubernetes/services/api/development/kustomization.yaml: -------------------------------------------------------------------------------- 1 | kind: Kustomization 2 | 3 | namePrefix: api- 4 | 5 | resources: 6 | - ../common 7 | - ../../../overlays/development 8 | -------------------------------------------------------------------------------- /_kubernetes/services/api/production/kustomization.yaml: -------------------------------------------------------------------------------- 1 | kind: Kustomization 2 | 3 | namePrefix: api- 4 | 5 | resources: 6 | - ../common 7 | - ../../../overlays/production 8 | -------------------------------------------------------------------------------- /_kubernetes/services/api/staging/kustomization.yaml: -------------------------------------------------------------------------------- 1 | kind: Kustomization 2 | 3 | namePrefix: api- 4 | 5 | resources: 6 | - ../common 7 | - ../../../overlays/staging 8 | -------------------------------------------------------------------------------- /_kubernetes/services/handlers/development/kustomization.yaml: -------------------------------------------------------------------------------- 1 | kind: Kustomization 2 | 3 | resources: 4 | - ../../../overlays/development 5 | -------------------------------------------------------------------------------- /_kubernetes/services/handlers/production/kustomization.yaml: -------------------------------------------------------------------------------- 1 | kind: Kustomization 2 | 3 | resources: 4 | - ../../../overlays/production 5 | -------------------------------------------------------------------------------- /_kubernetes/services/handlers/staging/kustomization.yaml: -------------------------------------------------------------------------------- 1 | kind: Kustomization 2 | 3 | resources: 4 | - ../../../overlays/staging 5 | -------------------------------------------------------------------------------- /bases/example/consumer/__init__.py: -------------------------------------------------------------------------------- 1 | from example.consumer import core 2 | 3 | __all__ = ["core"] 4 | -------------------------------------------------------------------------------- /bases/example/consumer/core.py: -------------------------------------------------------------------------------- 1 | from example import kafka, log 2 | 3 | 4 | logger = log.get_logger("Consumer-app-logger") 5 | 6 | 7 | def parse_message(topic: str, key: str, value: str) -> None: 8 | logger.info(f"Consumed message with topic={topic}, key={key}, value={value}") 9 | 10 | 11 | def main() -> None: 12 | topic = kafka.get_topic("message") 13 | 14 | kafka.consumer.consume(topic, parse_message) 15 | -------------------------------------------------------------------------------- /bases/example/greet_api/__init__.py: -------------------------------------------------------------------------------- 1 | from example.greet_api import core 2 | 3 | __all__ = ["core"] 4 | -------------------------------------------------------------------------------- /bases/example/greet_api/core.py: -------------------------------------------------------------------------------- 1 | from example import greeting 2 | from example.log import get_logger 3 | from fastapi import FastAPI 4 | 5 | logger = get_logger("greet-FastAPI-logger") 6 | app = FastAPI() 7 | 8 | 9 | @app.get("/") 10 | def root() -> dict: 11 | logger.info("The FastAPI root endpoint was called.") 12 | logger.debug("This is a debug message") 13 | 14 | return {"message": greeting.hello_world()} 15 | -------------------------------------------------------------------------------- /bases/example/greet_aws_lambda/__init__.py: -------------------------------------------------------------------------------- 1 | from example.greet_aws_lambda import core 2 | 3 | __all__ = ["core"] 4 | -------------------------------------------------------------------------------- /bases/example/greet_aws_lambda/core.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from example import greeting 4 | from example.log import get_logger 5 | 6 | logger = get_logger("greet-aws-lambda-logger") 7 | 8 | 9 | def handler(event: dict, context: dict) -> dict: 10 | logger.info("The Lambda handler was invoked.") 11 | 12 | body = {"message": greeting.hello_world()} 13 | 14 | return { 15 | "statusCode": 200, 16 | "headers": {"Content-Type": "application/json"}, 17 | "body": json.dumps(body), 18 | } 19 | -------------------------------------------------------------------------------- /bases/example/greet_gcp_function/__init__.py: -------------------------------------------------------------------------------- 1 | from example.greet_gcp_function.core import handler 2 | 3 | __all__ = ["handler"] 4 | -------------------------------------------------------------------------------- /bases/example/greet_gcp_function/core.py: -------------------------------------------------------------------------------- 1 | import functions_framework 2 | from example import greeting 3 | from example.log import get_logger 4 | 5 | logger = get_logger("greet-gcp-function-logger") 6 | 7 | 8 | @functions_framework.http 9 | def handler(_request): 10 | return greeting.hello_world() 11 | -------------------------------------------------------------------------------- /bases/example/message_api/__init__.py: -------------------------------------------------------------------------------- 1 | from example.message_api import core 2 | 3 | __all__ = ["core"] 4 | -------------------------------------------------------------------------------- /bases/example/message_api/core.py: -------------------------------------------------------------------------------- 1 | from example import log, message 2 | from example.schema import Message 3 | from fastapi import Body, FastAPI 4 | 5 | from example.database import Base, engine 6 | 7 | logger = log.get_logger("message-FastAPI-logger") 8 | app = FastAPI() 9 | 10 | Base.metadata.create_all(bind=engine) 11 | 12 | 13 | @app.post("/message/", response_model=int) 14 | def create(content: str = Body()): 15 | logger.info(f"Creating a message with content={content}") 16 | 17 | return message.create(content) 18 | 19 | 20 | @app.get("/message/{message_id}", response_model=Message) 21 | def read(message_id: int): 22 | logger.info(f"Fetching message with id={message_id}") 23 | 24 | return message.read(message_id) 25 | 26 | 27 | @app.put("/message/{message_id}", response_model=None) 28 | def update(message_id: int, content: str = Body()): 29 | logger.info(f"Updating message with id={message_id}") 30 | 31 | return message.update(message_id, content) 32 | 33 | 34 | @app.post("/message/{message_id}", response_model=None) 35 | def delete(message_id: int): 36 | logger.info(f"Deleting message with id={message_id}") 37 | 38 | return message.delete(message_id) 39 | -------------------------------------------------------------------------------- /components/example/database/__init__.py: -------------------------------------------------------------------------------- 1 | from example.database import message 2 | from example.database.core import Base, Session, engine 3 | 4 | __all__ = ["Base", "Session", "engine", "message"] 5 | -------------------------------------------------------------------------------- /components/example/database/core.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | from sqlalchemy.orm import declarative_base, sessionmaker 3 | 4 | DATABASE_URL = "sqlite:///./sql_app.db" 5 | DATABASE_ARGS = {"check_same_thread": False} 6 | 7 | engine = create_engine(DATABASE_URL, connect_args=DATABASE_ARGS) 8 | 9 | Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) 10 | 11 | Base = declarative_base() 12 | -------------------------------------------------------------------------------- /components/example/database/message/crud.py: -------------------------------------------------------------------------------- 1 | from example.database.message.model import Message 2 | from sqlalchemy import select 3 | from sqlalchemy.orm import Session 4 | 5 | 6 | def create(session: Session, content: str) -> Message: 7 | data = Message(content=content) 8 | 9 | session.add(data) 10 | session.flush() 11 | 12 | return data 13 | 14 | 15 | def read(session: Session, message_id: int) -> Message | None: 16 | query = select(Message).where(Message.id == message_id) 17 | 18 | return session.execute(query).scalar() 19 | 20 | 21 | def update(session: Session, existing: Message, content: str) -> None: 22 | existing.content = content 23 | 24 | session.add(existing) 25 | 26 | 27 | def delete(session: Session, message_id: int) -> None: 28 | existing = read(session, message_id) 29 | 30 | session.delete(existing) 31 | -------------------------------------------------------------------------------- /components/example/database/message/model.py: -------------------------------------------------------------------------------- 1 | from example.database import Base 2 | from sqlalchemy import Integer, String 3 | from sqlalchemy.orm import Mapped, mapped_column 4 | 5 | 6 | class Message(Base): 7 | __tablename__ = "messages" 8 | 9 | id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True) 10 | content: Mapped[str] = mapped_column(String, unique=False) 11 | -------------------------------------------------------------------------------- /components/example/dictionaries/__init__.py: -------------------------------------------------------------------------------- 1 | from example.dictionaries.core import omit, pick 2 | 3 | __all__ = ["pick", "omit"] 4 | -------------------------------------------------------------------------------- /components/example/dictionaries/core.py: -------------------------------------------------------------------------------- 1 | """ 2 | Dictionary helper functions 3 | 4 | The pick and omit functions are similar to select-keys and dissoc in Clojure, 5 | and I have borrowed the naming from the JavaScript equivalents in the Lodash.js library. 6 | 7 | """ 8 | 9 | 10 | def pick(data: dict, keys: set) -> dict: 11 | return {k: v for k, v in data.items() if k in keys} 12 | 13 | 14 | def omit(data: dict, keys: set) -> dict: 15 | return {k: v for k, v in data.items() if k not in keys} 16 | -------------------------------------------------------------------------------- /components/example/greeting/__init__.py: -------------------------------------------------------------------------------- 1 | from example.greeting.core import hello_world 2 | 3 | __all__ = ["hello_world"] 4 | -------------------------------------------------------------------------------- /components/example/greeting/core.py: -------------------------------------------------------------------------------- 1 | def hello_world() -> str: 2 | return "HELLO WORLD" 3 | -------------------------------------------------------------------------------- /components/example/kafka/__init__.py: -------------------------------------------------------------------------------- 1 | from example.kafka import consumer, producer 2 | from example.kafka.core import get_topic 3 | 4 | __all__ = ["consumer", "producer", "get_topic"] 5 | -------------------------------------------------------------------------------- /components/example/kafka/consumer.py: -------------------------------------------------------------------------------- 1 | """ 2 | A simplistic example implementation of a Kafka Consumer, 3 | with the basics as described in the Confluent Python Client Getting Started guides. 4 | """ 5 | 6 | from functools import cache 7 | from typing import Callable 8 | 9 | from confluent_kafka import Consumer 10 | from example import log 11 | from example.kafka.core import fetch_consumer_config, fetch_default_config 12 | from example.kafka.parser import parse_message 13 | 14 | logger = log.get_logger("Kafka-Consumer-logger") 15 | 16 | 17 | @cache 18 | def get_consumer() -> Consumer: 19 | logger.info("a new instance of a Kafka Consumer") 20 | 21 | config = fetch_default_config() | fetch_consumer_config() 22 | 23 | return Consumer(config) 24 | 25 | 26 | def consume(topic: str, callback: Callable) -> None: 27 | consumer = get_consumer() 28 | 29 | consumer.subscribe([topic]) 30 | 31 | try: 32 | while True: 33 | msg = consumer.poll(1.0) 34 | 35 | if msg is None: 36 | continue 37 | 38 | if msg.error(): 39 | logger.error(msg.error()) 40 | else: 41 | topic, key, value = parse_message(msg) 42 | callback(topic, key, value) 43 | except KeyboardInterrupt: 44 | pass 45 | finally: 46 | consumer.close() 47 | -------------------------------------------------------------------------------- /components/example/kafka/core.py: -------------------------------------------------------------------------------- 1 | """ 2 | In a Real-World scenario, you likely want to fetch the Kafka-specific 3 | configs depending on the running environment (such as environment variables for dev, test or prod). 4 | 5 | In this simplistic example, values returned from these functions are fixed. 6 | """ 7 | 8 | import os 9 | 10 | 11 | def fetch_default_config() -> dict: 12 | return {"bootstrap.servers": "localhost:9092"} 13 | 14 | 15 | def fetch_consumer_config() -> dict: 16 | return {"group.id": "python_example_group_1", "auto.offset.reset": "earliest"} 17 | 18 | 19 | def is_enabled() -> bool: 20 | """Check if Kafka is enabled or not. 21 | 22 | Note: 23 | This is to keep the example code simplistic, 24 | being able to run the CRUD code without a running Kafka server. 25 | """ 26 | return os.environ.get("kafka", "") == "enabled" 27 | 28 | 29 | def get_topic(category: str) -> str: 30 | topics = {"message": os.getenv("KAFKA_MESSAGE_TOPIC", "message")} 31 | 32 | return topics[category] 33 | -------------------------------------------------------------------------------- /components/example/kafka/parser.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Tuple 2 | 3 | 4 | def parse_message(msg: Any) -> Tuple[str, str, str]: 5 | topic = msg.topic() 6 | key = msg.key().decode("utf-8") 7 | value = msg.value().decode("utf-8") 8 | 9 | return topic, key, value 10 | -------------------------------------------------------------------------------- /components/example/kafka/producer.py: -------------------------------------------------------------------------------- 1 | """ 2 | A simplistic example implementation of a Kafka Producer, 3 | with the basics as described in the Confluent Python Client Getting Started guides. 4 | """ 5 | 6 | from functools import cache 7 | 8 | from confluent_kafka import Producer 9 | from example import log 10 | from example.kafka.core import fetch_default_config, is_enabled 11 | from example.kafka.parser import parse_message 12 | 13 | logger = log.get_logger("Kafka-Producer-logger") 14 | 15 | 16 | def _acked(err, msg): 17 | if err: 18 | logger.error(err) 19 | return 20 | 21 | topic, key, value = parse_message(msg) 22 | 23 | logger.info(f"Produced: topic={topic}: key={key} value={value}") 24 | 25 | 26 | @cache 27 | def get_producer() -> Producer: 28 | logger.info("a new instance of a Kafka Producer") 29 | 30 | config = fetch_default_config() 31 | 32 | return Producer(config) 33 | 34 | 35 | def produce(topic: str, key: str, value: str) -> None: 36 | if not is_enabled(): 37 | return 38 | 39 | producer = get_producer() 40 | 41 | producer.produce(topic, value, key, callback=_acked) 42 | 43 | producer.poll(10000) 44 | producer.flush() 45 | -------------------------------------------------------------------------------- /components/example/log/__init__.py: -------------------------------------------------------------------------------- 1 | from example.log.core import get_logger 2 | 3 | __all__ = ["get_logger"] 4 | -------------------------------------------------------------------------------- /components/example/log/core.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | 4 | fmt = "%(asctime)s [%(levelname)s] %(name)s: %(message)s" 5 | 6 | 7 | def get_level() -> str: 8 | level = os.getenv("LOG_LEVEL", "INFO") 9 | 10 | return str.upper(level) 11 | 12 | 13 | def get_logger(name) -> logging.Logger: 14 | logger = logging.getLogger(name) 15 | 16 | if not logger.hasHandlers(): 17 | handler = logging.StreamHandler() 18 | formatter = logging.Formatter(fmt) 19 | 20 | handler.setFormatter(formatter) 21 | logger.addHandler(handler) 22 | 23 | logger.setLevel(get_level()) 24 | 25 | return logger 26 | -------------------------------------------------------------------------------- /components/example/message/__init__.py: -------------------------------------------------------------------------------- 1 | from example.message.core import create, read, update, delete 2 | 3 | __all__ = ["create", "read", "update", "delete"] 4 | -------------------------------------------------------------------------------- /components/example/message/core.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from example import kafka 4 | from example.database import Session 5 | from example.database.message import crud 6 | from example.dictionaries import pick 7 | from example.schema import Message 8 | 9 | 10 | def notify(message: Message) -> None: 11 | data = pick(vars(message), {"id", "content"}) 12 | 13 | key = str(data["id"]) 14 | value = json.dumps(data) 15 | 16 | topic = kafka.get_topic("message") 17 | 18 | kafka.producer.produce(topic, key, value) 19 | 20 | 21 | def create(content: str) -> int: 22 | with Session.begin() as session: 23 | data = crud.create(session, content) 24 | 25 | notify(data) 26 | 27 | return data.id 28 | 29 | 30 | def read(message_id: int): 31 | with Session.begin() as session: 32 | return vars(crud.read(session, message_id)) 33 | 34 | 35 | def update(message_id: int, content: str) -> None: 36 | with Session.begin() as session: 37 | existing = crud.read(session, message_id) 38 | 39 | if not existing: 40 | raise ValueError() 41 | 42 | return crud.update(session, existing, content) 43 | 44 | 45 | def delete(message_id: int) -> None: 46 | with Session.begin() as session: 47 | return crud.delete(session, message_id) 48 | -------------------------------------------------------------------------------- /components/example/schema/__init__.py: -------------------------------------------------------------------------------- 1 | from example.schema.message import Message 2 | 3 | __all__ = ["Message"] 4 | -------------------------------------------------------------------------------- /components/example/schema/message.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class Message(BaseModel): 5 | id: int | None 6 | content: str | None = None 7 | 8 | class Config: 9 | orm_mode = True 10 | -------------------------------------------------------------------------------- /development/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidVujic/python-polylith-example/913cd45599b534100c5cbbf41a725b09d8cb00b3/development/__init__.py -------------------------------------------------------------------------------- /development/ci/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidVujic/python-polylith-example/913cd45599b534100c5cbbf41a725b09d8cb00b3/development/ci/__init__.py -------------------------------------------------------------------------------- /development/ci/utils.py: -------------------------------------------------------------------------------- 1 | def hello(): 2 | return "world" 3 | -------------------------------------------------------------------------------- /development/david.py: -------------------------------------------------------------------------------- 1 | from example import greeting, log 2 | 3 | logger = log.get_logger("The DEV logger") 4 | data = greeting.hello_world() 5 | 6 | logger.info(data) 7 | 8 | 9 | def start_local_for_repl_driven_development_with_jupyter_kernel(): 10 | """Dev-only FastAPI startup. 11 | Important: only for REPL Driven Development using Jupyter kernel. 12 | 13 | This will start the app in an event loop. This is useful 14 | when running the app in a Jupyter kernel and connecting clients 15 | to the kernel. 16 | """ 17 | 18 | import asyncio 19 | 20 | from example.message_api import core 21 | from uvicorn import Config, Server 22 | 23 | config = Config(core.app, host="127.0.0.1", port=8000) 24 | server = Server(config) 25 | 26 | loop = asyncio.get_running_loop() 27 | 28 | loop.create_task(server.serve()) 29 | -------------------------------------------------------------------------------- /development/kafka/docker-compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3' 3 | services: 4 | zookeeper: 5 | image: confluentinc/cp-zookeeper:7.3.0 6 | hostname: zookeeper 7 | container_name: zookeeper 8 | environment: 9 | ZOOKEEPER_CLIENT_PORT: 2181 10 | ZOOKEEPER_TICK_TIME: 2000 11 | 12 | broker: 13 | image: confluentinc/cp-kafka:7.3.0 14 | container_name: broker 15 | ports: 16 | - "9092:9092" 17 | depends_on: 18 | - zookeeper 19 | environment: 20 | KAFKA_BROKER_ID: 1 21 | KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181' 22 | KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_INTERNAL:PLAINTEXT 23 | KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092,PLAINTEXT_INTERNAL://broker:29092 24 | KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 25 | KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 26 | KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 27 | -------------------------------------------------------------------------------- /mypy.ini: -------------------------------------------------------------------------------- 1 | [mypy] 2 | mypy_path = components, bases 3 | namespace_packages = True 4 | explicit_package_bases = True 5 | 6 | [mypy-functions_framework] 7 | ignore_missing_imports = True 8 | 9 | [mypy-confluent_kafka] 10 | ignore_missing_imports = True 11 | -------------------------------------------------------------------------------- /poetry.toml: -------------------------------------------------------------------------------- 1 | [virtualenvs] 2 | path = ".venv" 3 | in-project = true -------------------------------------------------------------------------------- /projects/consumer_project/poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 2.0.0 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "confluent-kafka" 5 | version = "2.8.2" 6 | description = "Confluent's Python client for Apache Kafka" 7 | optional = false 8 | python-versions = ">=3.7" 9 | groups = ["main"] 10 | files = [ 11 | {file = "confluent_kafka-2.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2de2540246d01ec73f6ccbbe189106c97e828ff99d5803b4b629639d3fcf61bd"}, 12 | {file = "confluent_kafka-2.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8fa24b18a1dfa7afa22124a4c417c991d3a7e5639c968c5993724d0e6b55069e"}, 13 | {file = "confluent_kafka-2.8.2-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:fae2edce2e4f9b0455d60e1590421ea36e5a31562073663c39446feedf804f19"}, 14 | {file = "confluent_kafka-2.8.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:bf6cff008f407cb9c2eac6465c858402980af81355a94dc0070f6ac70b014aa5"}, 15 | {file = "confluent_kafka-2.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:835594da79e09cb239a0d9434af556d8ca6bedb4d7efc1995adf085ca44aaca6"}, 16 | {file = "confluent_kafka-2.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:958be78c89e25f2506ef39ee0251c171b9cd3f771ad7687ab56165e8e32b7df1"}, 17 | {file = "confluent_kafka-2.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:38e0c4809670d9a6a3e268b82793db90fe408a569f7215266abd27b52b7ecf3d"}, 18 | {file = "confluent_kafka-2.8.2-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:882b67c076661be252dca962fe7f26c92e8da23b6607618e6512e462750e7f83"}, 19 | {file = "confluent_kafka-2.8.2-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:fd10d521873e7d2f64c7d1bc0ee1fc27434d7bc45e50e8a8abf7e8366e38002a"}, 20 | {file = "confluent_kafka-2.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:1969bfb672a7c55d1bcacd54d3c2cf90f45dbef29a5934828d439cafded31dc9"}, 21 | {file = "confluent_kafka-2.8.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b632a230abee16b03bdfbb931eb6cdd05a3b9474066b5dcae01550a0faf7cbaf"}, 22 | {file = "confluent_kafka-2.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cd8f33fb94258b676c7c86520f572e2866405056bb31c3425d01fbe0a21f6883"}, 23 | {file = "confluent_kafka-2.8.2-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:2cb254a1d53af672cd0d9f3b34492cb5ca4dae829cecc48292afedd199312f06"}, 24 | {file = "confluent_kafka-2.8.2-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9ca5a6ddd6401684d6e7237e11efb112087e4c4c4535503e07fc3385e52b2f16"}, 25 | {file = "confluent_kafka-2.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:77eb22389c5d95a5d4b8a5713ee3f9ad084cbd19107eb80f51678f676fc3a27f"}, 26 | {file = "confluent_kafka-2.8.2-cp313-cp313-macosx_13_0_arm64.whl", hash = "sha256:0974d544bf8b0f23cae70852e53a4e7fec1af7fc83222b302f3ce8855d3ff70b"}, 27 | {file = "confluent_kafka-2.8.2-cp313-cp313-macosx_13_0_x86_64.whl", hash = "sha256:8eb18f6908aa10cb1f410b429abcb0a62d0ca0daf4386ef3784022d0779d236e"}, 28 | {file = "confluent_kafka-2.8.2-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:9171a75ef2430eb04dea4b433de7ae20db063b7cea2318cb0e6394175a153f6f"}, 29 | {file = "confluent_kafka-2.8.2-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:6ea4f733aaa2c6363adb8cd1cfeda16599642c472e479cea66c6b298325df0aa"}, 30 | {file = "confluent_kafka-2.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:60c6b77179301366410b35bbd224099a43061c983047329b69ed594f86240e7a"}, 31 | {file = "confluent_kafka-2.8.2-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:1eaf441620918600bd8dcfb0e38f2102bf735938ba4d87b057bddacd1fa46262"}, 32 | {file = "confluent_kafka-2.8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ec6c0e72c2b8d8d19209a094ddbb87579973b096f7490229aff5c0a1603aef38"}, 33 | {file = "confluent_kafka-2.8.2-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:d78deb8a443dc4ba2ed21c4902da9b78fba469b7ceeac92f4e1db739a74b512e"}, 34 | {file = "confluent_kafka-2.8.2-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:5cf86372a660e29363c9165014227fd492923887efb3fea85373bb67cbd8a1a3"}, 35 | {file = "confluent_kafka-2.8.2-cp37-cp37m-win_amd64.whl", hash = "sha256:169788daf3f6a45e50df3e8ebce5beec5ecd1387edebac181291de5d92db58c5"}, 36 | {file = "confluent_kafka-2.8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:59411423ebb9804743f4b409b352af93c003bd2bd929890744e3c95f4c76d37a"}, 37 | {file = "confluent_kafka-2.8.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:696689124df8734f6f8ed2edf7d0036d66acdff2c3915078e66b73aebef6b333"}, 38 | {file = "confluent_kafka-2.8.2-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:5c5a7490c2c593d8fb84fb10ae95ec9ec631fb229c64e307247a3d1558b7f3e7"}, 39 | {file = "confluent_kafka-2.8.2-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:5093c3d2dde81ac1dccf5355bcab4f28c8c39f3501b18d910cbdc08cb0b2b946"}, 40 | {file = "confluent_kafka-2.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:41f646f924a77e5d2dcc1d421d24130bf8e518f80043c5b740c1763bf5c79f25"}, 41 | {file = "confluent_kafka-2.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c1206376218e083a9a962c20fabb881b995b63e8ff55d2ee3408a7527de5584f"}, 42 | {file = "confluent_kafka-2.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b179d792c9ccecbb5d358db8bc16f01798f55ba3f0f281f6b2d698541489cd47"}, 43 | {file = "confluent_kafka-2.8.2-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:5e49281da59dbefc9ea0f41431e1604a629076ff9ad9cadf9258f4a57b12f968"}, 44 | {file = "confluent_kafka-2.8.2-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:356d0a27bf350da69fea80d982b777a6b87f91f4b2326b3c8b061e3a01bcdd60"}, 45 | {file = "confluent_kafka-2.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:5b4471c7ced93407c2c8ee89d7735cbc387aaa3f68707201e7351ce03f59647c"}, 46 | {file = "confluent_kafka-2.8.2.tar.gz", hash = "sha256:e8cac2a00968c587d7e7a8fbb6b2d3c2eb0d342d42fdf1fdc36c10036b944bf3"}, 47 | ] 48 | 49 | [package.extras] 50 | all = ["attrs", "attrs", "authlib", "avro (>=1.11.1,<2)", "avro (>=1.11.1,<2)", "azure-identity", "azure-identity", "azure-keyvault-keys", "azure-keyvault-keys", "boto3", "boto3 (>=1.35)", "cachetools", "cachetools", "cel-python (>=0.1.5)", "cel-python (>=0.1.5)", "confluent-kafka", "fastapi", "fastavro (<1.8.0)", "fastavro (<1.8.0)", "fastavro (<2)", "fastavro (<2)", "flake8", "google-api-core", "google-api-core", "google-auth", "google-auth", "google-cloud-kms", "google-cloud-kms", "googleapis-common-protos", "googleapis-common-protos", "hkdf (==0.0.3)", "hkdf (==0.0.3)", "httpx", "httpx (>=0.26)", "hvac", "hvac", "jsonata-python", "jsonata-python", "jsonschema", "jsonschema", "opentelemetry-distro", "opentelemetry-exporter-otlp", "orjson", "protobuf", "protobuf", "psutil", "pydantic", "pyrsistent", "pyrsistent", "pytest", "pytest-timeout", "pytest_cov", "pyyaml (>=6.0.0)", "pyyaml (>=6.0.0)", "requests", "requests", "requests-mock", "respx", "six", "sphinx", "sphinx-rtd-theme", "tink", "tink", "urllib3 (<2)", "urllib3 (<3)", "uvicorn"] 51 | avro = ["attrs", "authlib", "avro (>=1.11.1,<2)", "cachetools", "fastavro (<1.8.0)", "fastavro (<2)", "httpx (>=0.26)", "requests"] 52 | dev = ["attrs", "attrs", "authlib", "avro (>=1.11.1,<2)", "avro (>=1.11.1,<2)", "azure-identity", "azure-identity", "azure-keyvault-keys", "azure-keyvault-keys", "boto3", "boto3 (>=1.35)", "cachetools", "cachetools", "cel-python (>=0.1.5)", "cel-python (>=0.1.5)", "confluent-kafka", "fastapi", "fastavro (<1.8.0)", "fastavro (<1.8.0)", "fastavro (<2)", "fastavro (<2)", "flake8", "google-api-core", "google-api-core", "google-auth", "google-auth", "google-cloud-kms", "google-cloud-kms", "googleapis-common-protos", "googleapis-common-protos", "hkdf (==0.0.3)", "hkdf (==0.0.3)", "httpx", "httpx (>=0.26)", "hvac", "hvac", "jsonata-python", "jsonata-python", "jsonschema", "jsonschema", "orjson", "protobuf", "protobuf", "pydantic", "pyrsistent", "pyrsistent", "pytest", "pytest-timeout", "pytest_cov", "pyyaml (>=6.0.0)", "pyyaml (>=6.0.0)", "requests", "requests", "requests-mock", "respx", "six", "sphinx", "sphinx-rtd-theme", "tink", "tink", "urllib3 (<2)", "urllib3 (<3)", "uvicorn"] 53 | docs = ["attrs", "authlib", "avro (>=1.11.1,<2)", "azure-identity", "azure-keyvault-keys", "boto3 (>=1.35)", "cachetools", "cel-python (>=0.1.5)", "fastavro (<1.8.0)", "fastavro (<2)", "google-api-core", "google-auth", "google-cloud-kms", "googleapis-common-protos", "hkdf (==0.0.3)", "httpx (>=0.26)", "hvac", "jsonata-python", "jsonschema", "protobuf", "pyrsistent", "pyyaml (>=6.0.0)", "requests", "sphinx", "sphinx-rtd-theme", "tink"] 54 | examples = ["attrs", "avro (>=1.11.1,<2)", "azure-identity", "azure-keyvault-keys", "boto3", "cachetools", "cel-python (>=0.1.5)", "confluent-kafka", "fastapi", "fastavro (<1.8.0)", "fastavro (<2)", "google-api-core", "google-auth", "google-cloud-kms", "googleapis-common-protos", "hkdf (==0.0.3)", "httpx", "hvac", "jsonata-python", "jsonschema", "protobuf", "pydantic", "pyrsistent", "pyyaml (>=6.0.0)", "requests", "six", "tink", "uvicorn"] 55 | json = ["attrs", "authlib", "cachetools", "httpx (>=0.26)", "jsonschema", "pyrsistent"] 56 | protobuf = ["attrs", "authlib", "cachetools", "googleapis-common-protos", "httpx (>=0.26)", "protobuf"] 57 | rules = ["attrs", "authlib", "azure-identity", "azure-keyvault-keys", "boto3 (>=1.35)", "cachetools", "cel-python (>=0.1.5)", "google-api-core", "google-auth", "google-cloud-kms", "hkdf (==0.0.3)", "httpx (>=0.26)", "hvac", "jsonata-python", "pyyaml (>=6.0.0)", "tink"] 58 | schema-registry = ["attrs", "authlib", "cachetools", "httpx (>=0.26)"] 59 | schemaregistry = ["attrs", "authlib", "cachetools", "httpx (>=0.26)"] 60 | soaktest = ["opentelemetry-distro", "opentelemetry-exporter-otlp", "psutil"] 61 | tests = ["attrs", "authlib", "avro (>=1.11.1,<2)", "azure-identity", "azure-keyvault-keys", "boto3 (>=1.35)", "cachetools", "cel-python (>=0.1.5)", "fastavro (<1.8.0)", "fastavro (<2)", "flake8", "google-api-core", "google-auth", "google-cloud-kms", "googleapis-common-protos", "hkdf (==0.0.3)", "httpx (>=0.26)", "hvac", "jsonata-python", "jsonschema", "orjson", "protobuf", "pyrsistent", "pytest", "pytest-timeout", "pytest_cov", "pyyaml (>=6.0.0)", "requests", "requests-mock", "respx", "tink", "urllib3 (<2)", "urllib3 (<3)"] 62 | 63 | [metadata] 64 | lock-version = "2.1" 65 | python-versions = "^3.10" 66 | content-hash = "03016da1bac8cdccd07be9070770510e212500495cc606bb57408566ded6822d" 67 | -------------------------------------------------------------------------------- /projects/consumer_project/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "consumer_project" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ['David Vujic'] 6 | license = "" 7 | 8 | packages = [ 9 | {include = "example/consumer", from = "../../bases"}, 10 | {include = "example/kafka",from = "../../components"}, 11 | {include = "example/log",from = "../../components"}, 12 | ] 13 | 14 | [tool.poetry.dependencies] 15 | python = "^3.10" 16 | confluent-kafka = "^2.3.0" 17 | 18 | [tool.poetry.scripts] 19 | consumer = "example.consumer.core:main" 20 | 21 | [build-system] 22 | requires = ["poetry-core>=1.0.0"] 23 | build-backend = "poetry.core.masonry.api" 24 | -------------------------------------------------------------------------------- /projects/message_fastapi_project/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.10 2 | 3 | ARG wheel=message_fastapi_project-0.1.0-py3-none-any.whl 4 | 5 | RUN python -m pip install --upgrade pip 6 | 7 | WORKDIR /code 8 | 9 | COPY ./dist/$wheel /code/$wheel 10 | RUN pip install --no-cache-dir --upgrade /code/$wheel 11 | 12 | CMD ["uvicorn", "example.message_api.core:app", "--host", "0.0.0.0", "--port", "8000"] 13 | -------------------------------------------------------------------------------- /projects/message_fastapi_project/README.md: -------------------------------------------------------------------------------- 1 | # Example usage 2 | 3 | ## Build the project 4 | Navigate to this folder (where the `pyproject.toml` file is) 5 | 6 | Run: 7 | ``` shell 8 | poetry build-project 9 | ``` 10 | 11 | ## Build a docker image 12 | 13 | ``` shell 14 | docker build -t myimage . 15 | ``` 16 | 17 | ## Run the image 18 | 19 | ``` shell 20 | docker run -d --name mycontainer -p 8000:8000 myimage 21 | ``` 22 | 23 | The OpenAPI specification of this FastAPI app can now be accessed at http://localhost:8000/docs# 24 | 25 | -------------------------------------------------------------------------------- /projects/message_fastapi_project/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "message_fastapi_project" 3 | version = "0.1.0" 4 | 5 | description = "another example FastAPI project" 6 | authors = ["David Vujic"] 7 | packages = [ 8 | {include = "example/database", from = "../../components"}, 9 | {include = "example/message", from = "../../components"}, 10 | {include = "example/schema", from = "../../components"}, 11 | {include = "example/message_api", from = "../../bases"}, 12 | {include = "example/log",from = "../../components"}, 13 | {include = "example/kafka",from = "../../components"}, 14 | {include = "example/dictionaries",from = "../../components"}, 15 | ] 16 | 17 | [tool.poetry.dependencies] 18 | python = "^3.10" 19 | fastapi = "^0.115.12" 20 | uvicorn = {extras = ["standard"], version = "^0.27.1"} 21 | sqlalchemy = "^2.0.28" 22 | confluent-kafka = "^2.3.0" 23 | 24 | [build-system] 25 | requires = ["poetry-core>=1.0.0"] 26 | build-backend = "poetry.core.masonry.api" 27 | -------------------------------------------------------------------------------- /projects/my_aws_lambda_project/README.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | # Serverless Framework AWS Python Example 16 | 17 | This template demonstrates how to deploy a Python function running on AWS Lambda using the traditional Serverless Framework. The deployed function does not include any event definitions as well as any kind of persistence (database). For more advanced configurations check out the [examples repo](https://github.com/serverless/examples/) which includes integrations with SQS, DynamoDB or examples of functions that are triggered in `cron`-like manner. For details about configuration of specific `events`, please refer to our [documentation](https://www.serverless.com/framework/docs/providers/aws/events/). 18 | 19 | ## Usage 20 | 21 | ### Deployment 22 | 23 | In order to deploy the example, you need to run the following command: 24 | 25 | ``` 26 | $ serverless deploy 27 | ``` 28 | 29 | After running deploy, you should see output similar to: 30 | 31 | ```bash 32 | Deploying aws-python-project to stage dev (us-east-1) 33 | 34 | ✔ Service deployed to stack aws-python-project-dev (112s) 35 | 36 | functions: 37 | hello: aws-python-project-dev-hello (1.5 kB) 38 | ``` 39 | 40 | ### Invocation 41 | 42 | After successful deployment, you can invoke the deployed function by using the following command: 43 | 44 | ```bash 45 | serverless invoke --function hello 46 | ``` 47 | 48 | Which should result in response similar to the following: 49 | 50 | ```json 51 | { 52 | "statusCode": 200, 53 | "body": "{\"message\": \"Go Serverless v3.0! Your function executed successfully!\", \"input\": {}}" 54 | } 55 | ``` 56 | 57 | ### Local development 58 | 59 | You can invoke your function locally by using the following command: 60 | 61 | ```bash 62 | serverless invoke local --function hello 63 | ``` 64 | 65 | Which should result in response similar to the following: 66 | 67 | ``` 68 | { 69 | "statusCode": 200, 70 | "body": "{\"message\": \"Go Serverless v3.0! Your function executed successfully!\", \"input\": {}}" 71 | } 72 | ``` 73 | 74 | ### Bundling dependencies 75 | 76 | In case you would like to include third-party dependencies, you will need to use a plugin called `serverless-python-requirements`. You can set it up by running the following command: 77 | 78 | ```bash 79 | serverless plugin install -n serverless-python-requirements 80 | ``` 81 | 82 | Running the above will automatically add `serverless-python-requirements` to `plugins` section in your `serverless.yml` file and add it as a `devDependency` to `package.json` file. The `package.json` file will be automatically created if it doesn't exist beforehand. Now you will be able to add your dependencies to `requirements.txt` file (`Pipfile` and `pyproject.toml` is also supported but requires additional configuration) and they will be automatically injected to Lambda package during build process. For more details about the plugin's configuration, please refer to [official documentation](https://github.com/UnitedIncome/serverless-python-requirements). 83 | -------------------------------------------------------------------------------- /projects/my_aws_lambda_project/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my_aws_lambda_project", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "name": "my_aws_lambda_project", 8 | "devDependencies": { 9 | "serverless-python-requirements": "^6.1.2" 10 | } 11 | }, 12 | "node_modules/@iarna/toml": { 13 | "version": "2.2.5", 14 | "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", 15 | "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", 16 | "dev": true, 17 | "license": "ISC" 18 | }, 19 | "node_modules/2-thenable": { 20 | "version": "1.0.0", 21 | "resolved": "https://registry.npmjs.org/2-thenable/-/2-thenable-1.0.0.tgz", 22 | "integrity": "sha512-HqiDzaLDFCXkcCO/SwoyhRwqYtINFHF7t9BDRq4x90TOKNAJpiqUt9X5lQ08bwxYzc067HUywDjGySpebHcUpw==", 23 | "dev": true, 24 | "license": "ISC", 25 | "dependencies": { 26 | "d": "1", 27 | "es5-ext": "^0.10.47" 28 | } 29 | }, 30 | "node_modules/appdirectory": { 31 | "version": "0.1.0", 32 | "resolved": "https://registry.npmjs.org/appdirectory/-/appdirectory-0.1.0.tgz", 33 | "integrity": "sha512-DJ5DV8vZXBbusyiyPlH28xppwS8eAMRuuyMo88xeEcf4bV64lbLtbxRxqixZuJBXsZzLtXFmA13GwVjJc7vdQw==", 34 | "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", 35 | "dev": true, 36 | "license": "MIT" 37 | }, 38 | "node_modules/balanced-match": { 39 | "version": "1.0.2", 40 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 41 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 42 | "dev": true, 43 | "license": "MIT" 44 | }, 45 | "node_modules/bluebird": { 46 | "version": "3.7.2", 47 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", 48 | "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", 49 | "dev": true, 50 | "license": "MIT" 51 | }, 52 | "node_modules/camelcase": { 53 | "version": "5.3.1", 54 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 55 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 56 | "dev": true, 57 | "license": "MIT", 58 | "engines": { 59 | "node": ">=6" 60 | } 61 | }, 62 | "node_modules/child-process-ext": { 63 | "version": "2.1.1", 64 | "resolved": "https://registry.npmjs.org/child-process-ext/-/child-process-ext-2.1.1.tgz", 65 | "integrity": "sha512-0UQ55f51JBkOFa+fvR76ywRzxiPwQS3Xe8oe5bZRphpv+dIMeerW5Zn5e4cUy4COJwVtJyU0R79RMnw+aCqmGA==", 66 | "dev": true, 67 | "license": "ISC", 68 | "dependencies": { 69 | "cross-spawn": "^6.0.5", 70 | "es5-ext": "^0.10.53", 71 | "log": "^6.0.0", 72 | "split2": "^3.1.1", 73 | "stream-promise": "^3.2.0" 74 | } 75 | }, 76 | "node_modules/cliui": { 77 | "version": "6.0.0", 78 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", 79 | "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", 80 | "dev": true, 81 | "license": "ISC", 82 | "dependencies": { 83 | "string-width": "^4.2.0", 84 | "strip-ansi": "^6.0.0", 85 | "wrap-ansi": "^6.2.0" 86 | } 87 | }, 88 | "node_modules/cliui/node_modules/ansi-regex": { 89 | "version": "5.0.1", 90 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 91 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 92 | "dev": true, 93 | "license": "MIT", 94 | "engines": { 95 | "node": ">=8" 96 | } 97 | }, 98 | "node_modules/cliui/node_modules/ansi-styles": { 99 | "version": "4.3.0", 100 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 101 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 102 | "dev": true, 103 | "license": "MIT", 104 | "dependencies": { 105 | "color-convert": "^2.0.1" 106 | }, 107 | "engines": { 108 | "node": ">=8" 109 | }, 110 | "funding": { 111 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 112 | } 113 | }, 114 | "node_modules/cliui/node_modules/emoji-regex": { 115 | "version": "8.0.0", 116 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 117 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 118 | "dev": true, 119 | "license": "MIT" 120 | }, 121 | "node_modules/cliui/node_modules/string-width": { 122 | "version": "4.2.3", 123 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 124 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 125 | "dev": true, 126 | "license": "MIT", 127 | "dependencies": { 128 | "emoji-regex": "^8.0.0", 129 | "is-fullwidth-code-point": "^3.0.0", 130 | "strip-ansi": "^6.0.1" 131 | }, 132 | "engines": { 133 | "node": ">=8" 134 | } 135 | }, 136 | "node_modules/cliui/node_modules/strip-ansi": { 137 | "version": "6.0.1", 138 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 139 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 140 | "dev": true, 141 | "license": "MIT", 142 | "dependencies": { 143 | "ansi-regex": "^5.0.1" 144 | }, 145 | "engines": { 146 | "node": ">=8" 147 | } 148 | }, 149 | "node_modules/cliui/node_modules/wrap-ansi": { 150 | "version": "6.2.0", 151 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", 152 | "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", 153 | "dev": true, 154 | "license": "MIT", 155 | "dependencies": { 156 | "ansi-styles": "^4.0.0", 157 | "string-width": "^4.1.0", 158 | "strip-ansi": "^6.0.0" 159 | }, 160 | "engines": { 161 | "node": ">=8" 162 | } 163 | }, 164 | "node_modules/color-convert": { 165 | "version": "2.0.1", 166 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 167 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 168 | "dev": true, 169 | "license": "MIT", 170 | "dependencies": { 171 | "color-name": "~1.1.4" 172 | }, 173 | "engines": { 174 | "node": ">=7.0.0" 175 | } 176 | }, 177 | "node_modules/color-name": { 178 | "version": "1.1.4", 179 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 180 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 181 | "dev": true, 182 | "license": "MIT" 183 | }, 184 | "node_modules/concat-map": { 185 | "version": "0.0.1", 186 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 187 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 188 | "dev": true, 189 | "license": "MIT" 190 | }, 191 | "node_modules/core-util-is": { 192 | "version": "1.0.3", 193 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", 194 | "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", 195 | "dev": true, 196 | "license": "MIT" 197 | }, 198 | "node_modules/cross-spawn": { 199 | "version": "6.0.6", 200 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", 201 | "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", 202 | "dev": true, 203 | "license": "MIT", 204 | "dependencies": { 205 | "nice-try": "^1.0.4", 206 | "path-key": "^2.0.1", 207 | "semver": "^5.5.0", 208 | "shebang-command": "^1.2.0", 209 | "which": "^1.2.9" 210 | }, 211 | "engines": { 212 | "node": ">=4.8" 213 | } 214 | }, 215 | "node_modules/cross-spawn/node_modules/semver": { 216 | "version": "5.7.2", 217 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", 218 | "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", 219 | "dev": true, 220 | "license": "ISC", 221 | "bin": { 222 | "semver": "bin/semver" 223 | } 224 | }, 225 | "node_modules/d": { 226 | "version": "1.0.2", 227 | "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", 228 | "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", 229 | "dev": true, 230 | "license": "ISC", 231 | "dependencies": { 232 | "es5-ext": "^0.10.64", 233 | "type": "^2.7.2" 234 | }, 235 | "engines": { 236 | "node": ">=0.12" 237 | } 238 | }, 239 | "node_modules/decamelize": { 240 | "version": "1.2.0", 241 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 242 | "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", 243 | "dev": true, 244 | "license": "MIT", 245 | "engines": { 246 | "node": ">=0.10.0" 247 | } 248 | }, 249 | "node_modules/duration": { 250 | "version": "0.2.2", 251 | "resolved": "https://registry.npmjs.org/duration/-/duration-0.2.2.tgz", 252 | "integrity": "sha512-06kgtea+bGreF5eKYgI/36A6pLXggY7oR4p1pq4SmdFBn1ReOL5D8RhG64VrqfTTKNucqqtBAwEj8aB88mcqrg==", 253 | "dev": true, 254 | "license": "ISC", 255 | "dependencies": { 256 | "d": "1", 257 | "es5-ext": "~0.10.46" 258 | } 259 | }, 260 | "node_modules/es5-ext": { 261 | "version": "0.10.64", 262 | "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", 263 | "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", 264 | "dev": true, 265 | "hasInstallScript": true, 266 | "license": "ISC", 267 | "dependencies": { 268 | "es6-iterator": "^2.0.3", 269 | "es6-symbol": "^3.1.3", 270 | "esniff": "^2.0.1", 271 | "next-tick": "^1.1.0" 272 | }, 273 | "engines": { 274 | "node": ">=0.10" 275 | } 276 | }, 277 | "node_modules/es6-iterator": { 278 | "version": "2.0.3", 279 | "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", 280 | "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", 281 | "dev": true, 282 | "license": "MIT", 283 | "dependencies": { 284 | "d": "1", 285 | "es5-ext": "^0.10.35", 286 | "es6-symbol": "^3.1.1" 287 | } 288 | }, 289 | "node_modules/es6-symbol": { 290 | "version": "3.1.4", 291 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", 292 | "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", 293 | "dev": true, 294 | "license": "ISC", 295 | "dependencies": { 296 | "d": "^1.0.2", 297 | "ext": "^1.7.0" 298 | }, 299 | "engines": { 300 | "node": ">=0.12" 301 | } 302 | }, 303 | "node_modules/esniff": { 304 | "version": "2.0.1", 305 | "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", 306 | "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", 307 | "dev": true, 308 | "license": "ISC", 309 | "dependencies": { 310 | "d": "^1.0.1", 311 | "es5-ext": "^0.10.62", 312 | "event-emitter": "^0.3.5", 313 | "type": "^2.7.2" 314 | }, 315 | "engines": { 316 | "node": ">=0.10" 317 | } 318 | }, 319 | "node_modules/event-emitter": { 320 | "version": "0.3.5", 321 | "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", 322 | "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", 323 | "dev": true, 324 | "license": "MIT", 325 | "dependencies": { 326 | "d": "1", 327 | "es5-ext": "~0.10.14" 328 | } 329 | }, 330 | "node_modules/ext": { 331 | "version": "1.7.0", 332 | "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", 333 | "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", 334 | "dev": true, 335 | "license": "ISC", 336 | "dependencies": { 337 | "type": "^2.7.2" 338 | } 339 | }, 340 | "node_modules/find-up": { 341 | "version": "4.1.0", 342 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", 343 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", 344 | "dev": true, 345 | "license": "MIT", 346 | "dependencies": { 347 | "locate-path": "^5.0.0", 348 | "path-exists": "^4.0.0" 349 | }, 350 | "engines": { 351 | "node": ">=8" 352 | } 353 | }, 354 | "node_modules/fs-extra": { 355 | "version": "10.1.0", 356 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", 357 | "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", 358 | "dev": true, 359 | "license": "MIT", 360 | "dependencies": { 361 | "graceful-fs": "^4.2.0", 362 | "jsonfile": "^6.0.1", 363 | "universalify": "^2.0.0" 364 | }, 365 | "engines": { 366 | "node": ">=12" 367 | } 368 | }, 369 | "node_modules/fs.realpath": { 370 | "version": "1.0.0", 371 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 372 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", 373 | "dev": true, 374 | "license": "ISC" 375 | }, 376 | "node_modules/get-caller-file": { 377 | "version": "2.0.5", 378 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 379 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 380 | "dev": true, 381 | "license": "ISC", 382 | "engines": { 383 | "node": "6.* || 8.* || >= 10.*" 384 | } 385 | }, 386 | "node_modules/glob-all": { 387 | "version": "3.3.1", 388 | "resolved": "https://registry.npmjs.org/glob-all/-/glob-all-3.3.1.tgz", 389 | "integrity": "sha512-Y+ESjdI7ZgMwfzanHZYQ87C59jOO0i+Hd+QYtVt9PhLi6d8wlOpzQnfBxWUlaTuAoR3TkybLqqbIoWveU4Ji7Q==", 390 | "dev": true, 391 | "license": "MIT", 392 | "dependencies": { 393 | "glob": "^7.2.3", 394 | "yargs": "^15.3.1" 395 | }, 396 | "bin": { 397 | "glob-all": "bin/glob-all" 398 | } 399 | }, 400 | "node_modules/glob-all/node_modules/brace-expansion": { 401 | "version": "1.1.11", 402 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 403 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 404 | "dev": true, 405 | "license": "MIT", 406 | "dependencies": { 407 | "balanced-match": "^1.0.0", 408 | "concat-map": "0.0.1" 409 | } 410 | }, 411 | "node_modules/glob-all/node_modules/glob": { 412 | "version": "7.2.3", 413 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", 414 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", 415 | "deprecated": "Glob versions prior to v9 are no longer supported", 416 | "dev": true, 417 | "license": "ISC", 418 | "dependencies": { 419 | "fs.realpath": "^1.0.0", 420 | "inflight": "^1.0.4", 421 | "inherits": "2", 422 | "minimatch": "^3.1.1", 423 | "once": "^1.3.0", 424 | "path-is-absolute": "^1.0.0" 425 | }, 426 | "engines": { 427 | "node": "*" 428 | }, 429 | "funding": { 430 | "url": "https://github.com/sponsors/isaacs" 431 | } 432 | }, 433 | "node_modules/glob-all/node_modules/minimatch": { 434 | "version": "3.1.2", 435 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 436 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 437 | "dev": true, 438 | "license": "ISC", 439 | "dependencies": { 440 | "brace-expansion": "^1.1.7" 441 | }, 442 | "engines": { 443 | "node": "*" 444 | } 445 | }, 446 | "node_modules/graceful-fs": { 447 | "version": "4.2.11", 448 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", 449 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", 450 | "dev": true, 451 | "license": "ISC" 452 | }, 453 | "node_modules/immediate": { 454 | "version": "3.0.6", 455 | "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", 456 | "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", 457 | "dev": true, 458 | "license": "MIT" 459 | }, 460 | "node_modules/inflight": { 461 | "version": "1.0.6", 462 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 463 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 464 | "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", 465 | "dev": true, 466 | "license": "ISC", 467 | "dependencies": { 468 | "once": "^1.3.0", 469 | "wrappy": "1" 470 | } 471 | }, 472 | "node_modules/inherits": { 473 | "version": "2.0.4", 474 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 475 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 476 | "dev": true, 477 | "license": "ISC" 478 | }, 479 | "node_modules/is-docker": { 480 | "version": "2.2.1", 481 | "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", 482 | "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", 483 | "dev": true, 484 | "license": "MIT", 485 | "bin": { 486 | "is-docker": "cli.js" 487 | }, 488 | "engines": { 489 | "node": ">=8" 490 | }, 491 | "funding": { 492 | "url": "https://github.com/sponsors/sindresorhus" 493 | } 494 | }, 495 | "node_modules/is-fullwidth-code-point": { 496 | "version": "3.0.0", 497 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 498 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 499 | "dev": true, 500 | "license": "MIT", 501 | "engines": { 502 | "node": ">=8" 503 | } 504 | }, 505 | "node_modules/is-plain-object": { 506 | "version": "2.0.4", 507 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", 508 | "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", 509 | "dev": true, 510 | "license": "MIT", 511 | "dependencies": { 512 | "isobject": "^3.0.1" 513 | }, 514 | "engines": { 515 | "node": ">=0.10.0" 516 | } 517 | }, 518 | "node_modules/is-primitive": { 519 | "version": "3.0.1", 520 | "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-3.0.1.tgz", 521 | "integrity": "sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w==", 522 | "dev": true, 523 | "license": "MIT", 524 | "engines": { 525 | "node": ">=0.10.0" 526 | } 527 | }, 528 | "node_modules/is-stream": { 529 | "version": "1.1.0", 530 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 531 | "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", 532 | "dev": true, 533 | "license": "MIT", 534 | "engines": { 535 | "node": ">=0.10.0" 536 | } 537 | }, 538 | "node_modules/is-wsl": { 539 | "version": "2.2.0", 540 | "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", 541 | "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", 542 | "dev": true, 543 | "license": "MIT", 544 | "dependencies": { 545 | "is-docker": "^2.0.0" 546 | }, 547 | "engines": { 548 | "node": ">=8" 549 | } 550 | }, 551 | "node_modules/isarray": { 552 | "version": "1.0.0", 553 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 554 | "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", 555 | "dev": true, 556 | "license": "MIT" 557 | }, 558 | "node_modules/isexe": { 559 | "version": "2.0.0", 560 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 561 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 562 | "dev": true, 563 | "license": "ISC" 564 | }, 565 | "node_modules/isobject": { 566 | "version": "3.0.1", 567 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 568 | "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", 569 | "dev": true, 570 | "license": "MIT", 571 | "engines": { 572 | "node": ">=0.10.0" 573 | } 574 | }, 575 | "node_modules/jsonfile": { 576 | "version": "6.1.0", 577 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", 578 | "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", 579 | "dev": true, 580 | "license": "MIT", 581 | "dependencies": { 582 | "universalify": "^2.0.0" 583 | }, 584 | "optionalDependencies": { 585 | "graceful-fs": "^4.1.6" 586 | } 587 | }, 588 | "node_modules/jszip": { 589 | "version": "3.10.1", 590 | "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", 591 | "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", 592 | "dev": true, 593 | "license": "(MIT OR GPL-3.0-or-later)", 594 | "dependencies": { 595 | "lie": "~3.3.0", 596 | "pako": "~1.0.2", 597 | "readable-stream": "~2.3.6", 598 | "setimmediate": "^1.0.5" 599 | } 600 | }, 601 | "node_modules/lie": { 602 | "version": "3.3.0", 603 | "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", 604 | "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", 605 | "dev": true, 606 | "license": "MIT", 607 | "dependencies": { 608 | "immediate": "~3.0.5" 609 | } 610 | }, 611 | "node_modules/locate-path": { 612 | "version": "5.0.0", 613 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 614 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 615 | "dev": true, 616 | "license": "MIT", 617 | "dependencies": { 618 | "p-locate": "^4.1.0" 619 | }, 620 | "engines": { 621 | "node": ">=8" 622 | } 623 | }, 624 | "node_modules/lodash.get": { 625 | "version": "4.4.2", 626 | "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", 627 | "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", 628 | "dev": true, 629 | "license": "MIT" 630 | }, 631 | "node_modules/lodash.uniqby": { 632 | "version": "4.7.0", 633 | "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", 634 | "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", 635 | "dev": true, 636 | "license": "MIT" 637 | }, 638 | "node_modules/lodash.values": { 639 | "version": "4.3.0", 640 | "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-4.3.0.tgz", 641 | "integrity": "sha512-r0RwvdCv8id9TUblb/O7rYPwVy6lerCbcawrfdo9iC/1t1wsNMJknO79WNBgwkH0hIeJ08jmvvESbFpNb4jH0Q==", 642 | "dev": true, 643 | "license": "MIT" 644 | }, 645 | "node_modules/log": { 646 | "version": "6.3.1", 647 | "resolved": "https://registry.npmjs.org/log/-/log-6.3.1.tgz", 648 | "integrity": "sha512-McG47rJEWOkXTDioZzQNydAVvZNeEkSyLJ1VWkFwfW+o1knW+QSi8D1KjPn/TnctV+q99lkvJNe1f0E1IjfY2A==", 649 | "dev": true, 650 | "license": "ISC", 651 | "dependencies": { 652 | "d": "^1.0.1", 653 | "duration": "^0.2.2", 654 | "es5-ext": "^0.10.53", 655 | "event-emitter": "^0.3.5", 656 | "sprintf-kit": "^2.0.1", 657 | "type": "^2.5.0", 658 | "uni-global": "^1.0.0" 659 | } 660 | }, 661 | "node_modules/next-tick": { 662 | "version": "1.1.0", 663 | "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", 664 | "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", 665 | "dev": true, 666 | "license": "ISC" 667 | }, 668 | "node_modules/nice-try": { 669 | "version": "1.0.5", 670 | "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", 671 | "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", 672 | "dev": true, 673 | "license": "MIT" 674 | }, 675 | "node_modules/once": { 676 | "version": "1.4.0", 677 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 678 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 679 | "dev": true, 680 | "license": "ISC", 681 | "dependencies": { 682 | "wrappy": "1" 683 | } 684 | }, 685 | "node_modules/p-limit": { 686 | "version": "2.3.0", 687 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 688 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 689 | "dev": true, 690 | "license": "MIT", 691 | "dependencies": { 692 | "p-try": "^2.0.0" 693 | }, 694 | "engines": { 695 | "node": ">=6" 696 | }, 697 | "funding": { 698 | "url": "https://github.com/sponsors/sindresorhus" 699 | } 700 | }, 701 | "node_modules/p-locate": { 702 | "version": "4.1.0", 703 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 704 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 705 | "dev": true, 706 | "license": "MIT", 707 | "dependencies": { 708 | "p-limit": "^2.2.0" 709 | }, 710 | "engines": { 711 | "node": ">=8" 712 | } 713 | }, 714 | "node_modules/p-try": { 715 | "version": "2.2.0", 716 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 717 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 718 | "dev": true, 719 | "license": "MIT", 720 | "engines": { 721 | "node": ">=6" 722 | } 723 | }, 724 | "node_modules/pako": { 725 | "version": "1.0.11", 726 | "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", 727 | "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", 728 | "dev": true, 729 | "license": "(MIT AND Zlib)" 730 | }, 731 | "node_modules/path-exists": { 732 | "version": "4.0.0", 733 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 734 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 735 | "dev": true, 736 | "license": "MIT", 737 | "engines": { 738 | "node": ">=8" 739 | } 740 | }, 741 | "node_modules/path-is-absolute": { 742 | "version": "1.0.1", 743 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 744 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 745 | "dev": true, 746 | "license": "MIT", 747 | "engines": { 748 | "node": ">=0.10.0" 749 | } 750 | }, 751 | "node_modules/path-key": { 752 | "version": "2.0.1", 753 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", 754 | "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", 755 | "dev": true, 756 | "license": "MIT", 757 | "engines": { 758 | "node": ">=4" 759 | } 760 | }, 761 | "node_modules/process-nextick-args": { 762 | "version": "2.0.1", 763 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 764 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", 765 | "dev": true, 766 | "license": "MIT" 767 | }, 768 | "node_modules/readable-stream": { 769 | "version": "2.3.8", 770 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", 771 | "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", 772 | "dev": true, 773 | "license": "MIT", 774 | "dependencies": { 775 | "core-util-is": "~1.0.0", 776 | "inherits": "~2.0.3", 777 | "isarray": "~1.0.0", 778 | "process-nextick-args": "~2.0.0", 779 | "safe-buffer": "~5.1.1", 780 | "string_decoder": "~1.1.1", 781 | "util-deprecate": "~1.0.1" 782 | } 783 | }, 784 | "node_modules/require-directory": { 785 | "version": "2.1.1", 786 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 787 | "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", 788 | "dev": true, 789 | "license": "MIT", 790 | "engines": { 791 | "node": ">=0.10.0" 792 | } 793 | }, 794 | "node_modules/require-main-filename": { 795 | "version": "2.0.0", 796 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 797 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", 798 | "dev": true, 799 | "license": "ISC" 800 | }, 801 | "node_modules/safe-buffer": { 802 | "version": "5.1.2", 803 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 804 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 805 | "dev": true, 806 | "license": "MIT" 807 | }, 808 | "node_modules/semver": { 809 | "version": "7.6.3", 810 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", 811 | "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", 812 | "dev": true, 813 | "license": "ISC", 814 | "bin": { 815 | "semver": "bin/semver.js" 816 | }, 817 | "engines": { 818 | "node": ">=10" 819 | } 820 | }, 821 | "node_modules/serverless-python-requirements": { 822 | "version": "6.1.2", 823 | "resolved": "https://registry.npmjs.org/serverless-python-requirements/-/serverless-python-requirements-6.1.2.tgz", 824 | "integrity": "sha512-pas27CBxxaLTU5XMYnCVPJc+LVdm65Ys5olNvRWRqfUaZwTfD/7KSSt2XPSRme8BeJubroslaiOtWPP+IrxTVA==", 825 | "dev": true, 826 | "license": "MIT", 827 | "dependencies": { 828 | "@iarna/toml": "^2.2.5", 829 | "appdirectory": "^0.1.0", 830 | "bluebird": "^3.7.2", 831 | "child-process-ext": "^2.1.1", 832 | "fs-extra": "^10.1.0", 833 | "glob-all": "^3.3.1", 834 | "is-wsl": "^2.2.0", 835 | "jszip": "^3.10.1", 836 | "lodash.get": "^4.4.2", 837 | "lodash.uniqby": "^4.7.0", 838 | "lodash.values": "^4.3.0", 839 | "rimraf": "^3.0.2", 840 | "semver": "^7.6.0", 841 | "set-value": "^4.1.0", 842 | "sha256-file": "1.0.0", 843 | "shell-quote": "^1.8.1" 844 | }, 845 | "engines": { 846 | "node": ">=12.0" 847 | } 848 | }, 849 | "node_modules/serverless-python-requirements/node_modules/brace-expansion": { 850 | "version": "1.1.11", 851 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 852 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 853 | "dev": true, 854 | "license": "MIT", 855 | "dependencies": { 856 | "balanced-match": "^1.0.0", 857 | "concat-map": "0.0.1" 858 | } 859 | }, 860 | "node_modules/serverless-python-requirements/node_modules/glob": { 861 | "version": "7.2.3", 862 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", 863 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", 864 | "deprecated": "Glob versions prior to v9 are no longer supported", 865 | "dev": true, 866 | "license": "ISC", 867 | "dependencies": { 868 | "fs.realpath": "^1.0.0", 869 | "inflight": "^1.0.4", 870 | "inherits": "2", 871 | "minimatch": "^3.1.1", 872 | "once": "^1.3.0", 873 | "path-is-absolute": "^1.0.0" 874 | }, 875 | "engines": { 876 | "node": "*" 877 | }, 878 | "funding": { 879 | "url": "https://github.com/sponsors/isaacs" 880 | } 881 | }, 882 | "node_modules/serverless-python-requirements/node_modules/minimatch": { 883 | "version": "3.1.2", 884 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 885 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 886 | "dev": true, 887 | "license": "ISC", 888 | "dependencies": { 889 | "brace-expansion": "^1.1.7" 890 | }, 891 | "engines": { 892 | "node": "*" 893 | } 894 | }, 895 | "node_modules/serverless-python-requirements/node_modules/rimraf": { 896 | "version": "3.0.2", 897 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 898 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 899 | "deprecated": "Rimraf versions prior to v4 are no longer supported", 900 | "dev": true, 901 | "license": "ISC", 902 | "dependencies": { 903 | "glob": "^7.1.3" 904 | }, 905 | "bin": { 906 | "rimraf": "bin.js" 907 | }, 908 | "funding": { 909 | "url": "https://github.com/sponsors/isaacs" 910 | } 911 | }, 912 | "node_modules/set-blocking": { 913 | "version": "2.0.0", 914 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 915 | "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", 916 | "dev": true, 917 | "license": "ISC" 918 | }, 919 | "node_modules/set-value": { 920 | "version": "4.1.0", 921 | "resolved": "https://registry.npmjs.org/set-value/-/set-value-4.1.0.tgz", 922 | "integrity": "sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw==", 923 | "dev": true, 924 | "funding": [ 925 | "https://github.com/sponsors/jonschlinkert", 926 | "https://paypal.me/jonathanschlinkert", 927 | "https://jonschlinkert.dev/sponsor" 928 | ], 929 | "license": "MIT", 930 | "dependencies": { 931 | "is-plain-object": "^2.0.4", 932 | "is-primitive": "^3.0.1" 933 | }, 934 | "engines": { 935 | "node": ">=11.0" 936 | } 937 | }, 938 | "node_modules/setimmediate": { 939 | "version": "1.0.5", 940 | "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", 941 | "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", 942 | "dev": true, 943 | "license": "MIT" 944 | }, 945 | "node_modules/sha256-file": { 946 | "version": "1.0.0", 947 | "resolved": "https://registry.npmjs.org/sha256-file/-/sha256-file-1.0.0.tgz", 948 | "integrity": "sha512-nqf+g0veqgQAkDx0U2y2Tn2KWyADuuludZTw9A7J3D+61rKlIIl9V5TS4mfnwKuXZOH9B7fQyjYJ9pKRHIsAyg==", 949 | "dev": true, 950 | "license": "MIT" 951 | }, 952 | "node_modules/shebang-command": { 953 | "version": "1.2.0", 954 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 955 | "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", 956 | "dev": true, 957 | "license": "MIT", 958 | "dependencies": { 959 | "shebang-regex": "^1.0.0" 960 | }, 961 | "engines": { 962 | "node": ">=0.10.0" 963 | } 964 | }, 965 | "node_modules/shebang-regex": { 966 | "version": "1.0.0", 967 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 968 | "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", 969 | "dev": true, 970 | "license": "MIT", 971 | "engines": { 972 | "node": ">=0.10.0" 973 | } 974 | }, 975 | "node_modules/shell-quote": { 976 | "version": "1.8.1", 977 | "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", 978 | "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", 979 | "dev": true, 980 | "license": "MIT", 981 | "funding": { 982 | "url": "https://github.com/sponsors/ljharb" 983 | } 984 | }, 985 | "node_modules/split2": { 986 | "version": "3.2.2", 987 | "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", 988 | "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", 989 | "dev": true, 990 | "license": "ISC", 991 | "dependencies": { 992 | "readable-stream": "^3.0.0" 993 | } 994 | }, 995 | "node_modules/split2/node_modules/readable-stream": { 996 | "version": "3.6.2", 997 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", 998 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", 999 | "dev": true, 1000 | "license": "MIT", 1001 | "dependencies": { 1002 | "inherits": "^2.0.3", 1003 | "string_decoder": "^1.1.1", 1004 | "util-deprecate": "^1.0.1" 1005 | }, 1006 | "engines": { 1007 | "node": ">= 6" 1008 | } 1009 | }, 1010 | "node_modules/sprintf-kit": { 1011 | "version": "2.0.2", 1012 | "resolved": "https://registry.npmjs.org/sprintf-kit/-/sprintf-kit-2.0.2.tgz", 1013 | "integrity": "sha512-lnapdj6W4LflHZGKvl9eVkz5YF0xaTrqpRWVA4cNVOTedwqifIP8ooGImldzT/4IAN5KXFQAyXTdLidYVQdyag==", 1014 | "dev": true, 1015 | "license": "ISC", 1016 | "dependencies": { 1017 | "es5-ext": "^0.10.64" 1018 | }, 1019 | "engines": { 1020 | "node": ">=0.12" 1021 | } 1022 | }, 1023 | "node_modules/stream-promise": { 1024 | "version": "3.2.0", 1025 | "resolved": "https://registry.npmjs.org/stream-promise/-/stream-promise-3.2.0.tgz", 1026 | "integrity": "sha512-P+7muTGs2C8yRcgJw/PPt61q7O517tDHiwYEzMWo1GSBCcZedUMT/clz7vUNsSxFphIlJ6QUL4GexQKlfJoVtA==", 1027 | "dev": true, 1028 | "license": "ISC", 1029 | "dependencies": { 1030 | "2-thenable": "^1.0.0", 1031 | "es5-ext": "^0.10.49", 1032 | "is-stream": "^1.1.0" 1033 | } 1034 | }, 1035 | "node_modules/string_decoder": { 1036 | "version": "1.1.1", 1037 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1038 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1039 | "dev": true, 1040 | "license": "MIT", 1041 | "dependencies": { 1042 | "safe-buffer": "~5.1.0" 1043 | } 1044 | }, 1045 | "node_modules/type": { 1046 | "version": "2.7.3", 1047 | "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", 1048 | "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", 1049 | "dev": true, 1050 | "license": "ISC" 1051 | }, 1052 | "node_modules/uni-global": { 1053 | "version": "1.0.0", 1054 | "resolved": "https://registry.npmjs.org/uni-global/-/uni-global-1.0.0.tgz", 1055 | "integrity": "sha512-WWM3HP+siTxzIWPNUg7hZ4XO8clKi6NoCAJJWnuRL+BAqyFXF8gC03WNyTefGoUXYc47uYgXxpKLIEvo65PEHw==", 1056 | "dev": true, 1057 | "license": "ISC", 1058 | "dependencies": { 1059 | "type": "^2.5.0" 1060 | } 1061 | }, 1062 | "node_modules/universalify": { 1063 | "version": "2.0.1", 1064 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", 1065 | "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", 1066 | "dev": true, 1067 | "license": "MIT", 1068 | "engines": { 1069 | "node": ">= 10.0.0" 1070 | } 1071 | }, 1072 | "node_modules/util-deprecate": { 1073 | "version": "1.0.2", 1074 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1075 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", 1076 | "dev": true, 1077 | "license": "MIT" 1078 | }, 1079 | "node_modules/which": { 1080 | "version": "1.3.1", 1081 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 1082 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 1083 | "dev": true, 1084 | "license": "ISC", 1085 | "dependencies": { 1086 | "isexe": "^2.0.0" 1087 | }, 1088 | "bin": { 1089 | "which": "bin/which" 1090 | } 1091 | }, 1092 | "node_modules/which-module": { 1093 | "version": "2.0.1", 1094 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", 1095 | "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", 1096 | "dev": true, 1097 | "license": "ISC" 1098 | }, 1099 | "node_modules/wrappy": { 1100 | "version": "1.0.2", 1101 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1102 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 1103 | "dev": true, 1104 | "license": "ISC" 1105 | }, 1106 | "node_modules/y18n": { 1107 | "version": "4.0.3", 1108 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", 1109 | "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", 1110 | "dev": true, 1111 | "license": "ISC" 1112 | }, 1113 | "node_modules/yargs": { 1114 | "version": "15.4.1", 1115 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", 1116 | "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", 1117 | "dev": true, 1118 | "license": "MIT", 1119 | "dependencies": { 1120 | "cliui": "^6.0.0", 1121 | "decamelize": "^1.2.0", 1122 | "find-up": "^4.1.0", 1123 | "get-caller-file": "^2.0.1", 1124 | "require-directory": "^2.1.1", 1125 | "require-main-filename": "^2.0.0", 1126 | "set-blocking": "^2.0.0", 1127 | "string-width": "^4.2.0", 1128 | "which-module": "^2.0.0", 1129 | "y18n": "^4.0.0", 1130 | "yargs-parser": "^18.1.2" 1131 | }, 1132 | "engines": { 1133 | "node": ">=8" 1134 | } 1135 | }, 1136 | "node_modules/yargs-parser": { 1137 | "version": "18.1.3", 1138 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", 1139 | "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", 1140 | "dev": true, 1141 | "license": "ISC", 1142 | "dependencies": { 1143 | "camelcase": "^5.0.0", 1144 | "decamelize": "^1.2.0" 1145 | }, 1146 | "engines": { 1147 | "node": ">=6" 1148 | } 1149 | }, 1150 | "node_modules/yargs/node_modules/ansi-regex": { 1151 | "version": "5.0.1", 1152 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1153 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 1154 | "dev": true, 1155 | "license": "MIT", 1156 | "engines": { 1157 | "node": ">=8" 1158 | } 1159 | }, 1160 | "node_modules/yargs/node_modules/emoji-regex": { 1161 | "version": "8.0.0", 1162 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1163 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 1164 | "dev": true, 1165 | "license": "MIT" 1166 | }, 1167 | "node_modules/yargs/node_modules/string-width": { 1168 | "version": "4.2.3", 1169 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1170 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1171 | "dev": true, 1172 | "license": "MIT", 1173 | "dependencies": { 1174 | "emoji-regex": "^8.0.0", 1175 | "is-fullwidth-code-point": "^3.0.0", 1176 | "strip-ansi": "^6.0.1" 1177 | }, 1178 | "engines": { 1179 | "node": ">=8" 1180 | } 1181 | }, 1182 | "node_modules/yargs/node_modules/strip-ansi": { 1183 | "version": "6.0.1", 1184 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1185 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1186 | "dev": true, 1187 | "license": "MIT", 1188 | "dependencies": { 1189 | "ansi-regex": "^5.0.1" 1190 | }, 1191 | "engines": { 1192 | "node": ">=8" 1193 | } 1194 | } 1195 | } 1196 | } 1197 | -------------------------------------------------------------------------------- /projects/my_aws_lambda_project/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "serverless-python-requirements": "^6.1.2" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /projects/my_aws_lambda_project/poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 2.0.0 and should not be changed by hand. 2 | package = [] 3 | 4 | [metadata] 5 | lock-version = "2.1" 6 | python-versions = "^3.10" 7 | content-hash = "53f2eabc9c26446fbcc00d348c47878e118afc2054778c3c803a0a8028af27d9" 8 | -------------------------------------------------------------------------------- /projects/my_aws_lambda_project/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "my_aws_lambda_project" 3 | version = "1.1.1" 4 | description = "an example aws lambda project" 5 | authors = ["David Vujic"] 6 | packages = [ 7 | {include = "example/log", from = "../../components"}, 8 | {include = "example/greeting", from = "../../components"}, 9 | {include = "example/greet_aws_lambda", from = "../../bases"}, 10 | ] 11 | 12 | [tool.poetry.dependencies] 13 | python = "^3.10" 14 | 15 | [build-system] 16 | requires = ["poetry-core"] 17 | build-backend = "poetry.core.masonry.api" 18 | -------------------------------------------------------------------------------- /projects/my_aws_lambda_project/serverless.yml: -------------------------------------------------------------------------------- 1 | service: aws-python-project 2 | frameworkVersion: '3' 3 | package: 4 | artifact: dist/my_aws_lambda_project-1.1.1-py3-none-any.whl 5 | 6 | provider: 7 | name: aws 8 | stage: dev 9 | runtime: python3.9 10 | region: eu-north-1 11 | 12 | functions: 13 | hello: 14 | handler: example.greet_aws_lambda.core.handler 15 | 16 | plugins: 17 | - serverless-python-requirements 18 | -------------------------------------------------------------------------------- /projects/my_fastapi_project/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12 2 | 3 | ARG wheel=my_fastapi_project-0.0.1-py3-none-any.whl 4 | 5 | RUN python -m pip install --upgrade pip 6 | 7 | WORKDIR /code 8 | 9 | COPY ./dist/$wheel /code/$wheel 10 | RUN pip install --no-cache-dir --upgrade /code/$wheel 11 | 12 | CMD ["uvicorn", "example.greet_api.core:app", "--host", "0.0.0.0", "--port", "8000"] 13 | -------------------------------------------------------------------------------- /projects/my_fastapi_project/README.md: -------------------------------------------------------------------------------- 1 | # Example usage 2 | 3 | ## Build the project 4 | Navigate to this folder (where the `pyproject.toml` file is) 5 | 6 | Run: 7 | ``` shell 8 | poetry build-project 9 | ``` 10 | 11 | ## Run the app in Docker 12 | Build a docker image and run a container, and access the app from localhost. 13 | 14 | ### Build a docker image 15 | 16 | ``` shell 17 | docker build -t my-fastapi-project-image . 18 | ``` 19 | 20 | ### Run the image 21 | 22 | ``` shell 23 | docker run -d --name mycontainer -p 8000:8000 my-fastapi-project-image 24 | ``` 25 | 26 | The OpenAPI specification of this FastAPI app can now be accessed at http://localhost:8000/docs# 27 | 28 | 29 | ## Deploy in Kubernetes 30 | 31 | ### Development 32 | Build and deploy into a local Kubernetes cluster. 33 | 34 | 35 | ## Build a docker image in a minikube context 36 | 37 | ``` shell 38 | eval $(minikube docker-env) 39 | 40 | docker build -t my-fastapi-project-image . 41 | ``` 42 | 43 | 44 | #### Dry run, to verify the result 45 | ``` shell 46 | kubectl apply -k kubernetes/development --dry-run=client -o yaml 47 | ``` 48 | 49 | #### Deploy 50 | 51 | ``` shell 52 | kubectl apply -k kubernetes/development 53 | ``` 54 | 55 | #### Verify deployment 56 | 57 | ``` shell 58 | kubectl get pods 59 | ``` 60 | 61 | ``` shell 62 | kubectl get services 63 | ``` 64 | 65 | Try out the API by port forwarding to localhost: 66 | 67 | ``` shell 68 | kubectl port-forward svc/my-fastapi-project-api-app 9090:80 69 | ``` 70 | -------------------------------------------------------------------------------- /projects/my_fastapi_project/kubernetes/development/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | 4 | metadata: 5 | name: app 6 | 7 | spec: 8 | template: 9 | spec: 10 | containers: 11 | - name: app 12 | image: my-fastapi-project-image:latest 13 | -------------------------------------------------------------------------------- /projects/my_fastapi_project/kubernetes/development/kustomization.yaml: -------------------------------------------------------------------------------- 1 | kind: Kustomization 2 | 3 | namePrefix: my-fastapi-project- 4 | 5 | resources: 6 | - ../../../../_kubernetes/services/api/development 7 | 8 | patches: 9 | - path: deployment.yaml 10 | 11 | configMapGenerator: 12 | - name: app-env 13 | behavior: merge 14 | literals: 15 | - SOMETHING=specific-for-development 16 | -------------------------------------------------------------------------------- /projects/my_fastapi_project/kubernetes/staging/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | 4 | metadata: 5 | name: app 6 | 7 | spec: 8 | template: 9 | spec: 10 | containers: 11 | - name: app 12 | image: staging-fastapi-project-image:latest 13 | -------------------------------------------------------------------------------- /projects/my_fastapi_project/kubernetes/staging/kustomization.yaml: -------------------------------------------------------------------------------- 1 | kind: Kustomization 2 | 3 | namePrefix: my-fastapi-project- 4 | 5 | resources: 6 | - ../../../../_kubernetes/services/api/staging 7 | 8 | patches: 9 | - path: deployment.yaml 10 | 11 | configMapGenerator: 12 | - name: app-env 13 | behavior: merge 14 | literals: 15 | - SOMETHING=specific-for-staging 16 | -------------------------------------------------------------------------------- /projects/my_fastapi_project/poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 2.0.0 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "annotated-types" 5 | version = "0.7.0" 6 | description = "Reusable constraint types to use with typing.Annotated" 7 | optional = false 8 | python-versions = ">=3.8" 9 | groups = ["main"] 10 | files = [ 11 | {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, 12 | {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, 13 | ] 14 | 15 | [[package]] 16 | name = "anyio" 17 | version = "4.9.0" 18 | description = "High level compatibility layer for multiple asynchronous event loop implementations" 19 | optional = false 20 | python-versions = ">=3.9" 21 | groups = ["main"] 22 | files = [ 23 | {file = "anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c"}, 24 | {file = "anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028"}, 25 | ] 26 | 27 | [package.dependencies] 28 | exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} 29 | idna = ">=2.8" 30 | sniffio = ">=1.1" 31 | typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} 32 | 33 | [package.extras] 34 | doc = ["Sphinx (>=8.2,<9.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"] 35 | test = ["anyio[trio]", "blockbuster (>=1.5.23)", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"] 36 | trio = ["trio (>=0.26.1)"] 37 | 38 | [[package]] 39 | name = "click" 40 | version = "8.1.8" 41 | description = "Composable command line interface toolkit" 42 | optional = false 43 | python-versions = ">=3.7" 44 | groups = ["main"] 45 | files = [ 46 | {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, 47 | {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, 48 | ] 49 | 50 | [package.dependencies] 51 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 52 | 53 | [[package]] 54 | name = "colorama" 55 | version = "0.4.6" 56 | description = "Cross-platform colored terminal text." 57 | optional = false 58 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 59 | groups = ["main"] 60 | markers = "platform_system == \"Windows\" or sys_platform == \"win32\"" 61 | files = [ 62 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, 63 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, 64 | ] 65 | 66 | [[package]] 67 | name = "exceptiongroup" 68 | version = "1.2.2" 69 | description = "Backport of PEP 654 (exception groups)" 70 | optional = false 71 | python-versions = ">=3.7" 72 | groups = ["main"] 73 | markers = "python_version < \"3.11\"" 74 | files = [ 75 | {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, 76 | {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, 77 | ] 78 | 79 | [package.extras] 80 | test = ["pytest (>=6)"] 81 | 82 | [[package]] 83 | name = "fastapi" 84 | version = "0.115.12" 85 | description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" 86 | optional = false 87 | python-versions = ">=3.8" 88 | groups = ["main"] 89 | files = [ 90 | {file = "fastapi-0.115.12-py3-none-any.whl", hash = "sha256:e94613d6c05e27be7ffebdd6ea5f388112e5e430c8f7d6494a9d1d88d43e814d"}, 91 | {file = "fastapi-0.115.12.tar.gz", hash = "sha256:1e2c2a2646905f9e83d32f04a3f86aff4a286669c6c950ca95b5fd68c2602681"}, 92 | ] 93 | 94 | [package.dependencies] 95 | pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" 96 | starlette = ">=0.40.0,<0.47.0" 97 | typing-extensions = ">=4.8.0" 98 | 99 | [package.extras] 100 | all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=3.1.5)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] 101 | standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=3.1.5)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"] 102 | 103 | [[package]] 104 | name = "h11" 105 | version = "0.16.0" 106 | description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" 107 | optional = false 108 | python-versions = ">=3.8" 109 | groups = ["main"] 110 | files = [ 111 | {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, 112 | {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, 113 | ] 114 | 115 | [[package]] 116 | name = "httptools" 117 | version = "0.6.4" 118 | description = "A collection of framework independent HTTP protocol utils." 119 | optional = false 120 | python-versions = ">=3.8.0" 121 | groups = ["main"] 122 | files = [ 123 | {file = "httptools-0.6.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3c73ce323711a6ffb0d247dcd5a550b8babf0f757e86a52558fe5b86d6fefcc0"}, 124 | {file = "httptools-0.6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:345c288418f0944a6fe67be8e6afa9262b18c7626c3ef3c28adc5eabc06a68da"}, 125 | {file = "httptools-0.6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deee0e3343f98ee8047e9f4c5bc7cedbf69f5734454a94c38ee829fb2d5fa3c1"}, 126 | {file = "httptools-0.6.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca80b7485c76f768a3bc83ea58373f8db7b015551117375e4918e2aa77ea9b50"}, 127 | {file = "httptools-0.6.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:90d96a385fa941283ebd231464045187a31ad932ebfa541be8edf5b3c2328959"}, 128 | {file = "httptools-0.6.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:59e724f8b332319e2875efd360e61ac07f33b492889284a3e05e6d13746876f4"}, 129 | {file = "httptools-0.6.4-cp310-cp310-win_amd64.whl", hash = "sha256:c26f313951f6e26147833fc923f78f95604bbec812a43e5ee37f26dc9e5a686c"}, 130 | {file = "httptools-0.6.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f47f8ed67cc0ff862b84a1189831d1d33c963fb3ce1ee0c65d3b0cbe7b711069"}, 131 | {file = "httptools-0.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0614154d5454c21b6410fdf5262b4a3ddb0f53f1e1721cfd59d55f32138c578a"}, 132 | {file = "httptools-0.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8787367fbdfccae38e35abf7641dafc5310310a5987b689f4c32cc8cc3ee975"}, 133 | {file = "httptools-0.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40b0f7fe4fd38e6a507bdb751db0379df1e99120c65fbdc8ee6c1d044897a636"}, 134 | {file = "httptools-0.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:40a5ec98d3f49904b9fe36827dcf1aadfef3b89e2bd05b0e35e94f97c2b14721"}, 135 | {file = "httptools-0.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dacdd3d10ea1b4ca9df97a0a303cbacafc04b5cd375fa98732678151643d4988"}, 136 | {file = "httptools-0.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:288cd628406cc53f9a541cfaf06041b4c71d751856bab45e3702191f931ccd17"}, 137 | {file = "httptools-0.6.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:df017d6c780287d5c80601dafa31f17bddb170232d85c066604d8558683711a2"}, 138 | {file = "httptools-0.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:85071a1e8c2d051b507161f6c3e26155b5c790e4e28d7f236422dbacc2a9cc44"}, 139 | {file = "httptools-0.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69422b7f458c5af875922cdb5bd586cc1f1033295aa9ff63ee196a87519ac8e1"}, 140 | {file = "httptools-0.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16e603a3bff50db08cd578d54f07032ca1631450ceb972c2f834c2b860c28ea2"}, 141 | {file = "httptools-0.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec4f178901fa1834d4a060320d2f3abc5c9e39766953d038f1458cb885f47e81"}, 142 | {file = "httptools-0.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f9eb89ecf8b290f2e293325c646a211ff1c2493222798bb80a530c5e7502494f"}, 143 | {file = "httptools-0.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:db78cb9ca56b59b016e64b6031eda5653be0589dba2b1b43453f6e8b405a0970"}, 144 | {file = "httptools-0.6.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ade273d7e767d5fae13fa637f4d53b6e961fb7fd93c7797562663f0171c26660"}, 145 | {file = "httptools-0.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:856f4bc0478ae143bad54a4242fccb1f3f86a6e1be5548fecfd4102061b3a083"}, 146 | {file = "httptools-0.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:322d20ea9cdd1fa98bd6a74b77e2ec5b818abdc3d36695ab402a0de8ef2865a3"}, 147 | {file = "httptools-0.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d87b29bd4486c0093fc64dea80231f7c7f7eb4dc70ae394d70a495ab8436071"}, 148 | {file = "httptools-0.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:342dd6946aa6bda4b8f18c734576106b8a31f2fe31492881a9a160ec84ff4bd5"}, 149 | {file = "httptools-0.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b36913ba52008249223042dca46e69967985fb4051951f94357ea681e1f5dc0"}, 150 | {file = "httptools-0.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:28908df1b9bb8187393d5b5db91435ccc9c8e891657f9cbb42a2541b44c82fc8"}, 151 | {file = "httptools-0.6.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d3f0d369e7ffbe59c4b6116a44d6a8eb4783aae027f2c0b366cf0aa964185dba"}, 152 | {file = "httptools-0.6.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:94978a49b8f4569ad607cd4946b759d90b285e39c0d4640c6b36ca7a3ddf2efc"}, 153 | {file = "httptools-0.6.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40dc6a8e399e15ea525305a2ddba998b0af5caa2566bcd79dcbe8948181eeaff"}, 154 | {file = "httptools-0.6.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab9ba8dcf59de5181f6be44a77458e45a578fc99c31510b8c65b7d5acc3cf490"}, 155 | {file = "httptools-0.6.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:fc411e1c0a7dcd2f902c7c48cf079947a7e65b5485dea9decb82b9105ca71a43"}, 156 | {file = "httptools-0.6.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:d54efd20338ac52ba31e7da78e4a72570cf729fac82bc31ff9199bedf1dc7440"}, 157 | {file = "httptools-0.6.4-cp38-cp38-win_amd64.whl", hash = "sha256:df959752a0c2748a65ab5387d08287abf6779ae9165916fe053e68ae1fbdc47f"}, 158 | {file = "httptools-0.6.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:85797e37e8eeaa5439d33e556662cc370e474445d5fab24dcadc65a8ffb04003"}, 159 | {file = "httptools-0.6.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:db353d22843cf1028f43c3651581e4bb49374d85692a85f95f7b9a130e1b2cab"}, 160 | {file = "httptools-0.6.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1ffd262a73d7c28424252381a5b854c19d9de5f56f075445d33919a637e3547"}, 161 | {file = "httptools-0.6.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:703c346571fa50d2e9856a37d7cd9435a25e7fd15e236c397bf224afaa355fe9"}, 162 | {file = "httptools-0.6.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:aafe0f1918ed07b67c1e838f950b1c1fabc683030477e60b335649b8020e1076"}, 163 | {file = "httptools-0.6.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0e563e54979e97b6d13f1bbc05a96109923e76b901f786a5eae36e99c01237bd"}, 164 | {file = "httptools-0.6.4-cp39-cp39-win_amd64.whl", hash = "sha256:b799de31416ecc589ad79dd85a0b2657a8fe39327944998dea368c1d4c9e55e6"}, 165 | {file = "httptools-0.6.4.tar.gz", hash = "sha256:4e93eee4add6493b59a5c514da98c939b244fce4a0d8879cd3f466562f4b7d5c"}, 166 | ] 167 | 168 | [package.extras] 169 | test = ["Cython (>=0.29.24)"] 170 | 171 | [[package]] 172 | name = "idna" 173 | version = "3.10" 174 | description = "Internationalized Domain Names in Applications (IDNA)" 175 | optional = false 176 | python-versions = ">=3.6" 177 | groups = ["main"] 178 | files = [ 179 | {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, 180 | {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, 181 | ] 182 | 183 | [package.extras] 184 | all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] 185 | 186 | [[package]] 187 | name = "pydantic" 188 | version = "2.11.3" 189 | description = "Data validation using Python type hints" 190 | optional = false 191 | python-versions = ">=3.9" 192 | groups = ["main"] 193 | files = [ 194 | {file = "pydantic-2.11.3-py3-none-any.whl", hash = "sha256:a082753436a07f9ba1289c6ffa01cd93db3548776088aa917cc43b63f68fa60f"}, 195 | {file = "pydantic-2.11.3.tar.gz", hash = "sha256:7471657138c16adad9322fe3070c0116dd6c3ad8d649300e3cbdfe91f4db4ec3"}, 196 | ] 197 | 198 | [package.dependencies] 199 | annotated-types = ">=0.6.0" 200 | pydantic-core = "2.33.1" 201 | typing-extensions = ">=4.12.2" 202 | typing-inspection = ">=0.4.0" 203 | 204 | [package.extras] 205 | email = ["email-validator (>=2.0.0)"] 206 | timezone = ["tzdata"] 207 | 208 | [[package]] 209 | name = "pydantic-core" 210 | version = "2.33.1" 211 | description = "Core functionality for Pydantic validation and serialization" 212 | optional = false 213 | python-versions = ">=3.9" 214 | groups = ["main"] 215 | files = [ 216 | {file = "pydantic_core-2.33.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3077cfdb6125cc8dab61b155fdd714663e401f0e6883f9632118ec12cf42df26"}, 217 | {file = "pydantic_core-2.33.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8ffab8b2908d152e74862d276cf5017c81a2f3719f14e8e3e8d6b83fda863927"}, 218 | {file = "pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5183e4f6a2d468787243ebcd70cf4098c247e60d73fb7d68d5bc1e1beaa0c4db"}, 219 | {file = "pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:398a38d323f37714023be1e0285765f0a27243a8b1506b7b7de87b647b517e48"}, 220 | {file = "pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87d3776f0001b43acebfa86f8c64019c043b55cc5a6a2e313d728b5c95b46969"}, 221 | {file = "pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c566dd9c5f63d22226409553531f89de0cac55397f2ab8d97d6f06cfce6d947e"}, 222 | {file = "pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0d5f3acc81452c56895e90643a625302bd6be351e7010664151cc55b7b97f89"}, 223 | {file = "pydantic_core-2.33.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d3a07fadec2a13274a8d861d3d37c61e97a816beae717efccaa4b36dfcaadcde"}, 224 | {file = "pydantic_core-2.33.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f99aeda58dce827f76963ee87a0ebe75e648c72ff9ba1174a253f6744f518f65"}, 225 | {file = "pydantic_core-2.33.1-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:902dbc832141aa0ec374f4310f1e4e7febeebc3256f00dc359a9ac3f264a45dc"}, 226 | {file = "pydantic_core-2.33.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fe44d56aa0b00d66640aa84a3cbe80b7a3ccdc6f0b1ca71090696a6d4777c091"}, 227 | {file = "pydantic_core-2.33.1-cp310-cp310-win32.whl", hash = "sha256:ed3eb16d51257c763539bde21e011092f127a2202692afaeaccb50db55a31383"}, 228 | {file = "pydantic_core-2.33.1-cp310-cp310-win_amd64.whl", hash = "sha256:694ad99a7f6718c1a498dc170ca430687a39894a60327f548e02a9c7ee4b6504"}, 229 | {file = "pydantic_core-2.33.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6e966fc3caaf9f1d96b349b0341c70c8d6573bf1bac7261f7b0ba88f96c56c24"}, 230 | {file = "pydantic_core-2.33.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bfd0adeee563d59c598ceabddf2c92eec77abcb3f4a391b19aa7366170bd9e30"}, 231 | {file = "pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91815221101ad3c6b507804178a7bb5cb7b2ead9ecd600041669c8d805ebd595"}, 232 | {file = "pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9fea9c1869bb4742d174a57b4700c6dadea951df8b06de40c2fedb4f02931c2e"}, 233 | {file = "pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d20eb4861329bb2484c021b9d9a977566ab16d84000a57e28061151c62b349a"}, 234 | {file = "pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb935c5591573ae3201640579f30128ccc10739b45663f93c06796854405505"}, 235 | {file = "pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c964fd24e6166420d18fb53996d8c9fd6eac9bf5ae3ec3d03015be4414ce497f"}, 236 | {file = "pydantic_core-2.33.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:681d65e9011f7392db5aa002b7423cc442d6a673c635668c227c6c8d0e5a4f77"}, 237 | {file = "pydantic_core-2.33.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e100c52f7355a48413e2999bfb4e139d2977a904495441b374f3d4fb4a170961"}, 238 | {file = "pydantic_core-2.33.1-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:048831bd363490be79acdd3232f74a0e9951b11b2b4cc058aeb72b22fdc3abe1"}, 239 | {file = "pydantic_core-2.33.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bdc84017d28459c00db6f918a7272a5190bec3090058334e43a76afb279eac7c"}, 240 | {file = "pydantic_core-2.33.1-cp311-cp311-win32.whl", hash = "sha256:32cd11c5914d1179df70406427097c7dcde19fddf1418c787540f4b730289896"}, 241 | {file = "pydantic_core-2.33.1-cp311-cp311-win_amd64.whl", hash = "sha256:2ea62419ba8c397e7da28a9170a16219d310d2cf4970dbc65c32faf20d828c83"}, 242 | {file = "pydantic_core-2.33.1-cp311-cp311-win_arm64.whl", hash = "sha256:fc903512177361e868bc1f5b80ac8c8a6e05fcdd574a5fb5ffeac5a9982b9e89"}, 243 | {file = "pydantic_core-2.33.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:1293d7febb995e9d3ec3ea09caf1a26214eec45b0f29f6074abb004723fc1de8"}, 244 | {file = "pydantic_core-2.33.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:99b56acd433386c8f20be5c4000786d1e7ca0523c8eefc995d14d79c7a081498"}, 245 | {file = "pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35a5ec3fa8c2fe6c53e1b2ccc2454398f95d5393ab398478f53e1afbbeb4d939"}, 246 | {file = "pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b172f7b9d2f3abc0efd12e3386f7e48b576ef309544ac3a63e5e9cdd2e24585d"}, 247 | {file = "pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9097b9f17f91eea659b9ec58148c0747ec354a42f7389b9d50701610d86f812e"}, 248 | {file = "pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cc77ec5b7e2118b152b0d886c7514a4653bcb58c6b1d760134a9fab915f777b3"}, 249 | {file = "pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3d15245b08fa4a84cefc6c9222e6f37c98111c8679fbd94aa145f9a0ae23d"}, 250 | {file = "pydantic_core-2.33.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef99779001d7ac2e2461d8ab55d3373fe7315caefdbecd8ced75304ae5a6fc6b"}, 251 | {file = "pydantic_core-2.33.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:fc6bf8869e193855e8d91d91f6bf59699a5cdfaa47a404e278e776dd7f168b39"}, 252 | {file = "pydantic_core-2.33.1-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:b1caa0bc2741b043db7823843e1bde8aaa58a55a58fda06083b0569f8b45693a"}, 253 | {file = "pydantic_core-2.33.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ec259f62538e8bf364903a7d0d0239447059f9434b284f5536e8402b7dd198db"}, 254 | {file = "pydantic_core-2.33.1-cp312-cp312-win32.whl", hash = "sha256:e14f369c98a7c15772b9da98987f58e2b509a93235582838bd0d1d8c08b68fda"}, 255 | {file = "pydantic_core-2.33.1-cp312-cp312-win_amd64.whl", hash = "sha256:1c607801d85e2e123357b3893f82c97a42856192997b95b4d8325deb1cd0c5f4"}, 256 | {file = "pydantic_core-2.33.1-cp312-cp312-win_arm64.whl", hash = "sha256:8d13f0276806ee722e70a1c93da19748594f19ac4299c7e41237fc791d1861ea"}, 257 | {file = "pydantic_core-2.33.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:70af6a21237b53d1fe7b9325b20e65cbf2f0a848cf77bed492b029139701e66a"}, 258 | {file = "pydantic_core-2.33.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:282b3fe1bbbe5ae35224a0dbd05aed9ccabccd241e8e6b60370484234b456266"}, 259 | {file = "pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b315e596282bbb5822d0c7ee9d255595bd7506d1cb20c2911a4da0b970187d3"}, 260 | {file = "pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1dfae24cf9921875ca0ca6a8ecb4bb2f13c855794ed0d468d6abbec6e6dcd44a"}, 261 | {file = "pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6dd8ecfde08d8bfadaea669e83c63939af76f4cf5538a72597016edfa3fad516"}, 262 | {file = "pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f593494876eae852dc98c43c6f260f45abdbfeec9e4324e31a481d948214764"}, 263 | {file = "pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:948b73114f47fd7016088e5186d13faf5e1b2fe83f5e320e371f035557fd264d"}, 264 | {file = "pydantic_core-2.33.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e11f3864eb516af21b01e25fac915a82e9ddad3bb0fb9e95a246067398b435a4"}, 265 | {file = "pydantic_core-2.33.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:549150be302428b56fdad0c23c2741dcdb5572413776826c965619a25d9c6bde"}, 266 | {file = "pydantic_core-2.33.1-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:495bc156026efafd9ef2d82372bd38afce78ddd82bf28ef5276c469e57c0c83e"}, 267 | {file = "pydantic_core-2.33.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ec79de2a8680b1a67a07490bddf9636d5c2fab609ba8c57597e855fa5fa4dacd"}, 268 | {file = "pydantic_core-2.33.1-cp313-cp313-win32.whl", hash = "sha256:ee12a7be1742f81b8a65b36c6921022301d466b82d80315d215c4c691724986f"}, 269 | {file = "pydantic_core-2.33.1-cp313-cp313-win_amd64.whl", hash = "sha256:ede9b407e39949d2afc46385ce6bd6e11588660c26f80576c11c958e6647bc40"}, 270 | {file = "pydantic_core-2.33.1-cp313-cp313-win_arm64.whl", hash = "sha256:aa687a23d4b7871a00e03ca96a09cad0f28f443690d300500603bd0adba4b523"}, 271 | {file = "pydantic_core-2.33.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:401d7b76e1000d0dd5538e6381d28febdcacb097c8d340dde7d7fc6e13e9f95d"}, 272 | {file = "pydantic_core-2.33.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7aeb055a42d734c0255c9e489ac67e75397d59c6fbe60d155851e9782f276a9c"}, 273 | {file = "pydantic_core-2.33.1-cp313-cp313t-win_amd64.whl", hash = "sha256:338ea9b73e6e109f15ab439e62cb3b78aa752c7fd9536794112e14bee02c8d18"}, 274 | {file = "pydantic_core-2.33.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5ab77f45d33d264de66e1884fca158bc920cb5e27fd0764a72f72f5756ae8bdb"}, 275 | {file = "pydantic_core-2.33.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e7aaba1b4b03aaea7bb59e1b5856d734be011d3e6d98f5bcaa98cb30f375f2ad"}, 276 | {file = "pydantic_core-2.33.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fb66263e9ba8fea2aa85e1e5578980d127fb37d7f2e292773e7bc3a38fb0c7b"}, 277 | {file = "pydantic_core-2.33.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3f2648b9262607a7fb41d782cc263b48032ff7a03a835581abbf7a3bec62bcf5"}, 278 | {file = "pydantic_core-2.33.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:723c5630c4259400818b4ad096735a829074601805d07f8cafc366d95786d331"}, 279 | {file = "pydantic_core-2.33.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d100e3ae783d2167782391e0c1c7a20a31f55f8015f3293647544df3f9c67824"}, 280 | {file = "pydantic_core-2.33.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177d50460bc976a0369920b6c744d927b0ecb8606fb56858ff542560251b19e5"}, 281 | {file = "pydantic_core-2.33.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a3edde68d1a1f9af1273b2fe798997b33f90308fb6d44d8550c89fc6a3647cf6"}, 282 | {file = "pydantic_core-2.33.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a62c3c3ef6a7e2c45f7853b10b5bc4ddefd6ee3cd31024754a1a5842da7d598d"}, 283 | {file = "pydantic_core-2.33.1-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:c91dbb0ab683fa0cd64a6e81907c8ff41d6497c346890e26b23de7ee55353f96"}, 284 | {file = "pydantic_core-2.33.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9f466e8bf0a62dc43e068c12166281c2eca72121dd2adc1040f3aa1e21ef8599"}, 285 | {file = "pydantic_core-2.33.1-cp39-cp39-win32.whl", hash = "sha256:ab0277cedb698749caada82e5d099dc9fed3f906a30d4c382d1a21725777a1e5"}, 286 | {file = "pydantic_core-2.33.1-cp39-cp39-win_amd64.whl", hash = "sha256:5773da0ee2d17136b1f1c6fbde543398d452a6ad2a7b54ea1033e2daa739b8d2"}, 287 | {file = "pydantic_core-2.33.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c834f54f8f4640fd7e4b193f80eb25a0602bba9e19b3cd2fc7ffe8199f5ae02"}, 288 | {file = "pydantic_core-2.33.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:049e0de24cf23766f12cc5cc71d8abc07d4a9deb9061b334b62093dedc7cb068"}, 289 | {file = "pydantic_core-2.33.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a28239037b3d6f16916a4c831a5a0eadf856bdd6d2e92c10a0da3a59eadcf3e"}, 290 | {file = "pydantic_core-2.33.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d3da303ab5f378a268fa7d45f37d7d85c3ec19769f28d2cc0c61826a8de21fe"}, 291 | {file = "pydantic_core-2.33.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:25626fb37b3c543818c14821afe0fd3830bc327a43953bc88db924b68c5723f1"}, 292 | {file = "pydantic_core-2.33.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3ab2d36e20fbfcce8f02d73c33a8a7362980cff717926bbae030b93ae46b56c7"}, 293 | {file = "pydantic_core-2.33.1-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:2f9284e11c751b003fd4215ad92d325d92c9cb19ee6729ebd87e3250072cdcde"}, 294 | {file = "pydantic_core-2.33.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:048c01eee07d37cbd066fc512b9d8b5ea88ceeb4e629ab94b3e56965ad655add"}, 295 | {file = "pydantic_core-2.33.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5ccd429694cf26af7997595d627dd2637e7932214486f55b8a357edaac9dae8c"}, 296 | {file = "pydantic_core-2.33.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3a371dc00282c4b84246509a5ddc808e61b9864aa1eae9ecc92bb1268b82db4a"}, 297 | {file = "pydantic_core-2.33.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:f59295ecc75a1788af8ba92f2e8c6eeaa5a94c22fc4d151e8d9638814f85c8fc"}, 298 | {file = "pydantic_core-2.33.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08530b8ac922003033f399128505f513e30ca770527cc8bbacf75a84fcc2c74b"}, 299 | {file = "pydantic_core-2.33.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bae370459da6a5466978c0eacf90690cb57ec9d533f8e63e564ef3822bfa04fe"}, 300 | {file = "pydantic_core-2.33.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e3de2777e3b9f4d603112f78006f4ae0acb936e95f06da6cb1a45fbad6bdb4b5"}, 301 | {file = "pydantic_core-2.33.1-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3a64e81e8cba118e108d7126362ea30e021291b7805d47e4896e52c791be2761"}, 302 | {file = "pydantic_core-2.33.1-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:52928d8c1b6bda03cc6d811e8923dffc87a2d3c8b3bfd2ce16471c7147a24850"}, 303 | {file = "pydantic_core-2.33.1-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:1b30d92c9412beb5ac6b10a3eb7ef92ccb14e3f2a8d7732e2d739f58b3aa7544"}, 304 | {file = "pydantic_core-2.33.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f995719707e0e29f0f41a8aa3bcea6e761a36c9136104d3189eafb83f5cec5e5"}, 305 | {file = "pydantic_core-2.33.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7edbc454a29fc6aeae1e1eecba4f07b63b8d76e76a748532233c4c167b4cb9ea"}, 306 | {file = "pydantic_core-2.33.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ad05b683963f69a1d5d2c2bdab1274a31221ca737dbbceaa32bcb67359453cdd"}, 307 | {file = "pydantic_core-2.33.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df6a94bf9452c6da9b5d76ed229a5683d0306ccb91cca8e1eea883189780d568"}, 308 | {file = "pydantic_core-2.33.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7965c13b3967909a09ecc91f21d09cfc4576bf78140b988904e94f130f188396"}, 309 | {file = "pydantic_core-2.33.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3f1fdb790440a34f6ecf7679e1863b825cb5ffde858a9197f851168ed08371e5"}, 310 | {file = "pydantic_core-2.33.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:5277aec8d879f8d05168fdd17ae811dd313b8ff894aeeaf7cd34ad28b4d77e33"}, 311 | {file = "pydantic_core-2.33.1-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8ab581d3530611897d863d1a649fb0644b860286b4718db919bfd51ece41f10b"}, 312 | {file = "pydantic_core-2.33.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0483847fa9ad5e3412265c1bd72aad35235512d9ce9d27d81a56d935ef489672"}, 313 | {file = "pydantic_core-2.33.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:de9e06abe3cc5ec6a2d5f75bc99b0bdca4f5c719a5b34026f8c57efbdecd2ee3"}, 314 | {file = "pydantic_core-2.33.1.tar.gz", hash = "sha256:bcc9c6fdb0ced789245b02b7d6603e17d1563064ddcfc36f046b61c0c05dd9df"}, 315 | ] 316 | 317 | [package.dependencies] 318 | typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" 319 | 320 | [[package]] 321 | name = "python-dotenv" 322 | version = "1.1.0" 323 | description = "Read key-value pairs from a .env file and set them as environment variables" 324 | optional = false 325 | python-versions = ">=3.9" 326 | groups = ["main"] 327 | files = [ 328 | {file = "python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d"}, 329 | {file = "python_dotenv-1.1.0.tar.gz", hash = "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5"}, 330 | ] 331 | 332 | [package.extras] 333 | cli = ["click (>=5.0)"] 334 | 335 | [[package]] 336 | name = "pyyaml" 337 | version = "6.0.2" 338 | description = "YAML parser and emitter for Python" 339 | optional = false 340 | python-versions = ">=3.8" 341 | groups = ["main"] 342 | files = [ 343 | {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, 344 | {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, 345 | {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, 346 | {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, 347 | {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, 348 | {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, 349 | {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, 350 | {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, 351 | {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, 352 | {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, 353 | {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, 354 | {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, 355 | {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, 356 | {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, 357 | {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, 358 | {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, 359 | {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, 360 | {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, 361 | {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, 362 | {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, 363 | {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, 364 | {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, 365 | {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, 366 | {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, 367 | {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, 368 | {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, 369 | {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, 370 | {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, 371 | {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, 372 | {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, 373 | {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, 374 | {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, 375 | {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, 376 | {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, 377 | {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, 378 | {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, 379 | {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, 380 | {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, 381 | {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, 382 | {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, 383 | {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, 384 | {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, 385 | {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, 386 | {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, 387 | {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, 388 | {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, 389 | {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, 390 | {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, 391 | {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, 392 | {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, 393 | {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, 394 | {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, 395 | {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, 396 | ] 397 | 398 | [[package]] 399 | name = "sniffio" 400 | version = "1.3.1" 401 | description = "Sniff out which async library your code is running under" 402 | optional = false 403 | python-versions = ">=3.7" 404 | groups = ["main"] 405 | files = [ 406 | {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, 407 | {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, 408 | ] 409 | 410 | [[package]] 411 | name = "starlette" 412 | version = "0.46.2" 413 | description = "The little ASGI library that shines." 414 | optional = false 415 | python-versions = ">=3.9" 416 | groups = ["main"] 417 | files = [ 418 | {file = "starlette-0.46.2-py3-none-any.whl", hash = "sha256:595633ce89f8ffa71a015caed34a5b2dc1c0cdb3f0f1fbd1e69339cf2abeec35"}, 419 | {file = "starlette-0.46.2.tar.gz", hash = "sha256:7f7361f34eed179294600af672f565727419830b54b7b084efe44bb82d2fccd5"}, 420 | ] 421 | 422 | [package.dependencies] 423 | anyio = ">=3.6.2,<5" 424 | 425 | [package.extras] 426 | full = ["httpx (>=0.27.0,<0.29.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.18)", "pyyaml"] 427 | 428 | [[package]] 429 | name = "typing-extensions" 430 | version = "4.13.2" 431 | description = "Backported and Experimental Type Hints for Python 3.8+" 432 | optional = false 433 | python-versions = ">=3.8" 434 | groups = ["main"] 435 | files = [ 436 | {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, 437 | {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, 438 | ] 439 | 440 | [[package]] 441 | name = "typing-inspection" 442 | version = "0.4.0" 443 | description = "Runtime typing introspection tools" 444 | optional = false 445 | python-versions = ">=3.9" 446 | groups = ["main"] 447 | files = [ 448 | {file = "typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f"}, 449 | {file = "typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122"}, 450 | ] 451 | 452 | [package.dependencies] 453 | typing-extensions = ">=4.12.0" 454 | 455 | [[package]] 456 | name = "uvicorn" 457 | version = "0.27.1" 458 | description = "The lightning-fast ASGI server." 459 | optional = false 460 | python-versions = ">=3.8" 461 | groups = ["main"] 462 | files = [ 463 | {file = "uvicorn-0.27.1-py3-none-any.whl", hash = "sha256:5c89da2f3895767472a35556e539fd59f7edbe9b1e9c0e1c99eebeadc61838e4"}, 464 | {file = "uvicorn-0.27.1.tar.gz", hash = "sha256:3d9a267296243532db80c83a959a3400502165ade2c1338dea4e67915fd4745a"}, 465 | ] 466 | 467 | [package.dependencies] 468 | click = ">=7.0" 469 | colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""} 470 | h11 = ">=0.8" 471 | httptools = {version = ">=0.5.0", optional = true, markers = "extra == \"standard\""} 472 | python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} 473 | pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} 474 | typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} 475 | uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "(sys_platform != \"win32\" and sys_platform != \"cygwin\") and platform_python_implementation != \"PyPy\" and extra == \"standard\""} 476 | watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} 477 | websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""} 478 | 479 | [package.extras] 480 | standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] 481 | 482 | [[package]] 483 | name = "uvloop" 484 | version = "0.21.0" 485 | description = "Fast implementation of asyncio event loop on top of libuv" 486 | optional = false 487 | python-versions = ">=3.8.0" 488 | groups = ["main"] 489 | markers = "(sys_platform != \"win32\" and sys_platform != \"cygwin\") and platform_python_implementation != \"PyPy\"" 490 | files = [ 491 | {file = "uvloop-0.21.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ec7e6b09a6fdded42403182ab6b832b71f4edaf7f37a9a0e371a01db5f0cb45f"}, 492 | {file = "uvloop-0.21.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:196274f2adb9689a289ad7d65700d37df0c0930fd8e4e743fa4834e850d7719d"}, 493 | {file = "uvloop-0.21.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f38b2e090258d051d68a5b14d1da7203a3c3677321cf32a95a6f4db4dd8b6f26"}, 494 | {file = "uvloop-0.21.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87c43e0f13022b998eb9b973b5e97200c8b90823454d4bc06ab33829e09fb9bb"}, 495 | {file = "uvloop-0.21.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:10d66943def5fcb6e7b37310eb6b5639fd2ccbc38df1177262b0640c3ca68c1f"}, 496 | {file = "uvloop-0.21.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:67dd654b8ca23aed0a8e99010b4c34aca62f4b7fce88f39d452ed7622c94845c"}, 497 | {file = "uvloop-0.21.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c0f3fa6200b3108919f8bdabb9a7f87f20e7097ea3c543754cabc7d717d95cf8"}, 498 | {file = "uvloop-0.21.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0878c2640cf341b269b7e128b1a5fed890adc4455513ca710d77d5e93aa6d6a0"}, 499 | {file = "uvloop-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9fb766bb57b7388745d8bcc53a359b116b8a04c83a2288069809d2b3466c37e"}, 500 | {file = "uvloop-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a375441696e2eda1c43c44ccb66e04d61ceeffcd76e4929e527b7fa401b90fb"}, 501 | {file = "uvloop-0.21.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:baa0e6291d91649c6ba4ed4b2f982f9fa165b5bbd50a9e203c416a2797bab3c6"}, 502 | {file = "uvloop-0.21.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4509360fcc4c3bd2c70d87573ad472de40c13387f5fda8cb58350a1d7475e58d"}, 503 | {file = "uvloop-0.21.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:359ec2c888397b9e592a889c4d72ba3d6befba8b2bb01743f72fffbde663b59c"}, 504 | {file = "uvloop-0.21.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f7089d2dc73179ce5ac255bdf37c236a9f914b264825fdaacaded6990a7fb4c2"}, 505 | {file = "uvloop-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baa4dcdbd9ae0a372f2167a207cd98c9f9a1ea1188a8a526431eef2f8116cc8d"}, 506 | {file = "uvloop-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86975dca1c773a2c9864f4c52c5a55631038e387b47eaf56210f873887b6c8dc"}, 507 | {file = "uvloop-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:461d9ae6660fbbafedd07559c6a2e57cd553b34b0065b6550685f6653a98c1cb"}, 508 | {file = "uvloop-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:183aef7c8730e54c9a3ee3227464daed66e37ba13040bb3f350bc2ddc040f22f"}, 509 | {file = "uvloop-0.21.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bfd55dfcc2a512316e65f16e503e9e450cab148ef11df4e4e679b5e8253a5281"}, 510 | {file = "uvloop-0.21.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:787ae31ad8a2856fc4e7c095341cccc7209bd657d0e71ad0dc2ea83c4a6fa8af"}, 511 | {file = "uvloop-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ee4d4ef48036ff6e5cfffb09dd192c7a5027153948d85b8da7ff705065bacc6"}, 512 | {file = "uvloop-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3df876acd7ec037a3d005b3ab85a7e4110422e4d9c1571d4fc89b0fc41b6816"}, 513 | {file = "uvloop-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd53ecc9a0f3d87ab847503c2e1552b690362e005ab54e8a48ba97da3924c0dc"}, 514 | {file = "uvloop-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a5c39f217ab3c663dc699c04cbd50c13813e31d917642d459fdcec07555cc553"}, 515 | {file = "uvloop-0.21.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:17df489689befc72c39a08359efac29bbee8eee5209650d4b9f34df73d22e414"}, 516 | {file = "uvloop-0.21.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc09f0ff191e61c2d592a752423c767b4ebb2986daa9ed62908e2b1b9a9ae206"}, 517 | {file = "uvloop-0.21.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0ce1b49560b1d2d8a2977e3ba4afb2414fb46b86a1b64056bc4ab929efdafbe"}, 518 | {file = "uvloop-0.21.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e678ad6fe52af2c58d2ae3c73dc85524ba8abe637f134bf3564ed07f555c5e79"}, 519 | {file = "uvloop-0.21.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:460def4412e473896ef179a1671b40c039c7012184b627898eea5072ef6f017a"}, 520 | {file = "uvloop-0.21.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:10da8046cc4a8f12c91a1c39d1dd1585c41162a15caaef165c2174db9ef18bdc"}, 521 | {file = "uvloop-0.21.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c097078b8031190c934ed0ebfee8cc5f9ba9642e6eb88322b9958b649750f72b"}, 522 | {file = "uvloop-0.21.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:46923b0b5ee7fc0020bef24afe7836cb068f5050ca04caf6b487c513dc1a20b2"}, 523 | {file = "uvloop-0.21.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53e420a3afe22cdcf2a0f4846e377d16e718bc70103d7088a4f7623567ba5fb0"}, 524 | {file = "uvloop-0.21.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88cb67cdbc0e483da00af0b2c3cdad4b7c61ceb1ee0f33fe00e09c81e3a6cb75"}, 525 | {file = "uvloop-0.21.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:221f4f2a1f46032b403bf3be628011caf75428ee3cc204a22addf96f586b19fd"}, 526 | {file = "uvloop-0.21.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2d1f581393673ce119355d56da84fe1dd9d2bb8b3d13ce792524e1607139feff"}, 527 | {file = "uvloop-0.21.0.tar.gz", hash = "sha256:3bf12b0fda68447806a7ad847bfa591613177275d35b6724b1ee573faa3704e3"}, 528 | ] 529 | 530 | [package.extras] 531 | dev = ["Cython (>=3.0,<4.0)", "setuptools (>=60)"] 532 | docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] 533 | test = ["aiohttp (>=3.10.5)", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=23.0.0,<23.1.0)", "pycodestyle (>=2.9.0,<2.10.0)"] 534 | 535 | [[package]] 536 | name = "watchfiles" 537 | version = "1.0.5" 538 | description = "Simple, modern and high performance file watching and code reload in python." 539 | optional = false 540 | python-versions = ">=3.9" 541 | groups = ["main"] 542 | files = [ 543 | {file = "watchfiles-1.0.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:5c40fe7dd9e5f81e0847b1ea64e1f5dd79dd61afbedb57759df06767ac719b40"}, 544 | {file = "watchfiles-1.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8c0db396e6003d99bb2d7232c957b5f0b5634bbd1b24e381a5afcc880f7373fb"}, 545 | {file = "watchfiles-1.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b551d4fb482fc57d852b4541f911ba28957d051c8776e79c3b4a51eb5e2a1b11"}, 546 | {file = "watchfiles-1.0.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:830aa432ba5c491d52a15b51526c29e4a4b92bf4f92253787f9726fe01519487"}, 547 | {file = "watchfiles-1.0.5-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a16512051a822a416b0d477d5f8c0e67b67c1a20d9acecb0aafa3aa4d6e7d256"}, 548 | {file = "watchfiles-1.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfe0cbc787770e52a96c6fda6726ace75be7f840cb327e1b08d7d54eadc3bc85"}, 549 | {file = "watchfiles-1.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d363152c5e16b29d66cbde8fa614f9e313e6f94a8204eaab268db52231fe5358"}, 550 | {file = "watchfiles-1.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ee32c9a9bee4d0b7bd7cbeb53cb185cf0b622ac761efaa2eba84006c3b3a614"}, 551 | {file = "watchfiles-1.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29c7fd632ccaf5517c16a5188e36f6612d6472ccf55382db6c7fe3fcccb7f59f"}, 552 | {file = "watchfiles-1.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e637810586e6fe380c8bc1b3910accd7f1d3a9a7262c8a78d4c8fb3ba6a2b3d"}, 553 | {file = "watchfiles-1.0.5-cp310-cp310-win32.whl", hash = "sha256:cd47d063fbeabd4c6cae1d4bcaa38f0902f8dc5ed168072874ea11d0c7afc1ff"}, 554 | {file = "watchfiles-1.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:86c0df05b47a79d80351cd179893f2f9c1b1cae49d96e8b3290c7f4bd0ca0a92"}, 555 | {file = "watchfiles-1.0.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:237f9be419e977a0f8f6b2e7b0475ababe78ff1ab06822df95d914a945eac827"}, 556 | {file = "watchfiles-1.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0da39ff917af8b27a4bdc5a97ac577552a38aac0d260a859c1517ea3dc1a7c4"}, 557 | {file = "watchfiles-1.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cfcb3952350e95603f232a7a15f6c5f86c5375e46f0bd4ae70d43e3e063c13d"}, 558 | {file = "watchfiles-1.0.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68b2dddba7a4e6151384e252a5632efcaa9bc5d1c4b567f3cb621306b2ca9f63"}, 559 | {file = "watchfiles-1.0.5-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:95cf944fcfc394c5f9de794ce581914900f82ff1f855326f25ebcf24d5397418"}, 560 | {file = "watchfiles-1.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ecf6cd9f83d7c023b1aba15d13f705ca7b7d38675c121f3cc4a6e25bd0857ee9"}, 561 | {file = "watchfiles-1.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:852de68acd6212cd6d33edf21e6f9e56e5d98c6add46f48244bd479d97c967c6"}, 562 | {file = "watchfiles-1.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5730f3aa35e646103b53389d5bc77edfbf578ab6dab2e005142b5b80a35ef25"}, 563 | {file = "watchfiles-1.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:18b3bd29954bc4abeeb4e9d9cf0b30227f0f206c86657674f544cb032296acd5"}, 564 | {file = "watchfiles-1.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ba5552a1b07c8edbf197055bc9d518b8f0d98a1c6a73a293bc0726dce068ed01"}, 565 | {file = "watchfiles-1.0.5-cp311-cp311-win32.whl", hash = "sha256:2f1fefb2e90e89959447bc0420fddd1e76f625784340d64a2f7d5983ef9ad246"}, 566 | {file = "watchfiles-1.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:b6e76ceb1dd18c8e29c73f47d41866972e891fc4cc7ba014f487def72c1cf096"}, 567 | {file = "watchfiles-1.0.5-cp311-cp311-win_arm64.whl", hash = "sha256:266710eb6fddc1f5e51843c70e3bebfb0f5e77cf4f27129278c70554104d19ed"}, 568 | {file = "watchfiles-1.0.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b5eb568c2aa6018e26da9e6c86f3ec3fd958cee7f0311b35c2630fa4217d17f2"}, 569 | {file = "watchfiles-1.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0a04059f4923ce4e856b4b4e5e783a70f49d9663d22a4c3b3298165996d1377f"}, 570 | {file = "watchfiles-1.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e380c89983ce6e6fe2dd1e1921b9952fb4e6da882931abd1824c092ed495dec"}, 571 | {file = "watchfiles-1.0.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fe43139b2c0fdc4a14d4f8d5b5d967f7a2777fd3d38ecf5b1ec669b0d7e43c21"}, 572 | {file = "watchfiles-1.0.5-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee0822ce1b8a14fe5a066f93edd20aada932acfe348bede8aa2149f1a4489512"}, 573 | {file = "watchfiles-1.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a0dbcb1c2d8f2ab6e0a81c6699b236932bd264d4cef1ac475858d16c403de74d"}, 574 | {file = "watchfiles-1.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a2014a2b18ad3ca53b1f6c23f8cd94a18ce930c1837bd891262c182640eb40a6"}, 575 | {file = "watchfiles-1.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10f6ae86d5cb647bf58f9f655fcf577f713915a5d69057a0371bc257e2553234"}, 576 | {file = "watchfiles-1.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1a7bac2bde1d661fb31f4d4e8e539e178774b76db3c2c17c4bb3e960a5de07a2"}, 577 | {file = "watchfiles-1.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ab626da2fc1ac277bbf752446470b367f84b50295264d2d313e28dc4405d663"}, 578 | {file = "watchfiles-1.0.5-cp312-cp312-win32.whl", hash = "sha256:9f4571a783914feda92018ef3901dab8caf5b029325b5fe4558c074582815249"}, 579 | {file = "watchfiles-1.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:360a398c3a19672cf93527f7e8d8b60d8275119c5d900f2e184d32483117a705"}, 580 | {file = "watchfiles-1.0.5-cp312-cp312-win_arm64.whl", hash = "sha256:1a2902ede862969077b97523987c38db28abbe09fb19866e711485d9fbf0d417"}, 581 | {file = "watchfiles-1.0.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0b289572c33a0deae62daa57e44a25b99b783e5f7aed81b314232b3d3c81a11d"}, 582 | {file = "watchfiles-1.0.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a056c2f692d65bf1e99c41045e3bdcaea3cb9e6b5a53dcaf60a5f3bd95fc9763"}, 583 | {file = "watchfiles-1.0.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9dca99744991fc9850d18015c4f0438865414e50069670f5f7eee08340d8b40"}, 584 | {file = "watchfiles-1.0.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:894342d61d355446d02cd3988a7326af344143eb33a2fd5d38482a92072d9563"}, 585 | {file = "watchfiles-1.0.5-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ab44e1580924d1ffd7b3938e02716d5ad190441965138b4aa1d1f31ea0877f04"}, 586 | {file = "watchfiles-1.0.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d6f9367b132078b2ceb8d066ff6c93a970a18c3029cea37bfd7b2d3dd2e5db8f"}, 587 | {file = "watchfiles-1.0.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2e55a9b162e06e3f862fb61e399fe9f05d908d019d87bf5b496a04ef18a970a"}, 588 | {file = "watchfiles-1.0.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0125f91f70e0732a9f8ee01e49515c35d38ba48db507a50c5bdcad9503af5827"}, 589 | {file = "watchfiles-1.0.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:13bb21f8ba3248386337c9fa51c528868e6c34a707f729ab041c846d52a0c69a"}, 590 | {file = "watchfiles-1.0.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:839ebd0df4a18c5b3c1b890145b5a3f5f64063c2a0d02b13c76d78fe5de34936"}, 591 | {file = "watchfiles-1.0.5-cp313-cp313-win32.whl", hash = "sha256:4a8ec1e4e16e2d5bafc9ba82f7aaecfeec990ca7cd27e84fb6f191804ed2fcfc"}, 592 | {file = "watchfiles-1.0.5-cp313-cp313-win_amd64.whl", hash = "sha256:f436601594f15bf406518af922a89dcaab416568edb6f65c4e5bbbad1ea45c11"}, 593 | {file = "watchfiles-1.0.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:2cfb371be97d4db374cba381b9f911dd35bb5f4c58faa7b8b7106c8853e5d225"}, 594 | {file = "watchfiles-1.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a3904d88955fda461ea2531fcf6ef73584ca921415d5cfa44457a225f4a42bc1"}, 595 | {file = "watchfiles-1.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b7a21715fb12274a71d335cff6c71fe7f676b293d322722fe708a9ec81d91f5"}, 596 | {file = "watchfiles-1.0.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dfd6ae1c385ab481766b3c61c44aca2b3cd775f6f7c0fa93d979ddec853d29d5"}, 597 | {file = "watchfiles-1.0.5-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b659576b950865fdad31fa491d31d37cf78b27113a7671d39f919828587b429b"}, 598 | {file = "watchfiles-1.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1909e0a9cd95251b15bff4261de5dd7550885bd172e3536824bf1cf6b121e200"}, 599 | {file = "watchfiles-1.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:832ccc221927c860e7286c55c9b6ebcc0265d5e072f49c7f6456c7798d2b39aa"}, 600 | {file = "watchfiles-1.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85fbb6102b3296926d0c62cfc9347f6237fb9400aecd0ba6bbda94cae15f2b3b"}, 601 | {file = "watchfiles-1.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:15ac96dd567ad6c71c71f7b2c658cb22b7734901546cd50a475128ab557593ca"}, 602 | {file = "watchfiles-1.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4b6227351e11c57ae997d222e13f5b6f1f0700d84b8c52304e8675d33a808382"}, 603 | {file = "watchfiles-1.0.5-cp39-cp39-win32.whl", hash = "sha256:974866e0db748ebf1eccab17862bc0f0303807ed9cda465d1324625b81293a18"}, 604 | {file = "watchfiles-1.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:9848b21ae152fe79c10dd0197304ada8f7b586d3ebc3f27f43c506e5a52a863c"}, 605 | {file = "watchfiles-1.0.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f59b870db1f1ae5a9ac28245707d955c8721dd6565e7f411024fa374b5362d1d"}, 606 | {file = "watchfiles-1.0.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9475b0093767e1475095f2aeb1d219fb9664081d403d1dff81342df8cd707034"}, 607 | {file = "watchfiles-1.0.5-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc533aa50664ebd6c628b2f30591956519462f5d27f951ed03d6c82b2dfd9965"}, 608 | {file = "watchfiles-1.0.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fed1cd825158dcaae36acce7b2db33dcbfd12b30c34317a88b8ed80f0541cc57"}, 609 | {file = "watchfiles-1.0.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:554389562c29c2c182e3908b149095051f81d28c2fec79ad6c8997d7d63e0009"}, 610 | {file = "watchfiles-1.0.5-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a74add8d7727e6404d5dc4dcd7fac65d4d82f95928bbee0cf5414c900e86773e"}, 611 | {file = "watchfiles-1.0.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb1489f25b051a89fae574505cc26360c8e95e227a9500182a7fe0afcc500ce0"}, 612 | {file = "watchfiles-1.0.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0901429650652d3f0da90bad42bdafc1f9143ff3605633c455c999a2d786cac"}, 613 | {file = "watchfiles-1.0.5.tar.gz", hash = "sha256:b7529b5dcc114679d43827d8c35a07c493ad6f083633d573d81c660abc5979e9"}, 614 | ] 615 | 616 | [package.dependencies] 617 | anyio = ">=3.0.0" 618 | 619 | [[package]] 620 | name = "websockets" 621 | version = "15.0.1" 622 | description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" 623 | optional = false 624 | python-versions = ">=3.9" 625 | groups = ["main"] 626 | files = [ 627 | {file = "websockets-15.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d63efaa0cd96cf0c5fe4d581521d9fa87744540d4bc999ae6e08595a1014b45b"}, 628 | {file = "websockets-15.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac60e3b188ec7574cb761b08d50fcedf9d77f1530352db4eef1707fe9dee7205"}, 629 | {file = "websockets-15.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5756779642579d902eed757b21b0164cd6fe338506a8083eb58af5c372e39d9a"}, 630 | {file = "websockets-15.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fdfe3e2a29e4db3659dbd5bbf04560cea53dd9610273917799f1cde46aa725e"}, 631 | {file = "websockets-15.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c2529b320eb9e35af0fa3016c187dffb84a3ecc572bcee7c3ce302bfeba52bf"}, 632 | {file = "websockets-15.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac1e5c9054fe23226fb11e05a6e630837f074174c4c2f0fe442996112a6de4fb"}, 633 | {file = "websockets-15.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5df592cd503496351d6dc14f7cdad49f268d8e618f80dce0cd5a36b93c3fc08d"}, 634 | {file = "websockets-15.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0a34631031a8f05657e8e90903e656959234f3a04552259458aac0b0f9ae6fd9"}, 635 | {file = "websockets-15.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3d00075aa65772e7ce9e990cab3ff1de702aa09be3940d1dc88d5abf1ab8a09c"}, 636 | {file = "websockets-15.0.1-cp310-cp310-win32.whl", hash = "sha256:1234d4ef35db82f5446dca8e35a7da7964d02c127b095e172e54397fb6a6c256"}, 637 | {file = "websockets-15.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:39c1fec2c11dc8d89bba6b2bf1556af381611a173ac2b511cf7231622058af41"}, 638 | {file = "websockets-15.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:823c248b690b2fd9303ba00c4f66cd5e2d8c3ba4aa968b2779be9532a4dad431"}, 639 | {file = "websockets-15.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678999709e68425ae2593acf2e3ebcbcf2e69885a5ee78f9eb80e6e371f1bf57"}, 640 | {file = "websockets-15.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d50fd1ee42388dcfb2b3676132c78116490976f1300da28eb629272d5d93e905"}, 641 | {file = "websockets-15.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d99e5546bf73dbad5bf3547174cd6cb8ba7273062a23808ffea025ecb1cf8562"}, 642 | {file = "websockets-15.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66dd88c918e3287efc22409d426c8f729688d89a0c587c88971a0faa2c2f3792"}, 643 | {file = "websockets-15.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dd8327c795b3e3f219760fa603dcae1dcc148172290a8ab15158cf85a953413"}, 644 | {file = "websockets-15.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8fdc51055e6ff4adeb88d58a11042ec9a5eae317a0a53d12c062c8a8865909e8"}, 645 | {file = "websockets-15.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:693f0192126df6c2327cce3baa7c06f2a117575e32ab2308f7f8216c29d9e2e3"}, 646 | {file = "websockets-15.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:54479983bd5fb469c38f2f5c7e3a24f9a4e70594cd68cd1fa6b9340dadaff7cf"}, 647 | {file = "websockets-15.0.1-cp311-cp311-win32.whl", hash = "sha256:16b6c1b3e57799b9d38427dda63edcbe4926352c47cf88588c0be4ace18dac85"}, 648 | {file = "websockets-15.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:27ccee0071a0e75d22cb35849b1db43f2ecd3e161041ac1ee9d2352ddf72f065"}, 649 | {file = "websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3"}, 650 | {file = "websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665"}, 651 | {file = "websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2"}, 652 | {file = "websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215"}, 653 | {file = "websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5"}, 654 | {file = "websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65"}, 655 | {file = "websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe"}, 656 | {file = "websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4"}, 657 | {file = "websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597"}, 658 | {file = "websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9"}, 659 | {file = "websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7"}, 660 | {file = "websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931"}, 661 | {file = "websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675"}, 662 | {file = "websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151"}, 663 | {file = "websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22"}, 664 | {file = "websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f"}, 665 | {file = "websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8"}, 666 | {file = "websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375"}, 667 | {file = "websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d"}, 668 | {file = "websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4"}, 669 | {file = "websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa"}, 670 | {file = "websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561"}, 671 | {file = "websockets-15.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5f4c04ead5aed67c8a1a20491d54cdfba5884507a48dd798ecaf13c74c4489f5"}, 672 | {file = "websockets-15.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abdc0c6c8c648b4805c5eacd131910d2a7f6455dfd3becab248ef108e89ab16a"}, 673 | {file = "websockets-15.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a625e06551975f4b7ea7102bc43895b90742746797e2e14b70ed61c43a90f09b"}, 674 | {file = "websockets-15.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d591f8de75824cbb7acad4e05d2d710484f15f29d4a915092675ad3456f11770"}, 675 | {file = "websockets-15.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47819cea040f31d670cc8d324bb6435c6f133b8c7a19ec3d61634e62f8d8f9eb"}, 676 | {file = "websockets-15.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac017dd64572e5c3bd01939121e4d16cf30e5d7e110a119399cf3133b63ad054"}, 677 | {file = "websockets-15.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4a9fac8e469d04ce6c25bb2610dc535235bd4aa14996b4e6dbebf5e007eba5ee"}, 678 | {file = "websockets-15.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363c6f671b761efcb30608d24925a382497c12c506b51661883c3e22337265ed"}, 679 | {file = "websockets-15.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2034693ad3097d5355bfdacfffcbd3ef5694f9718ab7f29c29689a9eae841880"}, 680 | {file = "websockets-15.0.1-cp39-cp39-win32.whl", hash = "sha256:3b1ac0d3e594bf121308112697cf4b32be538fb1444468fb0a6ae4feebc83411"}, 681 | {file = "websockets-15.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:b7643a03db5c95c799b89b31c036d5f27eeb4d259c798e878d6937d71832b1e4"}, 682 | {file = "websockets-15.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0c9e74d766f2818bb95f84c25be4dea09841ac0f734d1966f415e4edfc4ef1c3"}, 683 | {file = "websockets-15.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1009ee0c7739c08a0cd59de430d6de452a55e42d6b522de7aa15e6f67db0b8e1"}, 684 | {file = "websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d1f20b1c7a2fa82367e04982e708723ba0e7b8d43aa643d3dcd404d74f1475"}, 685 | {file = "websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f29d80eb9a9263b8d109135351caf568cc3f80b9928bccde535c235de55c22d9"}, 686 | {file = "websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b359ed09954d7c18bbc1680f380c7301f92c60bf924171629c5db97febb12f04"}, 687 | {file = "websockets-15.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:cad21560da69f4ce7658ca2cb83138fb4cf695a2ba3e475e0559e05991aa8122"}, 688 | {file = "websockets-15.0.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7f493881579c90fc262d9cdbaa05a6b54b3811c2f300766748db79f098db9940"}, 689 | {file = "websockets-15.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:47b099e1f4fbc95b701b6e85768e1fcdaf1630f3cbe4765fa216596f12310e2e"}, 690 | {file = "websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67f2b6de947f8c757db2db9c71527933ad0019737ec374a8a6be9a956786aaf9"}, 691 | {file = "websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d08eb4c2b7d6c41da6ca0600c077e93f5adcfd979cd777d747e9ee624556da4b"}, 692 | {file = "websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b826973a4a2ae47ba357e4e82fa44a463b8f168e1ca775ac64521442b19e87f"}, 693 | {file = "websockets-15.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:21c1fa28a6a7e3cbdc171c694398b6df4744613ce9b36b1a498e816787e28123"}, 694 | {file = "websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f"}, 695 | {file = "websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee"}, 696 | ] 697 | 698 | [metadata] 699 | lock-version = "2.1" 700 | python-versions = "^3.10" 701 | content-hash = "8ead41f76b3283b09f5d79dfa881bb46f7a3b9e0a6b0581da98e6bbc566a12e5" 702 | -------------------------------------------------------------------------------- /projects/my_fastapi_project/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "my_fastapi_project" 3 | version = "0.0.1" 4 | description = "an example FastAPI project" 5 | authors = ["David Vujic"] 6 | packages = [ 7 | {include = "example/log", from = "../../components"}, 8 | {include = "example/greeting", from = "../../components"}, 9 | {include = "example/greet_api", from = "../../bases"}, 10 | ] 11 | 12 | [tool.poetry.dependencies] 13 | python = "^3.10" 14 | fastapi = "^0.115.12" 15 | uvicorn = {extras = ["standard"], version = "^0.27.1"} 16 | 17 | [build-system] 18 | requires = ["poetry-core"] 19 | build-backend = "poetry.core.masonry.api" 20 | -------------------------------------------------------------------------------- /projects/my_gcp_function_project/.gitignore: -------------------------------------------------------------------------------- 1 | requirements.txt 2 | main.py -------------------------------------------------------------------------------- /projects/my_gcp_function_project/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: add-gcp-entrypoint export-deps build-gcp-project gcp-package 2 | 3 | PROJECT_NAME = my_gcp_function_project-0.1.0 4 | 5 | add-gcp-entrypoint: 6 | cp ../../bases/example/greet_gcp_function/__init__.py ./main.py 7 | 8 | export-deps: 9 | poetry export -f requirements.txt --output requirements.txt 10 | 11 | build-gcp-project: export-deps add-gcp-entrypoint 12 | poetry build-project 13 | 14 | gcp-package: build-gcp-project 15 | mv dist/$(PROJECT_NAME)-py3-none-any.whl dist/function.zip 16 | -------------------------------------------------------------------------------- /projects/my_gcp_function_project/poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 2.0.0 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "blinker" 5 | version = "1.9.0" 6 | description = "Fast, simple object-to-object and broadcast signaling" 7 | optional = false 8 | python-versions = ">=3.9" 9 | groups = ["main"] 10 | files = [ 11 | {file = "blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc"}, 12 | {file = "blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf"}, 13 | ] 14 | 15 | [[package]] 16 | name = "click" 17 | version = "8.1.8" 18 | description = "Composable command line interface toolkit" 19 | optional = false 20 | python-versions = ">=3.7" 21 | groups = ["main"] 22 | files = [ 23 | {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, 24 | {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, 25 | ] 26 | 27 | [package.dependencies] 28 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 29 | 30 | [[package]] 31 | name = "cloudevents" 32 | version = "1.11.0" 33 | description = "CloudEvents Python SDK" 34 | optional = false 35 | python-versions = "*" 36 | groups = ["main"] 37 | files = [ 38 | {file = "cloudevents-1.11.0-py3-none-any.whl", hash = "sha256:77edb4f2b01f405c44ea77120c3213418dbc63d8859f98e9e85de875502b8a76"}, 39 | {file = "cloudevents-1.11.0.tar.gz", hash = "sha256:5be990583e99f3b08af5a709460e20b25cb169270227957a20b47a6ec8635e66"}, 40 | ] 41 | 42 | [package.dependencies] 43 | deprecation = ">=2.0,<3.0" 44 | 45 | [package.extras] 46 | pydantic = ["pydantic (>=1.0.0,<3.0)"] 47 | 48 | [[package]] 49 | name = "colorama" 50 | version = "0.4.6" 51 | description = "Cross-platform colored terminal text." 52 | optional = false 53 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 54 | groups = ["main"] 55 | markers = "platform_system == \"Windows\"" 56 | files = [ 57 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, 58 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, 59 | ] 60 | 61 | [[package]] 62 | name = "deprecation" 63 | version = "2.1.0" 64 | description = "A library to handle automated deprecations" 65 | optional = false 66 | python-versions = "*" 67 | groups = ["main"] 68 | files = [ 69 | {file = "deprecation-2.1.0-py2.py3-none-any.whl", hash = "sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a"}, 70 | {file = "deprecation-2.1.0.tar.gz", hash = "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff"}, 71 | ] 72 | 73 | [package.dependencies] 74 | packaging = "*" 75 | 76 | [[package]] 77 | name = "flask" 78 | version = "3.1.0" 79 | description = "A simple framework for building complex web applications." 80 | optional = false 81 | python-versions = ">=3.9" 82 | groups = ["main"] 83 | files = [ 84 | {file = "flask-3.1.0-py3-none-any.whl", hash = "sha256:d667207822eb83f1c4b50949b1623c8fc8d51f2341d65f72e1a1815397551136"}, 85 | {file = "flask-3.1.0.tar.gz", hash = "sha256:5f873c5184c897c8d9d1b05df1e3d01b14910ce69607a117bd3277098a5836ac"}, 86 | ] 87 | 88 | [package.dependencies] 89 | blinker = ">=1.9" 90 | click = ">=8.1.3" 91 | itsdangerous = ">=2.2" 92 | Jinja2 = ">=3.1.2" 93 | Werkzeug = ">=3.1" 94 | 95 | [package.extras] 96 | async = ["asgiref (>=3.2)"] 97 | dotenv = ["python-dotenv"] 98 | 99 | [[package]] 100 | name = "functions-framework" 101 | version = "3.8.2" 102 | description = "An open source FaaS (Function as a service) framework for writing portable Python functions -- brought to you by the Google Cloud Functions team." 103 | optional = false 104 | python-versions = "<4,>=3.5" 105 | groups = ["main"] 106 | files = [ 107 | {file = "functions_framework-3.8.2-py3-none-any.whl", hash = "sha256:ecbe8e4566efca9ed1718f210ac92d47fc47ec3a448d2bca3b4bb5888bceca08"}, 108 | {file = "functions_framework-3.8.2.tar.gz", hash = "sha256:109bcdca01244067052a605536b44d042903b3805d093cd32e343ba5affffc90"}, 109 | ] 110 | 111 | [package.dependencies] 112 | click = ">=7.0,<9.0" 113 | cloudevents = ">=1.2.0,<2.0.0" 114 | flask = ">=1.0,<4.0" 115 | gunicorn = {version = ">=22.0.0", markers = "platform_system != \"Windows\""} 116 | watchdog = ">=1.0.0" 117 | Werkzeug = ">=0.14,<4.0.0" 118 | 119 | [[package]] 120 | name = "gunicorn" 121 | version = "23.0.0" 122 | description = "WSGI HTTP Server for UNIX" 123 | optional = false 124 | python-versions = ">=3.7" 125 | groups = ["main"] 126 | markers = "platform_system != \"Windows\"" 127 | files = [ 128 | {file = "gunicorn-23.0.0-py3-none-any.whl", hash = "sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d"}, 129 | {file = "gunicorn-23.0.0.tar.gz", hash = "sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec"}, 130 | ] 131 | 132 | [package.dependencies] 133 | packaging = "*" 134 | 135 | [package.extras] 136 | eventlet = ["eventlet (>=0.24.1,!=0.36.0)"] 137 | gevent = ["gevent (>=1.4.0)"] 138 | setproctitle = ["setproctitle"] 139 | testing = ["coverage", "eventlet", "gevent", "pytest", "pytest-cov"] 140 | tornado = ["tornado (>=0.2)"] 141 | 142 | [[package]] 143 | name = "itsdangerous" 144 | version = "2.2.0" 145 | description = "Safely pass data to untrusted environments and back." 146 | optional = false 147 | python-versions = ">=3.8" 148 | groups = ["main"] 149 | files = [ 150 | {file = "itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef"}, 151 | {file = "itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"}, 152 | ] 153 | 154 | [[package]] 155 | name = "jinja2" 156 | version = "3.1.6" 157 | description = "A very fast and expressive template engine." 158 | optional = false 159 | python-versions = ">=3.7" 160 | groups = ["main"] 161 | files = [ 162 | {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, 163 | {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, 164 | ] 165 | 166 | [package.dependencies] 167 | MarkupSafe = ">=2.0" 168 | 169 | [package.extras] 170 | i18n = ["Babel (>=2.7)"] 171 | 172 | [[package]] 173 | name = "markupsafe" 174 | version = "3.0.2" 175 | description = "Safely add untrusted strings to HTML/XML markup." 176 | optional = false 177 | python-versions = ">=3.9" 178 | groups = ["main"] 179 | files = [ 180 | {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, 181 | {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, 182 | {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"}, 183 | {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"}, 184 | {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"}, 185 | {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"}, 186 | {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"}, 187 | {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"}, 188 | {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"}, 189 | {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"}, 190 | {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}, 191 | {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}, 192 | {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}, 193 | {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}, 194 | {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}, 195 | {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}, 196 | {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}, 197 | {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}, 198 | {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}, 199 | {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}, 200 | {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"}, 201 | {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"}, 202 | {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"}, 203 | {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"}, 204 | {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"}, 205 | {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"}, 206 | {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"}, 207 | {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}, 208 | {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}, 209 | {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}, 210 | {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"}, 211 | {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"}, 212 | {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"}, 213 | {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"}, 214 | {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"}, 215 | {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"}, 216 | {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"}, 217 | {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"}, 218 | {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"}, 219 | {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"}, 220 | {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"}, 221 | {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"}, 222 | {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"}, 223 | {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"}, 224 | {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"}, 225 | {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"}, 226 | {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"}, 227 | {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"}, 228 | {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"}, 229 | {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"}, 230 | {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"}, 231 | {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"}, 232 | {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"}, 233 | {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"}, 234 | {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"}, 235 | {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"}, 236 | {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"}, 237 | {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"}, 238 | {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"}, 239 | {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"}, 240 | {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, 241 | ] 242 | 243 | [[package]] 244 | name = "packaging" 245 | version = "24.2" 246 | description = "Core utilities for Python packages" 247 | optional = false 248 | python-versions = ">=3.8" 249 | groups = ["main"] 250 | files = [ 251 | {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, 252 | {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, 253 | ] 254 | 255 | [[package]] 256 | name = "watchdog" 257 | version = "6.0.0" 258 | description = "Filesystem events monitoring" 259 | optional = false 260 | python-versions = ">=3.9" 261 | groups = ["main"] 262 | files = [ 263 | {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26"}, 264 | {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112"}, 265 | {file = "watchdog-6.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3"}, 266 | {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c"}, 267 | {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2"}, 268 | {file = "watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c"}, 269 | {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948"}, 270 | {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860"}, 271 | {file = "watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0"}, 272 | {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c"}, 273 | {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134"}, 274 | {file = "watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b"}, 275 | {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8"}, 276 | {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a"}, 277 | {file = "watchdog-6.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c"}, 278 | {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881"}, 279 | {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11"}, 280 | {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa"}, 281 | {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e"}, 282 | {file = "watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13"}, 283 | {file = "watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379"}, 284 | {file = "watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e"}, 285 | {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f"}, 286 | {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26"}, 287 | {file = "watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c"}, 288 | {file = "watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2"}, 289 | {file = "watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a"}, 290 | {file = "watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680"}, 291 | {file = "watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f"}, 292 | {file = "watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282"}, 293 | ] 294 | 295 | [package.extras] 296 | watchmedo = ["PyYAML (>=3.10)"] 297 | 298 | [[package]] 299 | name = "werkzeug" 300 | version = "3.1.3" 301 | description = "The comprehensive WSGI web application library." 302 | optional = false 303 | python-versions = ">=3.9" 304 | groups = ["main"] 305 | files = [ 306 | {file = "werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e"}, 307 | {file = "werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746"}, 308 | ] 309 | 310 | [package.dependencies] 311 | MarkupSafe = ">=2.1.1" 312 | 313 | [package.extras] 314 | watchdog = ["watchdog (>=2.3)"] 315 | 316 | [metadata] 317 | lock-version = "2.1" 318 | python-versions = "^3.10" 319 | content-hash = "e2f581924dbb1c05f36ad61f6284d0d83e6d0c1b8efc4cc83c37425112725254" 320 | -------------------------------------------------------------------------------- /projects/my_gcp_function_project/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "my_gcp_function_project" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ['David Vujic'] 6 | license = "" 7 | 8 | packages = [ 9 | {include = "example/log", from = "../../components"}, 10 | {include = "example/greeting", from = "../../components"}, 11 | {include = "example/greet_gcp_function", from = "../../bases"} 12 | ] 13 | 14 | include = ["main.py", "requirements.txt"] # added by the build process 15 | 16 | [tool.poetry.dependencies] 17 | python = "^3.10" 18 | functions-framework = "^3.5.0" 19 | 20 | [tool.poetry.group.dev.dependencies] 21 | 22 | [build-system] 23 | requires = ["poetry-core>=1.0.0"] 24 | build-backend = "poetry.core.masonry.api" 25 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "Python Polylith Example" 3 | version = "1.0.0" 4 | description = "A Python Polylith example code repo" 5 | authors = ["David Vujic"] 6 | homepage = "https://github.com/davidvujic/python-polylith-example" 7 | repository = "https://github.com/davidvujic/python-polylith-example" 8 | packages = [ 9 | {include = "example/consumer",from = "bases"}, 10 | {include = "example/greet_api", from = "bases"}, 11 | {include = "example/greet_aws_lambda", from = "bases"}, 12 | {include = "example/greet_gcp_function", from = "bases"}, 13 | {include = "example/message_api", from = "bases"}, 14 | {include = "example/database", from = "components"}, 15 | {include = "example/dictionaries",from = "components"}, 16 | {include = "example/greeting", from = "components"}, 17 | {include = "example/kafka",from = "components"}, 18 | {include = "example/log", from = "components"}, 19 | {include = "example/message", from = "components"}, 20 | {include = "example/schema", from = "components"}, 21 | {include = "development"}, 22 | ] 23 | 24 | [tool.poetry.dependencies] 25 | python = "^3.10" 26 | fastapi = "^0.115.12" 27 | uvicorn = {extras = ["standard"], version = "^0.27.1"} 28 | functions-framework = "^3.5.0" 29 | sqlalchemy = "^2.0.28" 30 | confluent-kafka = "^2.3.0" 31 | 32 | [tool.poetry.group.dev.dependencies] 33 | black = "^24.4.2" 34 | isort = "^5.13.2" 35 | mypy = "^1.8.0" 36 | flake8 = "^7.0.0" 37 | pytest = "^8.2.2" 38 | 39 | [tool.isort] 40 | profile = "black" 41 | 42 | [build-system] 43 | requires = ["poetry-core"] 44 | build-backend = "poetry.core.masonry.api" 45 | 46 | [tool.pytest.ini_options] 47 | addopts = "-vv" 48 | -------------------------------------------------------------------------------- /test/bases/example/consumer/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidVujic/python-polylith-example/913cd45599b534100c5cbbf41a725b09d8cb00b3/test/bases/example/consumer/__init__.py -------------------------------------------------------------------------------- /test/bases/example/consumer/test_core.py: -------------------------------------------------------------------------------- 1 | from example.consumer import core 2 | 3 | 4 | def test_sample(): 5 | assert core is not None 6 | -------------------------------------------------------------------------------- /test/components/example/database/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidVujic/python-polylith-example/913cd45599b534100c5cbbf41a725b09d8cb00b3/test/components/example/database/__init__.py -------------------------------------------------------------------------------- /test/components/example/database/test_core.py: -------------------------------------------------------------------------------- 1 | from example.database import core 2 | 3 | 4 | def test_sample(): 5 | assert core is not None 6 | -------------------------------------------------------------------------------- /test/components/example/dictionaries/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidVujic/python-polylith-example/913cd45599b534100c5cbbf41a725b09d8cb00b3/test/components/example/dictionaries/__init__.py -------------------------------------------------------------------------------- /test/components/example/dictionaries/test_core.py: -------------------------------------------------------------------------------- 1 | from example.dictionaries.core import omit, pick 2 | 3 | from development.ci.utils import hello 4 | 5 | 6 | def test_pick(fake_data): 7 | assert pick(fake_data, {"good"}) == {"good": ["morning", "day", "afternoon"]} 8 | 9 | 10 | def test_omit(fake_data): 11 | assert omit(fake_data, {"good"}) == {"hello": "world"} 12 | 13 | 14 | def test_environment_customization(set_some_environment_variables): 15 | import os 16 | 17 | data = os.getenv("HELLO") 18 | 19 | assert data == "world" 20 | 21 | 22 | def test_shared_code(): 23 | assert hello() == "world" 24 | -------------------------------------------------------------------------------- /test/components/example/greeting/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidVujic/python-polylith-example/913cd45599b534100c5cbbf41a725b09d8cb00b3/test/components/example/greeting/__init__.py -------------------------------------------------------------------------------- /test/components/example/greeting/test_core.py: -------------------------------------------------------------------------------- 1 | from example.greeting import core 2 | 3 | 4 | def test_sample(): 5 | assert core.hello_world() == "HELLO WORLD" 6 | -------------------------------------------------------------------------------- /test/components/example/kafka/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidVujic/python-polylith-example/913cd45599b534100c5cbbf41a725b09d8cb00b3/test/components/example/kafka/__init__.py -------------------------------------------------------------------------------- /test/components/example/kafka/test_core.py: -------------------------------------------------------------------------------- 1 | from example.kafka import core 2 | 3 | 4 | def test_sample(): 5 | assert core is not None 6 | -------------------------------------------------------------------------------- /test/components/example/log/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidVujic/python-polylith-example/913cd45599b534100c5cbbf41a725b09d8cb00b3/test/components/example/log/__init__.py -------------------------------------------------------------------------------- /test/components/example/log/test_core.py: -------------------------------------------------------------------------------- 1 | from example.log import core 2 | 3 | 4 | def test_sample(): 5 | assert core is not None 6 | -------------------------------------------------------------------------------- /test/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.fixture 5 | def set_some_environment_variables(monkeypatch): 6 | monkeypatch.setenv("HELLO", "world") 7 | 8 | 9 | @pytest.fixture 10 | def fake_data(): 11 | return {"hello": "world", "good": ["morning", "day", "afternoon"]} 12 | -------------------------------------------------------------------------------- /workspace.toml: -------------------------------------------------------------------------------- 1 | [tool.polylith] 2 | namespace = "example" 3 | 4 | [tool.polylith.structure] 5 | theme = "loose" 6 | 7 | [tool.polylith.tag.patterns] 8 | stable = "stable-*" 9 | release = "v[0-9]-*" 10 | 11 | [tool.polylith.test] 12 | enabled = true 13 | --------------------------------------------------------------------------------