diff --git a/.flox/env/manifest.lock b/.flox/env/manifest.lock index ff15369b9..964e64525 100644 --- a/.flox/env/manifest.lock +++ b/.flox/env/manifest.lock @@ -12,6 +12,9 @@ "pulumi-python": { "pkg-path": "pulumiPackages.pulumi-python" }, + "pulumictl": { + "pkg-path": "pulumictl" + }, "ruff": { "pkg-path": "ruff" }, @@ -395,6 +398,126 @@ "group": "toplevel", "priority": 5 }, + { + "attr_path": "pulumictl", + "broken": false, + "derivation": "/nix/store/kx43jzcfslw28byvs6h5ngsgl432pvvv-pulumictl-0.0.49.drv", + "description": "Swiss Army Knife for Pulumi Development", + "install_id": "pulumictl", + "license": "Apache-2.0", + "locked_url": "https://github.com/flox/nixpkgs?rev=979daf34c8cacebcd917d540070b52a3c2b9b16e", + "name": "pulumictl-0.0.49", + "pname": "pulumictl", + "rev": "979daf34c8cacebcd917d540070b52a3c2b9b16e", + "rev_count": 793735, + "rev_date": "2025-05-04T03:14:55Z", + "scrape_date": "2025-05-05T04:19:37.687142Z", + "stabilities": [ + "staging", + "unstable" + ], + "unfree": false, + "version": "0.0.49", + "outputs_to_install": [ + "out" + ], + "outputs": { + "out": "/nix/store/ny69c9bfkf4w179240ch45injfb2ajqr-pulumictl-0.0.49" + }, + "system": "aarch64-darwin", + "group": "toplevel", + "priority": 5 + }, + { + "attr_path": "pulumictl", + "broken": false, + "derivation": "/nix/store/www9nfncvv7l339n8dks22x5vs5lz1mk-pulumictl-0.0.49.drv", + "description": "Swiss Army Knife for Pulumi Development", + "install_id": "pulumictl", + "license": "Apache-2.0", + "locked_url": "https://github.com/flox/nixpkgs?rev=979daf34c8cacebcd917d540070b52a3c2b9b16e", + "name": "pulumictl-0.0.49", + "pname": "pulumictl", + "rev": "979daf34c8cacebcd917d540070b52a3c2b9b16e", + "rev_count": 793735, + "rev_date": "2025-05-04T03:14:55Z", + "scrape_date": "2025-05-05T04:37:42.118866Z", + "stabilities": [ + "staging", + "unstable" + ], + "unfree": false, + "version": "0.0.49", + "outputs_to_install": [ + "out" + ], + "outputs": { + "out": "/nix/store/xpdh5dijdki4cngh7k7n4rg84i6c28zs-pulumictl-0.0.49" + }, + "system": "aarch64-linux", + "group": "toplevel", + "priority": 5 + }, + { + "attr_path": "pulumictl", + "broken": false, + "derivation": "/nix/store/17wf5x1kk3v5ch5npwhamnix629y07wg-pulumictl-0.0.49.drv", + "description": "Swiss Army Knife for Pulumi Development", + "install_id": "pulumictl", + "license": "Apache-2.0", + "locked_url": "https://github.com/flox/nixpkgs?rev=979daf34c8cacebcd917d540070b52a3c2b9b16e", + "name": "pulumictl-0.0.49", + "pname": "pulumictl", + "rev": "979daf34c8cacebcd917d540070b52a3c2b9b16e", + "rev_count": 793735, + "rev_date": "2025-05-04T03:14:55Z", + "scrape_date": "2025-05-05T04:54:38.447587Z", + "stabilities": [ + "staging", + "unstable" + ], + "unfree": false, + "version": "0.0.49", + "outputs_to_install": [ + "out" + ], + "outputs": { + "out": "/nix/store/6wmig1w7f3vmfrlyg2qzv21bvacj3as8-pulumictl-0.0.49" + }, + "system": "x86_64-darwin", + "group": "toplevel", + "priority": 5 + }, + { + "attr_path": "pulumictl", + "broken": false, + "derivation": "/nix/store/ib7hqxg7xdf5kyh78jqggzdcs97q1224-pulumictl-0.0.49.drv", + "description": "Swiss Army Knife for Pulumi Development", + "install_id": "pulumictl", + "license": "Apache-2.0", + "locked_url": "https://github.com/flox/nixpkgs?rev=979daf34c8cacebcd917d540070b52a3c2b9b16e", + "name": "pulumictl-0.0.49", + "pname": "pulumictl", + "rev": "979daf34c8cacebcd917d540070b52a3c2b9b16e", + "rev_count": 793735, + "rev_date": "2025-05-04T03:14:55Z", + "scrape_date": "2025-05-05T05:16:19.858098Z", + "stabilities": [ + "staging", + "unstable" + ], + "unfree": false, + "version": "0.0.49", + "outputs_to_install": [ + "out" + ], + "outputs": { + "out": "/nix/store/rmh9mjkxijxcc7cvjhsqc9657fbw0yyg-pulumictl-0.0.49" + }, + "system": "x86_64-linux", + "group": "toplevel", + "priority": 5 + }, { "attr_path": "ruff", "broken": false, diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 1478e9b75..331293840 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -4,20 +4,13 @@ on: push jobs: python_test_and_coverage: - name: Run Python tests (${{ matrix.os }}) - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest] + name: Run Python tests + runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Install Flox uses: flox/install-flox-action@v2 - - name: Install Python dependencies - uses: flox/activate-action@v1 - with: - command: mise tasks run python:install - name: Run unit tests with coverage uses: flox/activate-action@v1 with: diff --git a/.gitignore b/.gitignore index eeeb68f1f..ca0851fe3 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ .python_coverage.* __pycache__/ infrastructure/Pulumi.infrastructure.yaml - -**/.claude/settings.local.json +.coverage* +.coverage/ +coverage.xml .envrc diff --git a/.mise.toml b/.mise.toml index a8f86e17d..9119a7e83 100644 --- a/.mise.toml +++ b/.mise.toml @@ -3,7 +3,7 @@ COMPOSE_BAKE=true [tasks."python:install"] description = "Install Python dependencies" -run = "uv sync --all-packages" +run = "uv sync --all-groups" [tasks."python:format"] description = "Format Python code" @@ -30,22 +30,14 @@ ruff check \ [tasks."python:test"] description = "Run Python tests" -run = """ -uv run coverage run \ - --parallel-mode \ - --omit '*/__init__.py,**/test_*.py' \ - --data-file .python_coverage.output \ - --module pytest - -uv run coverage combine \ - --data-file .python_coverage.output +run = "docker compose run tests" -uv run coverage report \ - --data-file .python_coverage.output -uv run coverage xml \ - --data-file .python_coverage.output \ - -o .python_coverage.xml +[tasks."python:test:behave"] +description = "Run behave end-to-end tests" +run = """ +cd application/{{arg(name="application_name")}} +uv run behave features/ """ @@ -62,19 +54,19 @@ description = "Build the application service" run = """ TIMESTAMP=$(date +%Y%m%d) docker build \ ---file application/{{arg(name="service_name")}}/Dockerfile \ ---tag pocketsizefund/{{arg(name="service_name")}}:latest \ ---tag pocketsizefund/{{arg(name="service_name")}}:${TIMESTAMP} \ +--file application/{{arg(name="application_name")}}/Dockerfile \ +--tag pocketsizefund/{{arg(name="application_name")}}:latest \ +--tag pocketsizefund/{{arg(name="application_name")}}:${TIMESTAMP} \ . """ -[tasks."application:service:run"] +[tasks."application:run"] description = "Run the application service" run = """ docker run \ --env-file .env \ --publish 8080:8080 \ -pocketsizefund/{{arg(name="service_name")}}:latest \ +pocketsizefund/{{arg(name="application_name")}}:latest \ """ [tasks."application:service:development"] diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..05026497d --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,19 @@ +# Codex Agent Instructions + +This project uses **mise** tasks for code quality and testing. Before committing, run the following steps: + +1. Install dependencies with `mise run python:install`. +2. Format code with `mise run python:format`. +3. Run lint checks with `mise run python:lint`. +4. Execute tests with `mise run python:test`. + +## Code Style +- Write tested, self-documenting code. Avoid comments unless the code is complex. + +## Pull Requests +- Use the Pull Request template: `.github/PULL_REQUEST_TEMPLATE.md`. + +## GitHub Issues +- When creating an issue, use the templates under `.github/ISSUE_TEMPLATE`. +- Include a clear title, the reason the feature or fix is needed, and two implementation options with cost-benefit analysis. + diff --git a/Dockerfile.test b/Dockerfile.test new file mode 100644 index 000000000..f24a29c57 --- /dev/null +++ b/Dockerfile.test @@ -0,0 +1,9 @@ +FROM python:3.13 +COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv + +ENV PYTEST_ADDOPTS="--rootdir=/tests" + +WORKDIR /tests + +COPY pyproject.toml uv.lock . +RUN uv sync --all-groups diff --git a/application/datamanager/Dockerfile b/application/datamanager/Dockerfile index 8cf6e8a51..1baa63522 100644 --- a/application/datamanager/Dockerfile +++ b/application/datamanager/Dockerfile @@ -1,6 +1,8 @@ FROM python:3.13-slim COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv +ENV PYTHONPATH=/app/src + RUN apt-get update && \ apt-get install -y --no-install-recommends libgomp1 curl \ && rm -rf /var/lib/apt/lists/* @@ -10,8 +12,8 @@ WORKDIR /app COPY pyproject.toml ./ RUN uv sync --no-dev -COPY ./src/ ./app +COPY ./src ./src EXPOSE 8080 -ENTRYPOINT ["uv", "run", "uvicorn", "datamanager.src.datamanager.main:application", "--host", "0.0.0.0", "--port", "8080"] +ENTRYPOINT ["uv", "run", "uvicorn", "datamanager.main:application", "--host", "0.0.0.0", "--port", "8080", "--app-dir", "src"] diff --git a/application/datamanager/features/steps/equity_bars_steps.py b/application/datamanager/features/steps/equity_bars_steps.py index 5ea39b6f6..799b3544b 100644 --- a/application/datamanager/features/steps/equity_bars_steps.py +++ b/application/datamanager/features/steps/equity_bars_steps.py @@ -60,4 +60,4 @@ def step_impl_equity_bars(context, date_str): expected_file = Path(f"equity_bars_{date_str}.parquet") assert not expected_file.exists(), ( f"Parquet file {expected_file} still exists after deletion" - ) + ) \ No newline at end of file diff --git a/application/datamanager/features/steps/health_steps.py b/application/datamanager/features/steps/health_steps.py index 14ba44ad0..b77fd1535 100644 --- a/application/datamanager/features/steps/health_steps.py +++ b/application/datamanager/features/steps/health_steps.py @@ -1,9 +1,7 @@ from behave import when import requests - @when('I send a GET request to "{endpoint}"') def step_impl(context, endpoint): - """Send a GET request to the specified endpoint.""" url = f"{context.api_url}{endpoint}" context.response = requests.get(url) diff --git a/application/datamanager/pyproject.toml b/application/datamanager/pyproject.toml index 388d9fbb8..fb96ef0c2 100644 --- a/application/datamanager/pyproject.toml +++ b/application/datamanager/pyproject.toml @@ -2,7 +2,7 @@ name = "datamanager" version = "0.1.0" description = "Data management service" -requires-python = ">=3.13" +requires-python = ">=3.12" dependencies = [ "fastapi>=0.115.12", "uvicorn>=0.34.2", diff --git a/application/datamanager/src/datamanager/bars.sql b/application/datamanager/src/datamanager/bars.sql new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/application/datamanager/src/datamanager/bars.sql @@ -0,0 +1 @@ + diff --git a/application/datamanager/src/datamanager/config.py b/application/datamanager/src/datamanager/config.py index d57ea181d..67adc30dc 100644 --- a/application/datamanager/src/datamanager/config.py +++ b/application/datamanager/src/datamanager/config.py @@ -1,7 +1,9 @@ import os import json from functools import cached_property +from datetime import date, datetime from pydantic import BaseModel, Field, computed_field +from loguru import logger class Polygon(BaseModel): diff --git a/application/datamanager/src/datamanager/main.py b/application/datamanager/src/datamanager/main.py index 4f3788d73..ea69e1c5e 100644 --- a/application/datamanager/src/datamanager/main.py +++ b/application/datamanager/src/datamanager/main.py @@ -165,5 +165,4 @@ async def delete_equity_bars(request: Request, summary_date: SummaryDate): logger.info(f"deleting {prefix=}") bucket.delete_blobs(blobs) - return Response(status_code=status.HTTP_204_NO_CONTENT) diff --git a/application/datamanager/src/datamanager/query.py b/application/datamanager/src/datamanager/query.py new file mode 100644 index 000000000..1dd0a409d --- /dev/null +++ b/application/datamanager/src/datamanager/query.py @@ -0,0 +1,28 @@ +from datetime import timedelta, date +from polars import DataFrame +import duckdb +from pathlib import Path + + +async def list_file_paths( + *, bucket: str, start_date: date, end_date: date +) -> list[Path]: + filepaths = [] + current = start_date + while current <= end_date: + filepaths.append( + f"gs://{bucket}/equity/bars/{current.strftime('%Y-%m-%d')}/data.parquet" + ) + current += timedelta(days=1) + + return filepaths + + +async def query_bars(*, filepaths: list[Path]) -> DataFrame: + query = f""" + SELECT * FROM read_parquet({filepaths}) + """ + try: + return duckdb.sql(query).pl() + except duckdb.duckdb.HTTPException as e: + return diff --git a/application/positionmanager/Dockerfile b/application/positionmanager/Dockerfile index 456c527e7..b69810e9c 100644 --- a/application/positionmanager/Dockerfile +++ b/application/positionmanager/Dockerfile @@ -1,15 +1,15 @@ -FROM python:3.13-slim - +FROM python:3.13 COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv +ENV PYTHONPATH=/app/src + WORKDIR /app COPY pyproject.toml ./ +RUN uv sync --no-dev -COPY application/positionmanager/ ./application/positionmanager/ - -RUN uv sync --all-packages +COPY ./src ./src EXPOSE 8080 -ENTRYPOINT ["uv", "run", "uvicorn", "application.positionmanager.src.positionmanager.main:application", "--host", "0.0.0.0", "--port", "8080"] \ No newline at end of file +ENTRYPOINT ["uv", "run", "uvicorn", "positionmanager.main:application", "--host", "0.0.0.0", "--port", "8080", "--app-dir", "src"] diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 000000000..a221c40ee --- /dev/null +++ b/compose.yaml @@ -0,0 +1,16 @@ + +services: + tests: + build: + context: . + dockerfile: Dockerfile.test + volumes: + - .:/tests + command: + - /bin/sh + - -euxc + - | + uv run coverage run --parallel-mode -m pytest && \ + uv run coverage combine && \ + uv run coverage report && \ + uv run coverage xml diff --git a/infrastructure/cloud_run.py b/infrastructure/cloud_run.py index 76dcb35de..500aedf53 100644 --- a/infrastructure/cloud_run.py +++ b/infrastructure/cloud_run.py @@ -47,6 +47,17 @@ name="DUCKDB_SECRET", value=duckdb_secret, ), + cloudrun.ServiceTemplateSpecContainerEnvArgs( + name="DATA_BUCKET", + value=buckets.production_data_bucket.name, + ), + cloudrun.ServiceTemplateSpecContainerEnvArgs( + name="DUCKDB_ACCESS_KEY", value=duckdb_access_key + ), + cloudrun.ServiceTemplateSpecContainerEnvArgs( + name="DUCKDB_SECRET", + value=duckdb_secret, + ), ], ) ], diff --git a/pyproject.toml b/pyproject.toml index 2fd403716..aac2ec314 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,12 +2,9 @@ name = "pocketsizefund" version = "0.1.0" description = "Open source quantitative hedge fund 🍊" -requires-python = ">=3.13" +requires-python = ">=3.12" dependencies = [ - "pytest>=8.3.5", - "pytest-asyncio>=0.23.0", "httpx>=0.28.1", - "coverage>=7.6.1", ] [tool.uv.workspace] @@ -29,3 +26,36 @@ packages = ["pocketsizefund"] [build-system] requires = ["hatchling"] build-backend = "hatchling.build" + +[dependency-groups] +dev = [ + "alpaca-py>=0.40.1", + "coverage>=7.8.0", + "duckdb>=1.2.2", + "ecos>=2.0.14", + "fastapi>=0.115.12", + "polars>=1.29.0", + "pyarrow>=20.0.0", + "pyportfolioopt>=1.5.6", + "pytest>=8.3.5", + "requests>=2.32.3", +] + + +[tool.pytest.ini_options] +testpaths = [ + "/tests/", + "application/datamanager/tests", + "application/positionmanager/tests", +] + +[tool.coverage.run] +parallel = true +omit = ["*/__init__.py", "**/test_*.py"] + +[tool.coverage.report] +show_missing = true +skip_covered = true + +[tool.coverage.xml] +output = ".python_coverage.xml" diff --git a/uv.lock b/uv.lock index 7b56c3c5b..da2939937 100644 --- a/uv.lock +++ b/uv.lock @@ -166,65 +166,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" }, ] -[[package]] -name = "azure-core" -version = "1.34.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "requests" }, - { name = "six" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c9/29/ff7a519a315e41c85bab92a7478c6acd1cf0b14353139a08caee4c691f77/azure_core-1.34.0.tar.gz", hash = "sha256:bdb544989f246a0ad1c85d72eeb45f2f835afdcbc5b45e43f0dbde7461c81ece", size = 297999, upload-time = "2025-05-01T23:17:27.59Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/84/9e/5c87b49f65bb16571599bc789857d0ded2f53014d3392bc88a5d1f3ad779/azure_core-1.34.0-py3-none-any.whl", hash = "sha256:0615d3b756beccdb6624d1c0ae97284f38b78fb59a2a9839bf927c66fbbdddd6", size = 207409, upload-time = "2025-05-01T23:17:29.818Z" }, -] - -[[package]] -name = "azure-datalake-store" -version = "0.0.53" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cffi" }, - { name = "msal" }, - { name = "requests" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/22/ff/61369d06422b5ac48067215ff404841342651b14a89b46c8d8e1507c8f17/azure-datalake-store-0.0.53.tar.gz", hash = "sha256:05b6de62ee3f2a0a6e6941e6933b792b800c3e7f6ffce2fc324bc19875757393", size = 71430, upload-time = "2023-05-10T21:17:05.665Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/88/2a/75f56b14f115189155cf12e46b366ad1fe3357af5a1a7c09f7446662d617/azure_datalake_store-0.0.53-py2.py3-none-any.whl", hash = "sha256:a30c902a6e360aa47d7f69f086b426729784e71c536f330b691647a51dc42b2b", size = 55308, upload-time = "2023-05-10T21:17:02.629Z" }, -] - -[[package]] -name = "azure-identity" -version = "1.23.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "azure-core" }, - { name = "cryptography" }, - { name = "msal" }, - { name = "msal-extensions" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/41/52/458c1be17a5d3796570ae2ed3c6b7b55b134b22d5ef8132b4f97046a9051/azure_identity-1.23.0.tar.gz", hash = "sha256:d9cdcad39adb49d4bb2953a217f62aec1f65bbb3c63c9076da2be2a47e53dde4", size = 265280, upload-time = "2025-05-14T00:18:30.408Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/07/16/a51d47780f41e4b87bb2d454df6aea90a44a346e918ac189d3700f3d728d/azure_identity-1.23.0-py3-none-any.whl", hash = "sha256:dbbeb64b8e5eaa81c44c565f264b519ff2de7ff0e02271c49f3cb492762a50b0", size = 186097, upload-time = "2025-05-14T00:18:32.734Z" }, -] - -[[package]] -name = "azure-storage-blob" -version = "12.25.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "azure-core" }, - { name = "cryptography" }, - { name = "isodate" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/8b/f3/f764536c25cc3829d36857167f03933ce9aee2262293179075439f3cd3ad/azure_storage_blob-12.25.1.tar.gz", hash = "sha256:4f294ddc9bc47909ac66b8934bd26b50d2000278b10ad82cc109764fdc6e0e3b", size = 570541, upload-time = "2025-03-27T17:13:05.424Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/57/33/085d9352d416e617993821b9d9488222fbb559bc15c3641d6cbd6d16d236/azure_storage_blob-12.25.1-py3-none-any.whl", hash = "sha256:1f337aab12e918ec3f1b638baada97550673911c4ceed892acc8e4e891b74167", size = 406990, upload-time = "2025-03-27T17:13:06.879Z" }, -] - [[package]] name = "behave" version = "1.2.6" @@ -239,20 +180,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a8/6c/ec9169548b6c4cb877aaa6773408ca08ae2a282805b958dbc163cb19822d/behave-1.2.6-py2.py3-none-any.whl", hash = "sha256:ebda1a6c9e5bfe95c5f9f0a2794e01c7098b3dde86c10a95d8621c5907ff6f1c", size = 136779, upload-time = "2018-02-25T20:06:34.436Z" }, ] -[[package]] -name = "botocore" -version = "1.37.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jmespath" }, - { name = "python-dateutil" }, - { name = "urllib3" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/74/fb/b243ab806d2e1e6b8a475b731cc59a1f1e4709eded4884b988a27bbc996b/botocore-1.37.3.tar.gz", hash = "sha256:fe8403eb55a88faf9b0f9da6615e5bee7be056d75e17af66c3c8f0a3b0648da4", size = 13574648, upload-time = "2025-02-27T20:27:59.559Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/88/54/772118f15b5990173aa5264946cc8c9ff70c8f02d72ee6d63167a985188c/botocore-1.37.3-py3-none-any.whl", hash = "sha256:d01bd3bf4c80e61fa88d636ad9f5c9f60a551d71549b481386c6b4efe0bb2b2e", size = 13342066, upload-time = "2025-02-27T20:27:53.137Z" }, -] - [[package]] name = "cachetools" version = "5.5.2" @@ -616,137 +543,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/50/b3/b51f09c2ba432a576fe63758bddc81f78f0c6309d9e5c10d194313bf021e/fastapi-0.115.12-py3-none-any.whl", hash = "sha256:e94613d6c05e27be7ffebdd6ea5f388112e5e430c8f7d6494a9d1d88d43e814d", size = 95164, upload-time = "2025-03-23T22:55:42.101Z" }, ] -[[package]] -name = "flyteidl" -version = "1.15.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "googleapis-common-protos" }, - { name = "protobuf" }, - { name = "protoc-gen-openapiv2" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/92/6d/252aaa552a21e42a15e642abd2828ccda936eacffcfc2ec7dfad11292d01/flyteidl-1.15.3.tar.gz", hash = "sha256:4c24aebd6b001efd4f65ee64b849ca0b22be7ab4ccd0e92bc247acb41fcc20cf", size = 129334, upload-time = "2025-04-22T02:05:09.741Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/2d/4cbc3e7f8616234ca5fc3f8d3e28deecd4ad9f0ce75593a797abefc1adae/flyteidl-1.15.3-py3-none-any.whl", hash = "sha256:7dca58e85afec5594e029cd4dfd046c9f156d95537051b744ccdc9f18a236467", size = 220503, upload-time = "2025-04-22T02:05:07.885Z" }, -] - -[[package]] -name = "flytekit" -version = "1.15.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "adlfs" }, - { name = "click" }, - { name = "cloudpickle" }, - { name = "croniter" }, - { name = "dataclasses-json" }, - { name = "diskcache" }, - { name = "docker" }, - { name = "docstring-parser" }, - { name = "flyteidl" }, - { name = "fsspec" }, - { name = "gcsfs" }, - { name = "googleapis-common-protos" }, - { name = "grpcio" }, - { name = "grpcio-status" }, - { name = "importlib-metadata" }, - { name = "joblib" }, - { name = "jsonlines" }, - { name = "jsonpickle" }, - { name = "keyring" }, - { name = "markdown-it-py" }, - { name = "marshmallow-enum" }, - { name = "marshmallow-jsonschema" }, - { name = "mashumaro" }, - { name = "msgpack" }, - { name = "protobuf" }, - { name = "pygments" }, - { name = "python-json-logger" }, - { name = "pytimeparse" }, - { name = "pyyaml" }, - { name = "requests" }, - { name = "rich" }, - { name = "rich-click" }, - { name = "s3fs" }, - { name = "statsd" }, - { name = "typing-extensions" }, - { name = "urllib3" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/30/91/3d17b8862115f6c426b8b9a32a16f599abffd82d0c8fbab643e406e2171a/flytekit-1.15.4.tar.gz", hash = "sha256:3520c7dcdeafc7f7d7418c1e9dca114f867bf81efb076beeecff37a272e18e0f", size = 556686, upload-time = "2025-04-22T23:05:52.786Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/50/a6/06499803ba31f1f725d50c874a6a1eb0e782c1c891a6e497e827b0aaa782/flytekit-1.15.4-py3-none-any.whl", hash = "sha256:c0a16cff5bb20b48c49525e974fe55a6885ca19e6f3c535fbe65e9815ffa566b", size = 658043, upload-time = "2025-04-22T23:05:50.308Z" }, -] - -[[package]] -name = "frozenlist" -version = "1.6.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ee/f4/d744cba2da59b5c1d88823cf9e8a6c74e4659e2b27604ed973be2a0bf5ab/frozenlist-1.6.0.tar.gz", hash = "sha256:b99655c32c1c8e06d111e7f41c06c29a5318cb1835df23a45518e02a47c63b68", size = 42831, upload-time = "2025-04-17T22:38:53.099Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6f/e5/04c7090c514d96ca00887932417f04343ab94904a56ab7f57861bf63652d/frozenlist-1.6.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:1d7fb014fe0fbfee3efd6a94fc635aeaa68e5e1720fe9e57357f2e2c6e1a647e", size = 158182, upload-time = "2025-04-17T22:37:16.837Z" }, - { url = "https://files.pythonhosted.org/packages/e9/8f/60d0555c61eec855783a6356268314d204137f5e0c53b59ae2fc28938c99/frozenlist-1.6.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01bcaa305a0fdad12745502bfd16a1c75b14558dabae226852f9159364573117", size = 122838, upload-time = "2025-04-17T22:37:18.352Z" }, - { url = "https://files.pythonhosted.org/packages/5a/a7/d0ec890e3665b4b3b7c05dc80e477ed8dc2e2e77719368e78e2cd9fec9c8/frozenlist-1.6.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8b314faa3051a6d45da196a2c495e922f987dc848e967d8cfeaee8a0328b1cd4", size = 120980, upload-time = "2025-04-17T22:37:19.857Z" }, - { url = "https://files.pythonhosted.org/packages/cc/19/9b355a5e7a8eba903a008579964192c3e427444752f20b2144b10bb336df/frozenlist-1.6.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da62fecac21a3ee10463d153549d8db87549a5e77eefb8c91ac84bb42bb1e4e3", size = 305463, upload-time = "2025-04-17T22:37:21.328Z" }, - { url = "https://files.pythonhosted.org/packages/9c/8d/5b4c758c2550131d66935ef2fa700ada2461c08866aef4229ae1554b93ca/frozenlist-1.6.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d1eb89bf3454e2132e046f9599fbcf0a4483ed43b40f545551a39316d0201cd1", size = 297985, upload-time = "2025-04-17T22:37:23.55Z" }, - { url = "https://files.pythonhosted.org/packages/48/2c/537ec09e032b5865715726b2d1d9813e6589b571d34d01550c7aeaad7e53/frozenlist-1.6.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18689b40cb3936acd971f663ccb8e2589c45db5e2c5f07e0ec6207664029a9c", size = 311188, upload-time = "2025-04-17T22:37:25.221Z" }, - { url = "https://files.pythonhosted.org/packages/31/2f/1aa74b33f74d54817055de9a4961eff798f066cdc6f67591905d4fc82a84/frozenlist-1.6.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e67ddb0749ed066b1a03fba812e2dcae791dd50e5da03be50b6a14d0c1a9ee45", size = 311874, upload-time = "2025-04-17T22:37:26.791Z" }, - { url = "https://files.pythonhosted.org/packages/bf/f0/cfec18838f13ebf4b37cfebc8649db5ea71a1b25dacd691444a10729776c/frozenlist-1.6.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fc5e64626e6682638d6e44398c9baf1d6ce6bc236d40b4b57255c9d3f9761f1f", size = 291897, upload-time = "2025-04-17T22:37:28.958Z" }, - { url = "https://files.pythonhosted.org/packages/ea/a5/deb39325cbbea6cd0a46db8ccd76150ae2fcbe60d63243d9df4a0b8c3205/frozenlist-1.6.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:437cfd39564744ae32ad5929e55b18ebd88817f9180e4cc05e7d53b75f79ce85", size = 305799, upload-time = "2025-04-17T22:37:30.889Z" }, - { url = "https://files.pythonhosted.org/packages/78/22/6ddec55c5243a59f605e4280f10cee8c95a449f81e40117163383829c241/frozenlist-1.6.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:62dd7df78e74d924952e2feb7357d826af8d2f307557a779d14ddf94d7311be8", size = 302804, upload-time = "2025-04-17T22:37:32.489Z" }, - { url = "https://files.pythonhosted.org/packages/5d/b7/d9ca9bab87f28855063c4d202936800219e39db9e46f9fb004d521152623/frozenlist-1.6.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:a66781d7e4cddcbbcfd64de3d41a61d6bdde370fc2e38623f30b2bd539e84a9f", size = 316404, upload-time = "2025-04-17T22:37:34.59Z" }, - { url = "https://files.pythonhosted.org/packages/a6/3a/1255305db7874d0b9eddb4fe4a27469e1fb63720f1fc6d325a5118492d18/frozenlist-1.6.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:482fe06e9a3fffbcd41950f9d890034b4a54395c60b5e61fae875d37a699813f", size = 295572, upload-time = "2025-04-17T22:37:36.337Z" }, - { url = "https://files.pythonhosted.org/packages/2a/f2/8d38eeee39a0e3a91b75867cc102159ecccf441deb6ddf67be96d3410b84/frozenlist-1.6.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:e4f9373c500dfc02feea39f7a56e4f543e670212102cc2eeb51d3a99c7ffbde6", size = 307601, upload-time = "2025-04-17T22:37:37.923Z" }, - { url = "https://files.pythonhosted.org/packages/38/04/80ec8e6b92f61ef085422d7b196822820404f940950dde5b2e367bede8bc/frozenlist-1.6.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e69bb81de06827147b7bfbaeb284d85219fa92d9f097e32cc73675f279d70188", size = 314232, upload-time = "2025-04-17T22:37:39.669Z" }, - { url = "https://files.pythonhosted.org/packages/3a/58/93b41fb23e75f38f453ae92a2f987274c64637c450285577bd81c599b715/frozenlist-1.6.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7613d9977d2ab4a9141dde4a149f4357e4065949674c5649f920fec86ecb393e", size = 308187, upload-time = "2025-04-17T22:37:41.662Z" }, - { url = "https://files.pythonhosted.org/packages/6a/a2/e64df5c5aa36ab3dee5a40d254f3e471bb0603c225f81664267281c46a2d/frozenlist-1.6.0-cp313-cp313-win32.whl", hash = "sha256:4def87ef6d90429f777c9d9de3961679abf938cb6b7b63d4a7eb8a268babfce4", size = 114772, upload-time = "2025-04-17T22:37:43.132Z" }, - { url = "https://files.pythonhosted.org/packages/a0/77/fead27441e749b2d574bb73d693530d59d520d4b9e9679b8e3cb779d37f2/frozenlist-1.6.0-cp313-cp313-win_amd64.whl", hash = "sha256:37a8a52c3dfff01515e9bbbee0e6063181362f9de3db2ccf9bc96189b557cbfd", size = 119847, upload-time = "2025-04-17T22:37:45.118Z" }, - { url = "https://files.pythonhosted.org/packages/df/bd/cc6d934991c1e5d9cafda83dfdc52f987c7b28343686aef2e58a9cf89f20/frozenlist-1.6.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:46138f5a0773d064ff663d273b309b696293d7a7c00a0994c5c13a5078134b64", size = 174937, upload-time = "2025-04-17T22:37:46.635Z" }, - { url = "https://files.pythonhosted.org/packages/f2/a2/daf945f335abdbfdd5993e9dc348ef4507436936ab3c26d7cfe72f4843bf/frozenlist-1.6.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f88bc0a2b9c2a835cb888b32246c27cdab5740059fb3688852bf91e915399b91", size = 136029, upload-time = "2025-04-17T22:37:48.192Z" }, - { url = "https://files.pythonhosted.org/packages/51/65/4c3145f237a31247c3429e1c94c384d053f69b52110a0d04bfc8afc55fb2/frozenlist-1.6.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:777704c1d7655b802c7850255639672e90e81ad6fa42b99ce5ed3fbf45e338dd", size = 134831, upload-time = "2025-04-17T22:37:50.485Z" }, - { url = "https://files.pythonhosted.org/packages/77/38/03d316507d8dea84dfb99bdd515ea245628af964b2bf57759e3c9205cc5e/frozenlist-1.6.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85ef8d41764c7de0dcdaf64f733a27352248493a85a80661f3c678acd27e31f2", size = 392981, upload-time = "2025-04-17T22:37:52.558Z" }, - { url = "https://files.pythonhosted.org/packages/37/02/46285ef9828f318ba400a51d5bb616ded38db8466836a9cfa39f3903260b/frozenlist-1.6.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:da5cb36623f2b846fb25009d9d9215322318ff1c63403075f812b3b2876c8506", size = 371999, upload-time = "2025-04-17T22:37:54.092Z" }, - { url = "https://files.pythonhosted.org/packages/0d/64/1212fea37a112c3c5c05bfb5f0a81af4836ce349e69be75af93f99644da9/frozenlist-1.6.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cbb56587a16cf0fb8acd19e90ff9924979ac1431baea8681712716a8337577b0", size = 392200, upload-time = "2025-04-17T22:37:55.951Z" }, - { url = "https://files.pythonhosted.org/packages/81/ce/9a6ea1763e3366e44a5208f76bf37c76c5da570772375e4d0be85180e588/frozenlist-1.6.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6154c3ba59cda3f954c6333025369e42c3acd0c6e8b6ce31eb5c5b8116c07e0", size = 390134, upload-time = "2025-04-17T22:37:57.633Z" }, - { url = "https://files.pythonhosted.org/packages/bc/36/939738b0b495b2c6d0c39ba51563e453232813042a8d908b8f9544296c29/frozenlist-1.6.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e8246877afa3f1ae5c979fe85f567d220f86a50dc6c493b9b7d8191181ae01e", size = 365208, upload-time = "2025-04-17T22:37:59.742Z" }, - { url = "https://files.pythonhosted.org/packages/b4/8b/939e62e93c63409949c25220d1ba8e88e3960f8ef6a8d9ede8f94b459d27/frozenlist-1.6.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b0f6cce16306d2e117cf9db71ab3a9e8878a28176aeaf0dbe35248d97b28d0c", size = 385548, upload-time = "2025-04-17T22:38:01.416Z" }, - { url = "https://files.pythonhosted.org/packages/62/38/22d2873c90102e06a7c5a3a5b82ca47e393c6079413e8a75c72bff067fa8/frozenlist-1.6.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:1b8e8cd8032ba266f91136d7105706ad57770f3522eac4a111d77ac126a25a9b", size = 391123, upload-time = "2025-04-17T22:38:03.049Z" }, - { url = "https://files.pythonhosted.org/packages/44/78/63aaaf533ee0701549500f6d819be092c6065cb5c577edb70c09df74d5d0/frozenlist-1.6.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:e2ada1d8515d3ea5378c018a5f6d14b4994d4036591a52ceaf1a1549dec8e1ad", size = 394199, upload-time = "2025-04-17T22:38:04.776Z" }, - { url = "https://files.pythonhosted.org/packages/54/45/71a6b48981d429e8fbcc08454dc99c4c2639865a646d549812883e9c9dd3/frozenlist-1.6.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:cdb2c7f071e4026c19a3e32b93a09e59b12000751fc9b0b7758da899e657d215", size = 373854, upload-time = "2025-04-17T22:38:06.576Z" }, - { url = "https://files.pythonhosted.org/packages/3f/f3/dbf2a5e11736ea81a66e37288bf9f881143a7822b288a992579ba1b4204d/frozenlist-1.6.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:03572933a1969a6d6ab509d509e5af82ef80d4a5d4e1e9f2e1cdd22c77a3f4d2", size = 395412, upload-time = "2025-04-17T22:38:08.197Z" }, - { url = "https://files.pythonhosted.org/packages/b3/f1/c63166806b331f05104d8ea385c4acd511598568b1f3e4e8297ca54f2676/frozenlist-1.6.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:77effc978947548b676c54bbd6a08992759ea6f410d4987d69feea9cd0919911", size = 394936, upload-time = "2025-04-17T22:38:10.056Z" }, - { url = "https://files.pythonhosted.org/packages/ef/ea/4f3e69e179a430473eaa1a75ff986526571215fefc6b9281cdc1f09a4eb8/frozenlist-1.6.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a2bda8be77660ad4089caf2223fdbd6db1858462c4b85b67fbfa22102021e497", size = 391459, upload-time = "2025-04-17T22:38:11.826Z" }, - { url = "https://files.pythonhosted.org/packages/d3/c3/0fc2c97dea550df9afd072a37c1e95421652e3206bbeaa02378b24c2b480/frozenlist-1.6.0-cp313-cp313t-win32.whl", hash = "sha256:a4d96dc5bcdbd834ec6b0f91027817214216b5b30316494d2b1aebffb87c534f", size = 128797, upload-time = "2025-04-17T22:38:14.013Z" }, - { url = "https://files.pythonhosted.org/packages/ae/f5/79c9320c5656b1965634fe4be9c82b12a3305bdbc58ad9cb941131107b20/frozenlist-1.6.0-cp313-cp313t-win_amd64.whl", hash = "sha256:e18036cb4caa17ea151fd5f3d70be9d354c99eb8cf817a3ccde8a7873b074348", size = 134709, upload-time = "2025-04-17T22:38:15.551Z" }, - { url = "https://files.pythonhosted.org/packages/71/3e/b04a0adda73bd52b390d730071c0d577073d3d26740ee1bad25c3ad0f37b/frozenlist-1.6.0-py3-none-any.whl", hash = "sha256:535eec9987adb04701266b92745d6cdcef2e77669299359c3009c3404dd5d191", size = 12404, upload-time = "2025-04-17T22:38:51.668Z" }, -] - -[[package]] -name = "fsspec" -version = "2025.5.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f2/77/deb99b97981e2e191913454da82d406702405178631c31cd623caebaf1b1/fsspec-2025.5.0.tar.gz", hash = "sha256:e4f4623bb6221f7407fd695cc535d1f857a077eb247580f4ada34f5dc25fd5c8", size = 300989, upload-time = "2025-05-20T15:46:22.484Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/a9/a7022f58e081149ec0184c31ea81dcee605e1d46380b48122e1ef94ac24e/fsspec-2025.5.0-py3-none-any.whl", hash = "sha256:0ca253eca6b5333d8a2b8bd98c7326fe821f1f0fdbd34e1b445bddde8e804c95", size = 196164, upload-time = "2025-05-20T15:46:20.89Z" }, -] - -[[package]] -name = "gcsfs" -version = "2025.5.0.post1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "aiohttp" }, - { name = "decorator" }, - { name = "fsspec" }, - { name = "google-auth" }, - { name = "google-auth-oauthlib" }, - { name = "google-cloud-storage" }, - { name = "requests" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/20/01/000d90d0e3646b16701a0a747175ddc80a016bdcc60b689936d201b6b45b/gcsfs-2025.5.0.post1.tar.gz", hash = "sha256:a5346a7185f306e8cc1dcb6c0447e9cc1ac050d22e4da89a4c176dfdf4c1dd42", size = 82189, upload-time = "2025-05-21T12:36:30.34Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3d/33/a1e020d25a22eb1565c8304789ba51c4ff0e6d915068a910afbc4780933e/gcsfs-2025.5.0.post1-py2.py3-none-any.whl", hash = "sha256:88199197209152c2972c705c783822e35dd8b813086f5101fa30441cd8ca7a35", size = 36644, upload-time = "2025-05-21T12:36:28.885Z" }, -] - [[package]] name = "google-api-core" version = "2.24.2" @@ -777,19 +573,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a1/b1/1272c6e80847ba5349f5ccb7574596393d1e222543f5003cb810865c3575/google_auth-2.40.1-py2.py3-none-any.whl", hash = "sha256:ed4cae4f5c46b41bae1d19c036e06f6c371926e97b19e816fc854eff811974ee", size = 216101, upload-time = "2025-05-07T01:04:53.612Z" }, ] -[[package]] -name = "google-auth-oauthlib" -version = "1.2.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "google-auth" }, - { name = "requests-oauthlib" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/fb/87/e10bf24f7bcffc1421b84d6f9c3377c30ec305d082cd737ddaa6d8f77f7c/google_auth_oauthlib-1.2.2.tar.gz", hash = "sha256:11046fb8d3348b296302dd939ace8af0a724042e8029c1b872d87fabc9f41684", size = 20955, upload-time = "2025-04-22T16:40:29.172Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ac/84/40ee070be95771acd2f4418981edb834979424565c3eec3cd88b6aa09d24/google_auth_oauthlib-1.2.2-py3-none-any.whl", hash = "sha256:fd619506f4b3908b5df17b65f39ca8d66ea56986e5472eb5978fd8f3786f00a2", size = 19072, upload-time = "2025-04-22T16:40:28.174Z" }, -] - [[package]] name = "google-cloud-core" version = "2.4.3" @@ -1685,15 +1468,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a", size = 181259, upload-time = "2025-03-28T02:41:19.028Z" }, ] -[[package]] -name = "pycparser" -version = "2.22" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736, upload-time = "2024-03-30T13:22:22.564Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552, upload-time = "2024-03-30T13:22:20.476Z" }, -] - [[package]] name = "pydantic" version = "2.11.4" @@ -1895,69 +1669,6 @@ wheels = [ ] [[package]] -name = "requests-oauthlib" -version = "2.0.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "oauthlib" }, - { name = "requests" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/42/f2/05f29bc3913aea15eb670be136045bf5c5bbf4b99ecb839da9b422bb2c85/requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9", size = 55650, upload-time = "2024-03-22T20:32:29.939Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3b/5d/63d4ae3b9daea098d5d6f5da83984853c1bbacd5dc826764b249fe119d24/requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36", size = 24179, upload-time = "2024-03-22T20:32:28.055Z" }, -] - -[[package]] -name = "rich" -version = "14.0.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "markdown-it-py" }, - { name = "pygments" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/a1/53/830aa4c3066a8ab0ae9a9955976fb770fe9c6102117c8ec4ab3ea62d89e8/rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725", size = 224078, upload-time = "2025-03-30T14:15:14.23Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/9b/63f4c7ebc259242c89b3acafdb37b41d1185c07ff0011164674e9076b491/rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", size = 243229, upload-time = "2025-03-30T14:15:12.283Z" }, -] - -[[package]] -name = "rich-click" -version = "1.8.9" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "click" }, - { name = "rich" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b7/a8/dcc0a8ec9e91d76ecad9413a84b6d3a3310c6111cfe012d75ed385c78d96/rich_click-1.8.9.tar.gz", hash = "sha256:fd98c0ab9ddc1cf9c0b7463f68daf28b4d0033a74214ceb02f761b3ff2af3136", size = 39378, upload-time = "2025-05-19T21:33:05.569Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b6/c2/9fce4c8a9587c4e90500114d742fe8ef0fd92d7bad29d136bb9941add271/rich_click-1.8.9-py3-none-any.whl", hash = "sha256:c3fa81ed8a671a10de65a9e20abf642cfdac6fdb882db1ef465ee33919fbcfe2", size = 36082, upload-time = "2025-05-19T21:33:04.195Z" }, -] - -[[package]] -name = "rsa" -version = "4.9.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pyasn1" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/da/8a/22b7beea3ee0d44b1916c0c1cb0ee3af23b700b6da9f04991899d0c555d4/rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75", size = 29034, upload-time = "2025-04-16T09:51:18.218Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/64/8d/0133e4eb4beed9e425d9a98ed6e081a55d195481b7632472be1af08d2f6b/rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762", size = 34696, upload-time = "2025-04-16T09:51:17.142Z" }, -] - -[[package]] -name = "s3fs" -version = "2025.5.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "aiobotocore" }, - { name = "aiohttp" }, - { name = "fsspec" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/58/54/142a70e4c39a84b2b7c97200b179a4491c9c479f36e5c569c74dbfa96394/s3fs-2025.5.0.tar.gz", hash = "sha256:8ddbdc83c98ed55c7397a295596a7106de6f7a126c45798a95ad4d280edb3611", size = 77305, upload-time = "2025-05-20T15:54:56.076Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/06/62/656d0b3534eacea309d78bd8a8e15e6359d3c691e4192743c2f41e45b509/s3fs-2025.5.0-py3-none-any.whl", hash = "sha256:4eb942ebadfb7423f695475519849862d7d88f6f139cd7d9a211e5eb6fd5fc93", size = 30481, upload-time = "2025-05-20T15:54:54.492Z" }, ] [[package]] @@ -2086,15 +1797,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f4/d0/c9543b52c067a390ae6ae632d7fd1b97a35cdc8d69d40c0b7d334b326410/statsd-4.0.1-py2.py3-none-any.whl", hash = "sha256:c2676519927f7afade3723aca9ca8ea986ef5b059556a980a867721ca69df093", size = 13118, upload-time = "2022-11-06T14:17:34.258Z" }, ] -[[package]] -name = "tenacity" -version = "9.1.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0a/d4/2b0cd0fe285e14b36db076e78c93766ff1d529d70408bd1d2a5a84f1d929/tenacity-9.1.2.tar.gz", hash = "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb", size = 48036, upload-time = "2025-04-02T08:25:09.966Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" }, -] - [[package]] name = "typing-extensions" version = "4.13.2" diff --git a/workflows/prediction_model.py b/workflows/prediction_model.py new file mode 100644 index 000000000..a61d76879 --- /dev/null +++ b/workflows/prediction_model.py @@ -0,0 +1,47 @@ +import os +import uuid +from datetime import datetime +from pathlib import Path +from typing import List, Dict, Any + +import requests +from flytekit import task, workflow + + +@task +def fetch_data(start_date: datetime, end_date: datetime) -> List[Dict[str, Any]]: + base_url = os.getenv("DATAMANAGER_BASE_URL", "http://localhost:8080") + response = requests.get( + f"{base_url}/equity-bars", + params={"start_date": start_date.isoformat(), "end_date": end_date.isoformat()}, + timeout=10, + ) + response.raise_for_status() + return response.json().get("data", []) + + +@task +def train_dummy_model(data: List[Dict[str, Any]]) -> bytes: + """Train a trivial model that stores the average close price.""" + close_prices = [row.get("close_price", 0.0) for row in data] + mean_close = statistics.mean(close_prices) if close_prices else 0.0 + model = {"average_close_price": mean_close} + return pickle.dumps(model) + + +@task +def store_model(model_bytes: bytes) -> str: + """Store the serialized model in blob storage.""" + bucket_path = os.getenv("MODEL_BUCKET", "/tmp") + filename = f"model-{uuid.uuid4().hex}.pkl" + path = Path(bucket_path) / filename + path.write_bytes(model_bytes) + return str(path) + + +@workflow +def training_workflow(start_date: datetime, end_date: datetime) -> str: + data = fetch_data(start_date=start_date, end_date=end_date) + model_bytes = train_dummy_model(data=data) + artifact_path = store_model(model_bytes=model_bytes) + return artifact_path