diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index dde661b..a520f02 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -27,4 +27,9 @@ jobs: uses: docker/build-push-action@v6 with: context: . + load: true push: false + tags: local/test-image:latest + + - name: Run image help + run: docker run --rm --entrypoint "${{ github.event.repository.name }}" local/test-image:latest --help diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0a55dd8..076d80d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -34,10 +34,10 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Set image name - run: echo "IMAGE_NAME=ghcr.io/${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV + run: echo "IMAGE_NAME=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_ENV" - name: Set short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> "$GITHUB_ENV" - name: Build and push image uses: docker/build-push-action@v6 diff --git a/.gitignore b/.gitignore index 7db5ac0..2857ca5 100644 --- a/.gitignore +++ b/.gitignore @@ -177,3 +177,4 @@ pyrightconfig.json node_modules/ history.jsonl +uploader/clients/gen/ diff --git a/.template.yaml b/.template.yaml index f7cfa2c..551d969 100644 --- a/.template.yaml +++ b/.template.yaml @@ -1,5 +1,6 @@ # Autogenerated - DO NOT EDIT # Parameters of the project as generated from template -_commit: 00cbce2 +_commit: f510818 _src_path: gh:kraysent/python-template +package_name: uploader project_name: uploader diff --git a/Dockerfile b/Dockerfile index 80bc43f..3cd136a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,12 @@ -FROM python:3.12-slim AS builder +FROM python:3.13-slim AS builder RUN apt-get update && apt-get install -y --no-install-recommends git && rm -rf /var/lib/apt/lists/* COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /usr/local/bin/ WORKDIR /app -COPY pyproject.toml uv.lock ./ +COPY pyproject.toml uv.lock README.md ./ +COPY uploader ./uploader RUN uv sync --frozen --no-dev -FROM python:3.12-slim AS runtime +FROM python:3.13-slim AS runtime WORKDIR /app COPY --from=builder /app/.venv /app/.venv ENV PATH="/app/.venv/bin:$PATH" diff --git a/app/crossmatch/__init__.py b/app/crossmatch/__init__.py deleted file mode 100644 index cbfed05..0000000 --- a/app/crossmatch/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from app.crossmatch.engine import run_crossmatch - -__all__ = ["run_crossmatch"] diff --git a/app/crossmatch/layered/__init__.py b/app/crossmatch/layered/__init__.py deleted file mode 100644 index 6427380..0000000 --- a/app/crossmatch/layered/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from app.crossmatch.layered.resolver import LayeredResolver - -__all__ = ["LayeredResolver"] diff --git a/app/gen/.gitignore b/app/gen/.gitignore deleted file mode 100644 index d6b7ef3..0000000 --- a/app/gen/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/app/sources/__init__.py b/app/sources/__init__.py deleted file mode 100644 index 1cbaf24..0000000 --- a/app/sources/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from app.sources.csv import CSVSource -from app.sources.fits import FITSSource -from app.sources.vizier import VizierSource -from app.sources.vizier_v2 import VizierV2Source - -__all__ = ["CSVSource", "FITSSource", "VizierSource", "VizierV2Source"] diff --git a/app/structured/designations/__init__.py b/app/structured/designations/__init__.py deleted file mode 100644 index 73a4657..0000000 --- a/app/structured/designations/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from app.structured.designations.upload import upload_designations - -__all__ = ["upload_designations"] diff --git a/app/structured/icrs/__init__.py b/app/structured/icrs/__init__.py deleted file mode 100644 index 4ac5cb6..0000000 --- a/app/structured/icrs/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from app.structured.icrs.upload import upload_icrs - -__all__ = ["upload_icrs"] diff --git a/app/structured/nature/__init__.py b/app/structured/nature/__init__.py deleted file mode 100644 index 88a0862..0000000 --- a/app/structured/nature/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from app.structured.nature.upload import upload_nature - -__all__ = ["upload_nature"] diff --git a/app/structured/redshift/__init__.py b/app/structured/redshift/__init__.py deleted file mode 100644 index f203560..0000000 --- a/app/structured/redshift/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from app.structured.redshift.upload import upload_redshift - -__all__ = ["upload_redshift"] diff --git a/makefile b/makefile index 5c42b39..108f748 100644 --- a/makefile +++ b/makefile @@ -92,8 +92,9 @@ upgrade: uv sync --all-extras --upgrade gen: + mkdir -p uploader/clients/gen uv run openapi-python-client generate \ - --output-path app/gen/client \ + --output-path uploader/clients/gen/client \ --overwrite \ --meta uv \ --config openapigen.yaml \ @@ -102,7 +103,7 @@ gen: .PHONY: serve frontend dev check-frontend fix-frontend install-frontend install-dev-frontend serve: - uv run uvicorn server.main:app --reload --port 8000 + uv run uvicorn uploader.cli:app --reload --port 8000 frontend: cd frontend && yarn dev diff --git a/pyproject.toml b/pyproject.toml index 71038dc..d006c5b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,8 +16,16 @@ dependencies = [ "numpy>=2.3.4", "pyvo>=1.8", "psycopg[binary]>=3.2.0", + "click~=8.3.1", ] +[project.scripts] +"uploader" = "uploader.cli:cli" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + [dependency-groups] dev = [ "ruff~=0.15.0", @@ -120,7 +128,7 @@ reportImplicitAbstractClass = "error" exclude = [ "frontend/**", - "app/gen/**", + "uploader/clients/gen/**", ".venv/**" ] diff --git a/server/forms/__init__.py b/server/forms/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test_crossmatch_resolver.py b/tests/test_crossmatch_resolver.py index 2697ee3..e15c57e 100644 --- a/tests/test_crossmatch_resolver.py +++ b/tests/test_crossmatch_resolver.py @@ -1,4 +1,4 @@ -from app.crossmatch.models import ( +from uploader.app.crossmatch.models import ( CrossmatchResult, CrossmatchStatus, Neighbor, @@ -6,7 +6,7 @@ RecordEvidence, TriageStatus, ) -from app.crossmatch.resolver import ( +from uploader.app.crossmatch.resolver import ( _apply_redshift_check, _resolve_by_radius_coordinate, resolve, diff --git a/tests/test_designation_rules.py b/tests/test_designation_rules.py index b2146d5..40bee16 100644 --- a/tests/test_designation_rules.py +++ b/tests/test_designation_rules.py @@ -1,6 +1,6 @@ import pytest -from app.structured.designations.rules import match +from uploader.app.structured.designations.rules import match RULE_CASES: list[tuple[str, tuple[str, str] | None]] = [ ("2MASSJ16295276+3911433", ("CAT JHHMMSSss+DDMMSSs", "2MASS J16295276+3911433")), diff --git a/tests/test_server_integration.py b/tests/test_server_integration.py index 4b95d29..0b2348e 100644 --- a/tests/test_server_integration.py +++ b/tests/test_server_integration.py @@ -7,10 +7,10 @@ from fastapi.testclient import TestClient from pydantic import BaseModel -import app.report as report -import server.history as history -import server.tasks as tasks -from server.main import app +import uploader.app.report as report +import uploader.history as history +import uploader.tasks as tasks +from uploader.cli import app class FakeTaskForm(BaseModel): diff --git a/tests/test_upload.py b/tests/test_upload.py index f9010aa..43e7739 100644 --- a/tests/test_upload.py +++ b/tests/test_upload.py @@ -6,11 +6,11 @@ import pandas import pytest -from app.gen.client import adminapi -from app.gen.client.adminapi import models, types -from app.interface import UploaderSource -from app.sources.csv import CSVSource -from app.upload import upload +from uploader.app.interface import UploaderSource +from uploader.app.sources.csv import CSVSource +from uploader.app.upload import upload +from uploader.clients.gen.client import adminapi +from uploader.clients.gen.client.adminapi import models, types class StubPlugin(UploaderSource): @@ -47,9 +47,9 @@ def mock_response[T: Any](resp: T) -> types.Response[T]: ) -@patch("app.upload.create_source") -@patch("app.upload.create_table") -@patch("app.upload.add_data") +@patch("uploader.app.upload.create_source") +@patch("uploader.app.upload.create_table") +@patch("uploader.app.upload.add_data") def test_upload_with_csv_plugin(mock_add_data, mock_create_table, mock_create_source, mock_client): mock_create_source_response = models.APIOkResponseCreateSourceResponse( data=models.CreateSourceResponse(code="test_bibcode") @@ -81,8 +81,8 @@ def test_upload_with_csv_plugin(mock_add_data, mock_create_table, mock_create_so mock_add_data.sync_detailed.assert_called_once() -@patch("app.upload.create_source") -@patch("app.upload.create_table") +@patch("uploader.app.upload.create_source") +@patch("uploader.app.upload.create_table") def test_plugin_stop_called_on_error(mock_create_table, mock_create_source, mock_client): mock_create_source_response = models.APIOkResponseCreateSourceResponse( data=models.CreateSourceResponse(code="test_bibcode") diff --git a/uploader/__init__.py b/uploader/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/uploader/__init__.py @@ -0,0 +1 @@ + diff --git a/app/__init__.py b/uploader/app/__init__.py similarity index 61% rename from app/__init__.py rename to uploader/app/__init__.py index e9e69a0..c81b88f 100644 --- a/app/__init__.py +++ b/uploader/app/__init__.py @@ -1,12 +1,12 @@ -from app.interface import ( +from uploader.app.interface import ( BibcodeProvider, DefaultTableNamer, DescriptionProvider, UploaderSource, ) -from app.log import logger -from app.tap import Constraint, TAPRepository -from app.upload import upload +from uploader.app.log import logger +from uploader.app.tap import Constraint, TAPRepository +from uploader.app.upload import upload __all__ = [ "UploaderSource", diff --git a/uploader/app/crossmatch/__init__.py b/uploader/app/crossmatch/__init__.py new file mode 100644 index 0000000..df60ca4 --- /dev/null +++ b/uploader/app/crossmatch/__init__.py @@ -0,0 +1,3 @@ +from uploader.app.crossmatch.engine import run_crossmatch + +__all__ = ["run_crossmatch"] diff --git a/app/crossmatch/engine.py b/uploader/app/crossmatch/engine.py similarity index 93% rename from app/crossmatch/engine.py rename to uploader/app/crossmatch/engine.py index a5d926c..bfd24da 100644 --- a/app/crossmatch/engine.py +++ b/uploader/app/crossmatch/engine.py @@ -7,9 +7,9 @@ from psycopg import sql -import app.report as report -from app import log -from app.crossmatch.models import ( +import uploader.app.report as report +from uploader.app import log +from uploader.app.crossmatch.models import ( CrossmatchResult, CrossmatchStatus, Neighbor, @@ -17,21 +17,21 @@ RecordEvidence, TriageStatus, ) -from app.crossmatch.resolver import Resolver -from app.display import format_table -from app.gen.client import adminapi -from app.gen.client.adminapi.api.default import set_crossmatch_results -from app.gen.client.adminapi.models.collided_status_payload import CollidedStatusPayload -from app.gen.client.adminapi.models.existing_status_payload import ExistingStatusPayload -from app.gen.client.adminapi.models.new_status_payload import NewStatusPayload -from app.gen.client.adminapi.models.record_triage_status import RecordTriageStatus -from app.gen.client.adminapi.models.set_crossmatch_results_request import ( +from uploader.app.crossmatch.resolver import Resolver +from uploader.app.display import format_table +from uploader.app.storage import PgStorage +from uploader.app.upload import handle_call +from uploader.clients.gen.client import adminapi +from uploader.clients.gen.client.adminapi.api.default import set_crossmatch_results +from uploader.clients.gen.client.adminapi.models.collided_status_payload import CollidedStatusPayload +from uploader.clients.gen.client.adminapi.models.existing_status_payload import ExistingStatusPayload +from uploader.clients.gen.client.adminapi.models.new_status_payload import NewStatusPayload +from uploader.clients.gen.client.adminapi.models.record_triage_status import RecordTriageStatus +from uploader.clients.gen.client.adminapi.models.set_crossmatch_results_request import ( SetCrossmatchResultsRequest, ) -from app.gen.client.adminapi.models.statuses_payload import StatusesPayload -from app.gen.client.adminapi.types import UNSET, Unset -from app.storage import PgStorage -from app.upload import handle_call +from uploader.clients.gen.client.adminapi.models.statuses_payload import StatusesPayload +from uploader.clients.gen.client.adminapi.types import UNSET, Unset C_M_S = 299792458 diff --git a/uploader/app/crossmatch/layered/__init__.py b/uploader/app/crossmatch/layered/__init__.py new file mode 100644 index 0000000..0303752 --- /dev/null +++ b/uploader/app/crossmatch/layered/__init__.py @@ -0,0 +1,3 @@ +from uploader.app.crossmatch.layered.resolver import LayeredResolver + +__all__ = ["LayeredResolver"] diff --git a/app/crossmatch/layered/icrs.py b/uploader/app/crossmatch/layered/icrs.py similarity index 84% rename from app/crossmatch/layered/icrs.py rename to uploader/app/crossmatch/layered/icrs.py index 5520b51..204453f 100644 --- a/app/crossmatch/layered/icrs.py +++ b/uploader/app/crossmatch/layered/icrs.py @@ -1,10 +1,10 @@ -from app.crossmatch.layered.models import ( +from uploader.app.crossmatch.layered.models import ( PreliminaryCrossmatchStatus, PreliminaryCrossmatchStatusColliding, PreliminaryCrossmatchStatusExisting, PreliminaryCrossmatchStatusNew, ) -from app.crossmatch.models import PendingReason, RecordEvidence +from uploader.app.crossmatch.models import PendingReason, RecordEvidence def icrs_simple_resolver( diff --git a/app/crossmatch/layered/models.py b/uploader/app/crossmatch/layered/models.py similarity index 100% rename from app/crossmatch/layered/models.py rename to uploader/app/crossmatch/layered/models.py diff --git a/app/crossmatch/layered/name.py b/uploader/app/crossmatch/layered/name.py similarity index 94% rename from app/crossmatch/layered/name.py rename to uploader/app/crossmatch/layered/name.py index f7b76ab..8763797 100644 --- a/app/crossmatch/layered/name.py +++ b/uploader/app/crossmatch/layered/name.py @@ -1,10 +1,10 @@ -from app.crossmatch.layered.models import ( +from uploader.app.crossmatch.layered.models import ( PreliminaryCrossmatchStatus, PreliminaryCrossmatchStatusColliding, PreliminaryCrossmatchStatusExisting, PreliminaryCrossmatchStatusNew, ) -from app.crossmatch.models import PendingReason, RecordEvidence +from uploader.app.crossmatch.models import PendingReason, RecordEvidence def name_resolver( diff --git a/app/crossmatch/layered/object_type.py b/uploader/app/crossmatch/layered/object_type.py similarity index 92% rename from app/crossmatch/layered/object_type.py rename to uploader/app/crossmatch/layered/object_type.py index b28f760..8dcc422 100644 --- a/app/crossmatch/layered/object_type.py +++ b/uploader/app/crossmatch/layered/object_type.py @@ -1,9 +1,9 @@ -from app.crossmatch.layered.models import ( +from uploader.app.crossmatch.layered.models import ( PreliminaryCrossmatchStatus, PreliminaryCrossmatchStatusExisting, PreliminaryCrossmatchStatusNew, ) -from app.crossmatch.models import PendingReason, RecordEvidence +from uploader.app.crossmatch.models import PendingReason, RecordEvidence SIMILAR_TYPE_MAP = { "G": {"ext", "?", "QSO"}, diff --git a/app/crossmatch/layered/pgc.py b/uploader/app/crossmatch/layered/pgc.py similarity index 90% rename from app/crossmatch/layered/pgc.py rename to uploader/app/crossmatch/layered/pgc.py index b945382..777dcb2 100644 --- a/app/crossmatch/layered/pgc.py +++ b/uploader/app/crossmatch/layered/pgc.py @@ -1,10 +1,10 @@ -from app.crossmatch.layered.models import ( +from uploader.app.crossmatch.layered.models import ( PreliminaryCrossmatchStatus, PreliminaryCrossmatchStatusColliding, PreliminaryCrossmatchStatusExisting, PreliminaryCrossmatchStatusNew, ) -from app.crossmatch.models import PendingReason, RecordEvidence +from uploader.app.crossmatch.models import PendingReason, RecordEvidence def pgc_resolver( diff --git a/app/crossmatch/layered/redshift.py b/uploader/app/crossmatch/layered/redshift.py similarity index 92% rename from app/crossmatch/layered/redshift.py rename to uploader/app/crossmatch/layered/redshift.py index 2858751..6b08ac6 100644 --- a/app/crossmatch/layered/redshift.py +++ b/uploader/app/crossmatch/layered/redshift.py @@ -1,9 +1,9 @@ -from app.crossmatch.layered.models import ( +from uploader.app.crossmatch.layered.models import ( PreliminaryCrossmatchStatus, PreliminaryCrossmatchStatusExisting, PreliminaryCrossmatchStatusNew, ) -from app.crossmatch.models import PendingReason, RecordEvidence +from uploader.app.crossmatch.models import PendingReason, RecordEvidence def redshift_resolver( diff --git a/app/crossmatch/layered/resolver.py b/uploader/app/crossmatch/layered/resolver.py similarity index 91% rename from app/crossmatch/layered/resolver.py rename to uploader/app/crossmatch/layered/resolver.py index 7f42292..9caf6d8 100644 --- a/app/crossmatch/layered/resolver.py +++ b/uploader/app/crossmatch/layered/resolver.py @@ -1,10 +1,16 @@ -from app.crossmatch.layered import icrs, name, object_type, pgc, redshift -from app.crossmatch.layered.models import ( +from uploader.app.crossmatch.layered import icrs, name, object_type, pgc, redshift +from uploader.app.crossmatch.layered.models import ( PreliminaryCrossmatchStatus, PreliminaryCrossmatchStatusExisting, PreliminaryCrossmatchStatusNew, ) -from app.crossmatch.models import CrossmatchResult, CrossmatchStatus, PendingReason, RecordEvidence, TriageStatus +from uploader.app.crossmatch.models import ( + CrossmatchResult, + CrossmatchStatus, + PendingReason, + RecordEvidence, + TriageStatus, +) def _preliminary_to_final(results: PreliminaryCrossmatchStatus, pending_reason: PendingReason) -> CrossmatchResult: diff --git a/app/crossmatch/models.py b/uploader/app/crossmatch/models.py similarity index 100% rename from app/crossmatch/models.py rename to uploader/app/crossmatch/models.py diff --git a/app/crossmatch/resolver.py b/uploader/app/crossmatch/resolver.py similarity index 99% rename from app/crossmatch/resolver.py rename to uploader/app/crossmatch/resolver.py index 7a46c67..5abc5d5 100644 --- a/app/crossmatch/resolver.py +++ b/uploader/app/crossmatch/resolver.py @@ -31,8 +31,8 @@ from typing import Protocol -from app.crossmatch import layered -from app.crossmatch.models import ( +from uploader.app.crossmatch import layered +from uploader.app.crossmatch.models import ( CrossmatchResult, CrossmatchStatus, Neighbor, diff --git a/app/display.py b/uploader/app/display.py similarity index 100% rename from app/display.py rename to uploader/app/display.py diff --git a/app/endpoints.py b/uploader/app/endpoints.py similarity index 100% rename from app/endpoints.py rename to uploader/app/endpoints.py diff --git a/app/interface.py b/uploader/app/interface.py similarity index 97% rename from app/interface.py rename to uploader/app/interface.py index 69ede88..7d69759 100644 --- a/app/interface.py +++ b/uploader/app/interface.py @@ -3,7 +3,7 @@ import pandas -from app.gen.client.adminapi import models +from uploader.clients.gen.client.adminapi import models class UploaderSource(abc.ABC): diff --git a/app/lib/__init__.py b/uploader/app/lib/__init__.py similarity index 100% rename from app/lib/__init__.py rename to uploader/app/lib/__init__.py diff --git a/app/lib/rawdata.py b/uploader/app/lib/rawdata.py similarity index 93% rename from app/lib/rawdata.py rename to uploader/app/lib/rawdata.py index 1591df3..810979d 100644 --- a/app/lib/rawdata.py +++ b/uploader/app/lib/rawdata.py @@ -3,8 +3,8 @@ from psycopg import sql -from app import log -from app.storage import PgStorage +from uploader.app import log +from uploader.app.storage import PgStorage def rawdata_batches( diff --git a/app/log.py b/uploader/app/log.py similarity index 100% rename from app/log.py rename to uploader/app/log.py diff --git a/app/report.py b/uploader/app/report.py similarity index 100% rename from app/report.py rename to uploader/app/report.py diff --git a/uploader/app/sources/__init__.py b/uploader/app/sources/__init__.py new file mode 100644 index 0000000..57b02f3 --- /dev/null +++ b/uploader/app/sources/__init__.py @@ -0,0 +1,6 @@ +from uploader.app.sources.csv import CSVSource +from uploader.app.sources.fits import FITSSource +from uploader.app.sources.vizier import VizierSource +from uploader.app.sources.vizier_v2 import VizierV2Source + +__all__ = ["CSVSource", "FITSSource", "VizierSource", "VizierV2Source"] diff --git a/app/sources/csv.py b/uploader/app/sources/csv.py similarity index 96% rename from app/sources/csv.py rename to uploader/app/sources/csv.py index f1c8cf5..bdeedcc 100644 --- a/app/sources/csv.py +++ b/uploader/app/sources/csv.py @@ -4,8 +4,8 @@ import pandas -import app -from app.gen.client.adminapi import models +import uploader.app as app +from uploader.clients.gen.client.adminapi import models type_map = { "object": models.DatatypeEnum.STRING, diff --git a/app/sources/fits.py b/uploader/app/sources/fits.py similarity index 96% rename from app/sources/fits.py rename to uploader/app/sources/fits.py index 5e101cb..95439d6 100644 --- a/app/sources/fits.py +++ b/uploader/app/sources/fits.py @@ -5,8 +5,8 @@ import pandas from astropy.io import fits -import app -from app.gen.client.adminapi import models +import uploader.app as app +from uploader.clients.gen.client.adminapi import models type_map = { "object": models.DatatypeEnum.STRING, diff --git a/app/sources/vizier.py b/uploader/app/sources/vizier.py similarity index 98% rename from app/sources/vizier.py rename to uploader/app/sources/vizier.py index eaa45e2..f60dd8c 100644 --- a/app/sources/vizier.py +++ b/uploader/app/sources/vizier.py @@ -11,8 +11,8 @@ from astropy.io.votable import tree from astroquery import vizier -import app -from app.gen.client.adminapi import models, types +import uploader.app as app +from uploader.clients.gen.client.adminapi import models, types VIZIER_URL = "https://vizier.cds.unistra.fr/viz-bin/votable/-tsv" diff --git a/app/sources/vizier_v2.py b/uploader/app/sources/vizier_v2.py similarity index 98% rename from app/sources/vizier_v2.py rename to uploader/app/sources/vizier_v2.py index 9fb40bd..a26a990 100644 --- a/app/sources/vizier_v2.py +++ b/uploader/app/sources/vizier_v2.py @@ -5,8 +5,8 @@ import pandas from astroquery import vizier -import app -from app.gen.client.adminapi import models, types +import uploader.app as app +from uploader.clients.gen.client.adminapi import models, types def _sanitize_filename(string: str) -> str: diff --git a/app/storage.py b/uploader/app/storage.py similarity index 97% rename from app/storage.py rename to uploader/app/storage.py index cfedc3b..cbcc555 100644 --- a/app/storage.py +++ b/uploader/app/storage.py @@ -5,7 +5,7 @@ from psycopg.connection import Connection from psycopg.rows import dict_row -from app import log +from uploader.app import log class PgStorage: diff --git a/uploader/app/structured/designations/__init__.py b/uploader/app/structured/designations/__init__.py new file mode 100644 index 0000000..cf13455 --- /dev/null +++ b/uploader/app/structured/designations/__init__.py @@ -0,0 +1,3 @@ +from uploader.app.structured.designations.upload import upload_designations + +__all__ = ["upload_designations"] diff --git a/app/structured/designations/rules.py b/uploader/app/structured/designations/rules.py similarity index 100% rename from app/structured/designations/rules.py rename to uploader/app/structured/designations/rules.py diff --git a/app/structured/designations/upload.py b/uploader/app/structured/designations/upload.py similarity index 87% rename from app/structured/designations/upload.py rename to uploader/app/structured/designations/upload.py index a8ee489..1fab55f 100644 --- a/app/structured/designations/upload.py +++ b/uploader/app/structured/designations/upload.py @@ -2,18 +2,18 @@ from psycopg import sql -import app.report as report -from app import log -from app.display import format_table -from app.gen.client import adminapi -from app.gen.client.adminapi.api.default import save_structured_data -from app.gen.client.adminapi.models.save_structured_data_request import ( +import uploader.app.report as report +from uploader.app import log +from uploader.app.display import format_table +from uploader.app.lib.rawdata import rawdata_batches +from uploader.app.storage import PgStorage +from uploader.app.structured.designations.rules import RULES, match +from uploader.app.upload import handle_call +from uploader.clients.gen.client import adminapi +from uploader.clients.gen.client.adminapi.api.default import save_structured_data +from uploader.clients.gen.client.adminapi.models.save_structured_data_request import ( SaveStructuredDataRequest, ) -from app.lib.rawdata import rawdata_batches -from app.storage import PgStorage -from app.structured.designations.rules import RULES, match -from app.upload import handle_call def upload_designations( diff --git a/uploader/app/structured/icrs/__init__.py b/uploader/app/structured/icrs/__init__.py new file mode 100644 index 0000000..e88555b --- /dev/null +++ b/uploader/app/structured/icrs/__init__.py @@ -0,0 +1,3 @@ +from uploader.app.structured.icrs.upload import upload_icrs + +__all__ = ["upload_icrs"] diff --git a/app/structured/icrs/upload.py b/uploader/app/structured/icrs/upload.py similarity index 89% rename from app/structured/icrs/upload.py rename to uploader/app/structured/icrs/upload.py index 85a5740..4662ac7 100644 --- a/app/structured/icrs/upload.py +++ b/uploader/app/structured/icrs/upload.py @@ -2,19 +2,19 @@ from psycopg import sql -import app.report as report -from app.display import format_table -from app.gen.client import adminapi -from app.gen.client.adminapi.api.default import get_table, save_structured_data -from app.gen.client.adminapi.models.save_structured_data_request import ( +import uploader.app.report as report +from uploader.app.display import format_table +from uploader.app.lib.rawdata import rawdata_batches +from uploader.app.storage import PgStorage +from uploader.app.upload import handle_call +from uploader.clients.gen.client import adminapi +from uploader.clients.gen.client.adminapi.api.default import get_table, save_structured_data +from uploader.clients.gen.client.adminapi.models.save_structured_data_request import ( SaveStructuredDataRequest, ) -from app.gen.client.adminapi.models.save_structured_data_request_units import ( +from uploader.clients.gen.client.adminapi.models.save_structured_data_request_units import ( SaveStructuredDataRequestUnits, ) -from app.lib.rawdata import rawdata_batches -from app.storage import PgStorage -from app.upload import handle_call ICRS_COLUMNS = ["ra", "dec", "e_ra", "e_dec"] diff --git a/uploader/app/structured/nature/__init__.py b/uploader/app/structured/nature/__init__.py new file mode 100644 index 0000000..0fe7c53 --- /dev/null +++ b/uploader/app/structured/nature/__init__.py @@ -0,0 +1,3 @@ +from uploader.app.structured.nature.upload import upload_nature + +__all__ = ["upload_nature"] diff --git a/app/structured/nature/upload.py b/uploader/app/structured/nature/upload.py similarity index 87% rename from app/structured/nature/upload.py rename to uploader/app/structured/nature/upload.py index 961e7be..6b23335 100644 --- a/app/structured/nature/upload.py +++ b/uploader/app/structured/nature/upload.py @@ -3,16 +3,16 @@ from psycopg import sql -import app.report as report -from app.display import format_table -from app.gen.client import adminapi -from app.gen.client.adminapi.api.default import save_structured_data -from app.gen.client.adminapi.models.save_structured_data_request import ( +import uploader.app.report as report +from uploader.app.display import format_table +from uploader.app.lib.rawdata import rawdata_batches +from uploader.app.storage import PgStorage +from uploader.app.upload import handle_call +from uploader.clients.gen.client import adminapi +from uploader.clients.gen.client.adminapi.api.default import save_structured_data +from uploader.clients.gen.client.adminapi.models.save_structured_data_request import ( SaveStructuredDataRequest, ) -from app.lib.rawdata import rawdata_batches -from app.storage import PgStorage -from app.upload import handle_call NATURE_COLUMNS = ["type_name"] diff --git a/app/structured/photometry/__init__.py b/uploader/app/structured/photometry/__init__.py similarity index 100% rename from app/structured/photometry/__init__.py rename to uploader/app/structured/photometry/__init__.py diff --git a/app/structured/photometry/upload.py b/uploader/app/structured/photometry/upload.py similarity index 88% rename from app/structured/photometry/upload.py rename to uploader/app/structured/photometry/upload.py index d78e60e..416e08c 100644 --- a/app/structured/photometry/upload.py +++ b/uploader/app/structured/photometry/upload.py @@ -2,20 +2,20 @@ from psycopg import sql -import app.report as report -from app import log -from app.display import format_table -from app.gen.client import adminapi -from app.gen.client.adminapi.api.default import save_structured_data -from app.gen.client.adminapi.models.save_structured_data_request import ( +import uploader.app.report as report +from uploader.app import log +from uploader.app.display import format_table +from uploader.app.lib.rawdata import rawdata_batches +from uploader.app.storage import PgStorage +from uploader.app.upload import handle_call +from uploader.clients.gen.client import adminapi +from uploader.clients.gen.client.adminapi.api.default import save_structured_data +from uploader.clients.gen.client.adminapi.models.save_structured_data_request import ( SaveStructuredDataRequest, ) -from app.gen.client.adminapi.models.save_structured_data_request_units import ( +from uploader.clients.gen.client.adminapi.models.save_structured_data_request_units import ( SaveStructuredDataRequestUnits, ) -from app.lib.rawdata import rawdata_batches -from app.storage import PgStorage -from app.upload import handle_call PHOTOMETRY_COLUMNS = ["band", "mag", "e_mag", "method"] diff --git a/uploader/app/structured/redshift/__init__.py b/uploader/app/structured/redshift/__init__.py new file mode 100644 index 0000000..2ae9ae5 --- /dev/null +++ b/uploader/app/structured/redshift/__init__.py @@ -0,0 +1,3 @@ +from uploader.app.structured.redshift.upload import upload_redshift + +__all__ = ["upload_redshift"] diff --git a/app/structured/redshift/upload.py b/uploader/app/structured/redshift/upload.py similarity index 85% rename from app/structured/redshift/upload.py rename to uploader/app/structured/redshift/upload.py index 0137cc9..4f406b4 100644 --- a/app/structured/redshift/upload.py +++ b/uploader/app/structured/redshift/upload.py @@ -2,19 +2,19 @@ from psycopg import sql -import app.report as report -from app.display import format_table -from app.gen.client import adminapi -from app.gen.client.adminapi.api.default import save_structured_data -from app.gen.client.adminapi.models.save_structured_data_request import ( +import uploader.app.report as report +from uploader.app.display import format_table +from uploader.app.lib.rawdata import rawdata_batches +from uploader.app.storage import PgStorage +from uploader.app.upload import handle_call +from uploader.clients.gen.client import adminapi +from uploader.clients.gen.client.adminapi.api.default import save_structured_data +from uploader.clients.gen.client.adminapi.models.save_structured_data_request import ( SaveStructuredDataRequest, ) -from app.gen.client.adminapi.models.save_structured_data_request_units import ( +from uploader.clients.gen.client.adminapi.models.save_structured_data_request_units import ( SaveStructuredDataRequestUnits, ) -from app.lib.rawdata import rawdata_batches -from app.storage import PgStorage -from app.upload import handle_call C_KM_S = 299792.458 diff --git a/app/tap.py b/uploader/app/tap.py similarity index 98% rename from app/tap.py rename to uploader/app/tap.py index 389dc06..ab99baf 100644 --- a/app/tap.py +++ b/uploader/app/tap.py @@ -3,7 +3,7 @@ from astropy import table from pyvo import registry -import app +import uploader.app as app TAP_ENDPOINT = "https://tapvizier.cds.unistra.fr/TAPVizieR/tap/sync" diff --git a/app/upload.py b/uploader/app/upload.py similarity index 94% rename from app/upload.py rename to uploader/app/upload.py index 87b858c..e9ea600 100644 --- a/app/upload.py +++ b/uploader/app/upload.py @@ -5,12 +5,12 @@ import click -import app.report as report -from app import interface, log -from app.display import format_table -from app.gen.client import adminapi -from app.gen.client.adminapi import models, types -from app.gen.client.adminapi.api.default import ( +import uploader.app.report as report +from uploader.app import interface, log +from uploader.app.display import format_table +from uploader.clients.gen.client import adminapi +from uploader.clients.gen.client.adminapi import models, types +from uploader.clients.gen.client.adminapi.api.default import ( add_data, create_source, create_table, diff --git a/server/main.py b/uploader/cli.py similarity index 79% rename from server/main.py rename to uploader/cli.py index 06699a7..032da56 100644 --- a/server/main.py +++ b/uploader/cli.py @@ -2,14 +2,16 @@ import json from typing import Any +import click +import uvicorn from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import StreamingResponse from pydantic import ValidationError -from server.history import load_history -from server.task_registry import register_all_tasks -from server.tasks import TASKS, get_run, start_task +from uploader.history import load_history +from uploader.task_registry import register_all_tasks +from uploader.tasks import TASKS, get_run, start_task register_all_tasks() @@ -54,7 +56,7 @@ def task_schema(task_id: str) -> dict[str, object]: @app.post("/api/tasks/{task_id}/submit") -def submit_task(task_id: str, body: dict) -> dict[str, str]: +def submit_task(task_id: str, body: dict[str, object]) -> dict[str, str]: if task_id not in TASKS: raise HTTPException(status_code=404, detail="Unknown task") try: @@ -70,7 +72,7 @@ async def run_stream(run_id: str) -> StreamingResponse: if run is None: raise HTTPException(status_code=404, detail="Unknown run") - async def event_gen(): + async def event_gen() -> Any: idx = 0 while True: chunk, idx = run.snapshot_from(idx) @@ -86,3 +88,15 @@ async def event_gen(): await asyncio.sleep(0.15) return StreamingResponse(event_gen(), media_type="text/event-stream") + + +@click.group() +def cli() -> None: + return None + + +@cli.command("serve") +@click.option("--reload", is_flag=True, default=False) +@click.option("--port", type=int, default=8000) +def serve_command(reload: bool, port: int) -> None: + uvicorn.run("uploader.cli:app", host="0.0.0.0", port=port, reload=reload) diff --git a/server/credentials.py b/uploader/credentials.py similarity index 100% rename from server/credentials.py rename to uploader/credentials.py diff --git a/server/__init__.py b/uploader/forms/__init__.py similarity index 100% rename from server/__init__.py rename to uploader/forms/__init__.py diff --git a/server/forms/authenticate.py b/uploader/forms/authenticate.py similarity index 90% rename from server/forms/authenticate.py rename to uploader/forms/authenticate.py index 955ddca..772118c 100644 --- a/server/forms/authenticate.py +++ b/uploader/forms/authenticate.py @@ -5,9 +5,9 @@ from psycopg import connect from pydantic import BaseModel, Field -import app.report as report -from app.endpoints import db_dsn_map -from server.credentials import save_credentials +import uploader.app.report as report +from uploader.app.endpoints import db_dsn_map +from uploader.credentials import save_credentials class AuthenticateForm(BaseModel): diff --git a/server/forms/crossmatch_default.py b/uploader/forms/crossmatch_default.py similarity index 82% rename from server/forms/crossmatch_default.py rename to uploader/forms/crossmatch_default.py index 0970171..6e4d66f 100644 --- a/server/forms/crossmatch_default.py +++ b/uploader/forms/crossmatch_default.py @@ -5,13 +5,13 @@ from psycopg import connect from pydantic import BaseModel, Field -import app.report as report -from app.crossmatch import run_crossmatch as run_crossmatch_cmd -from app.crossmatch.resolver import DefaultResolver -from app.endpoints import db_dsn_map, env_map -from app.gen.client import adminapi -from app.storage import PgStorage -from server.credentials import load_credentials +import uploader.app.report as report +from uploader.app.crossmatch import run_crossmatch as run_crossmatch_cmd +from uploader.app.crossmatch.resolver import DefaultResolver +from uploader.app.endpoints import db_dsn_map, env_map +from uploader.app.storage import PgStorage +from uploader.clients.gen.client import adminapi +from uploader.credentials import load_credentials class CrossmatchDefaultForm(BaseModel): diff --git a/server/forms/crossmatch_layered.py b/uploader/forms/crossmatch_layered.py similarity index 85% rename from server/forms/crossmatch_layered.py rename to uploader/forms/crossmatch_layered.py index a4a215d..a6d1f62 100644 --- a/server/forms/crossmatch_layered.py +++ b/uploader/forms/crossmatch_layered.py @@ -5,13 +5,13 @@ from psycopg import connect from pydantic import BaseModel, Field -import app.report as report -from app.crossmatch import run_crossmatch as run_crossmatch_cmd -from app.crossmatch.resolver import LayeredResolver -from app.endpoints import db_dsn_map, env_map -from app.gen.client import adminapi -from app.storage import PgStorage -from server.credentials import load_credentials +import uploader.app.report as report +from uploader.app.crossmatch import run_crossmatch as run_crossmatch_cmd +from uploader.app.crossmatch.resolver import LayeredResolver +from uploader.app.endpoints import db_dsn_map, env_map +from uploader.app.storage import PgStorage +from uploader.clients.gen.client import adminapi +from uploader.credentials import load_credentials class CrossmatchLayeredForm(BaseModel): diff --git a/server/forms/crossmatch_two_radii.py b/uploader/forms/crossmatch_two_radii.py similarity index 83% rename from server/forms/crossmatch_two_radii.py rename to uploader/forms/crossmatch_two_radii.py index b592cee..0289458 100644 --- a/server/forms/crossmatch_two_radii.py +++ b/uploader/forms/crossmatch_two_radii.py @@ -5,13 +5,13 @@ from psycopg import connect from pydantic import BaseModel, Field -import app.report as report -from app.crossmatch import run_crossmatch as run_crossmatch_cmd -from app.crossmatch.resolver import TwoRadiiResolver -from app.endpoints import db_dsn_map, env_map -from app.gen.client import adminapi -from app.storage import PgStorage -from server.credentials import load_credentials +import uploader.app.report as report +from uploader.app.crossmatch import run_crossmatch as run_crossmatch_cmd +from uploader.app.crossmatch.resolver import TwoRadiiResolver +from uploader.app.endpoints import db_dsn_map, env_map +from uploader.app.storage import PgStorage +from uploader.clients.gen.client import adminapi +from uploader.credentials import load_credentials class CrossmatchTwoRadiiForm(BaseModel): diff --git a/server/forms/structured_designation.py b/uploader/forms/structured_designation.py similarity index 84% rename from server/forms/structured_designation.py rename to uploader/forms/structured_designation.py index e32d0c6..d5a8e2f 100644 --- a/server/forms/structured_designation.py +++ b/uploader/forms/structured_designation.py @@ -5,12 +5,12 @@ from psycopg import connect from pydantic import BaseModel, Field -import app.report as report -from app.endpoints import db_dsn_map, env_map -from app.gen.client import adminapi -from app.storage import PgStorage -from app.structured.designations import upload_designations as run_upload_designations -from server.credentials import load_credentials +import uploader.app.report as report +from uploader.app.endpoints import db_dsn_map, env_map +from uploader.app.storage import PgStorage +from uploader.app.structured.designations import upload_designations as run_upload_designations +from uploader.clients.gen.client import adminapi +from uploader.credentials import load_credentials class StructuredDesignationForm(BaseModel): diff --git a/server/forms/structured_icrs.py b/uploader/forms/structured_icrs.py similarity index 87% rename from server/forms/structured_icrs.py rename to uploader/forms/structured_icrs.py index 3213edd..2f51281 100644 --- a/server/forms/structured_icrs.py +++ b/uploader/forms/structured_icrs.py @@ -5,12 +5,12 @@ from psycopg import connect from pydantic import BaseModel, Field -import app.report as report -from app.endpoints import db_dsn_map, env_map -from app.gen.client import adminapi -from app.storage import PgStorage -from app.structured.icrs import upload_icrs as run_upload_icrs -from server.credentials import load_credentials +import uploader.app.report as report +from uploader.app.endpoints import db_dsn_map, env_map +from uploader.app.storage import PgStorage +from uploader.app.structured.icrs import upload_icrs as run_upload_icrs +from uploader.clients.gen.client import adminapi +from uploader.credentials import load_credentials class StructuredIcrsForm(BaseModel): diff --git a/server/forms/structured_nature.py b/uploader/forms/structured_nature.py similarity index 91% rename from server/forms/structured_nature.py rename to uploader/forms/structured_nature.py index cd18bb8..72631ae 100644 --- a/server/forms/structured_nature.py +++ b/uploader/forms/structured_nature.py @@ -5,12 +5,12 @@ from psycopg import connect from pydantic import BaseModel, ConfigDict, Field -import app.report as report -from app.endpoints import db_dsn_map, env_map -from app.gen.client import adminapi -from app.storage import PgStorage -from app.structured.nature import upload_nature as run_upload_nature -from server.credentials import load_credentials +import uploader.app.report as report +from uploader.app.endpoints import db_dsn_map, env_map +from uploader.app.storage import PgStorage +from uploader.app.structured.nature import upload_nature as run_upload_nature +from uploader.clients.gen.client import adminapi +from uploader.credentials import load_credentials class StructuredNatureForm(BaseModel): diff --git a/server/forms/structured_photometry_hyperleda.py b/uploader/forms/structured_photometry_hyperleda.py similarity index 83% rename from server/forms/structured_photometry_hyperleda.py rename to uploader/forms/structured_photometry_hyperleda.py index e2f5ef3..072d4c7 100644 --- a/server/forms/structured_photometry_hyperleda.py +++ b/uploader/forms/structured_photometry_hyperleda.py @@ -5,14 +5,14 @@ from psycopg import connect from pydantic import BaseModel, Field -import app.report as report -from app.endpoints import db_dsn_map, env_map -from app.gen.client import adminapi -from app.storage import PgStorage -from app.structured.photometry.upload import ( +import uploader.app.report as report +from uploader.app.endpoints import db_dsn_map, env_map +from uploader.app.storage import PgStorage +from uploader.app.structured.photometry.upload import ( upload_photometry_hyperleda as run_upload_photometry_hyperleda, ) -from server.credentials import load_credentials +from uploader.clients.gen.client import adminapi +from uploader.credentials import load_credentials class StructuredPhotometryHyperledaForm(BaseModel): diff --git a/server/forms/structured_redshift.py b/uploader/forms/structured_redshift.py similarity index 83% rename from server/forms/structured_redshift.py rename to uploader/forms/structured_redshift.py index 774e9fa..5585123 100644 --- a/server/forms/structured_redshift.py +++ b/uploader/forms/structured_redshift.py @@ -5,12 +5,12 @@ from psycopg import connect from pydantic import BaseModel, Field -import app.report as report -from app.endpoints import db_dsn_map, env_map -from app.gen.client import adminapi -from app.storage import PgStorage -from app.structured.redshift import upload_redshift as run_upload_redshift -from server.credentials import load_credentials +import uploader.app.report as report +from uploader.app.endpoints import db_dsn_map, env_map +from uploader.app.storage import PgStorage +from uploader.app.structured.redshift import upload_redshift as run_upload_redshift +from uploader.clients.gen.client import adminapi +from uploader.credentials import load_credentials class StructuredRedshiftForm(BaseModel): diff --git a/server/forms/upload_base.py b/uploader/forms/upload_base.py similarity index 100% rename from server/forms/upload_base.py rename to uploader/forms/upload_base.py diff --git a/server/forms/upload_csv.py b/uploader/forms/upload_csv.py similarity index 77% rename from server/forms/upload_csv.py rename to uploader/forms/upload_csv.py index 47be29c..765a7fc 100644 --- a/server/forms/upload_csv.py +++ b/uploader/forms/upload_csv.py @@ -3,12 +3,12 @@ from pydantic import BaseModel, Field -import app.report as report -from app.endpoints import env_map -from app.gen.client import adminapi -from app.sources.csv import CSVSource -from app.upload import upload_for_web -from server.forms.upload_base import UploadBaseForm +import uploader.app.report as report +from uploader.app.endpoints import env_map +from uploader.app.sources.csv import CSVSource +from uploader.app.upload import upload_for_web +from uploader.clients.gen.client import adminapi +from uploader.forms.upload_base import UploadBaseForm class UploadCsvForm(UploadBaseForm): diff --git a/server/forms/upload_fits.py b/uploader/forms/upload_fits.py similarity index 78% rename from server/forms/upload_fits.py rename to uploader/forms/upload_fits.py index 36b90fd..2dd6ef6 100644 --- a/server/forms/upload_fits.py +++ b/uploader/forms/upload_fits.py @@ -3,12 +3,12 @@ from pydantic import BaseModel, Field -import app.report as report -from app.endpoints import env_map -from app.gen.client import adminapi -from app.sources.fits import FITSSource -from app.upload import upload_for_web -from server.forms.upload_base import UploadBaseForm +import uploader.app.report as report +from uploader.app.endpoints import env_map +from uploader.app.sources.fits import FITSSource +from uploader.app.upload import upload_for_web +from uploader.clients.gen.client import adminapi +from uploader.forms.upload_base import UploadBaseForm class UploadFitsForm(UploadBaseForm): diff --git a/server/forms/upload_vizier.py b/uploader/forms/upload_vizier.py similarity index 93% rename from server/forms/upload_vizier.py rename to uploader/forms/upload_vizier.py index a4307fe..a78de52 100644 --- a/server/forms/upload_vizier.py +++ b/uploader/forms/upload_vizier.py @@ -4,11 +4,11 @@ from pydantic import BaseModel, Field -import app.report as report -from app.endpoints import env_map -from app.gen.client import adminapi -from app.sources.vizier import VizierSource -from app.upload import upload_for_web +import uploader.app.report as report +from uploader.app.endpoints import env_map +from uploader.app.sources.vizier import VizierSource +from uploader.app.upload import upload_for_web +from uploader.clients.gen.client import adminapi class UploadVizierForm(BaseModel): diff --git a/server/forms/upload_vizier_v2.py b/uploader/forms/upload_vizier_v2.py similarity index 84% rename from server/forms/upload_vizier_v2.py rename to uploader/forms/upload_vizier_v2.py index 8aba0e4..fd3aaf7 100644 --- a/server/forms/upload_vizier_v2.py +++ b/uploader/forms/upload_vizier_v2.py @@ -3,12 +3,12 @@ from pydantic import BaseModel, Field -import app.report as report -from app.endpoints import env_map -from app.gen.client import adminapi -from app.sources.vizier_v2 import VizierV2Source -from app.upload import upload_for_web -from server.forms.upload_base import UploadBaseForm +import uploader.app.report as report +from uploader.app.endpoints import env_map +from uploader.app.sources.vizier_v2 import VizierV2Source +from uploader.app.upload import upload_for_web +from uploader.clients.gen.client import adminapi +from uploader.forms.upload_base import UploadBaseForm class UploadVizierV2Form(UploadBaseForm): diff --git a/server/history.py b/uploader/history.py similarity index 100% rename from server/history.py rename to uploader/history.py diff --git a/server/task_registry.py b/uploader/task_registry.py similarity index 80% rename from server/task_registry.py rename to uploader/task_registry.py index a1a26e2..06daa1b 100644 --- a/server/task_registry.py +++ b/uploader/task_registry.py @@ -1,23 +1,23 @@ -from server.forms.authenticate import AuthenticateForm, handle_authenticate -from server.forms.crossmatch_default import CrossmatchDefaultForm, handle_crossmatch_default -from server.forms.crossmatch_layered import CrossmatchLayeredForm, handle_crossmatch_layered -from server.forms.crossmatch_two_radii import CrossmatchTwoRadiiForm, handle_crossmatch_two_radii -from server.forms.structured_designation import ( +from uploader.forms.authenticate import AuthenticateForm, handle_authenticate +from uploader.forms.crossmatch_default import CrossmatchDefaultForm, handle_crossmatch_default +from uploader.forms.crossmatch_layered import CrossmatchLayeredForm, handle_crossmatch_layered +from uploader.forms.crossmatch_two_radii import CrossmatchTwoRadiiForm, handle_crossmatch_two_radii +from uploader.forms.structured_designation import ( StructuredDesignationForm, handle_structured_designation, ) -from server.forms.structured_icrs import StructuredIcrsForm, handle_structured_icrs -from server.forms.structured_nature import StructuredNatureForm, handle_structured_nature -from server.forms.structured_photometry_hyperleda import ( +from uploader.forms.structured_icrs import StructuredIcrsForm, handle_structured_icrs +from uploader.forms.structured_nature import StructuredNatureForm, handle_structured_nature +from uploader.forms.structured_photometry_hyperleda import ( StructuredPhotometryHyperledaForm, handle_structured_photometry_hyperleda, ) -from server.forms.structured_redshift import StructuredRedshiftForm, handle_structured_redshift -from server.forms.upload_csv import UploadCsvForm, handle_upload_csv -from server.forms.upload_fits import UploadFitsForm, handle_upload_fits -from server.forms.upload_vizier import UploadVizierForm, handle_upload_vizier -from server.forms.upload_vizier_v2 import UploadVizierV2Form, handle_upload_vizier_v2 -from server.tasks import TaskDefinition, register_task +from uploader.forms.structured_redshift import StructuredRedshiftForm, handle_structured_redshift +from uploader.forms.upload_csv import UploadCsvForm, handle_upload_csv +from uploader.forms.upload_fits import UploadFitsForm, handle_upload_fits +from uploader.forms.upload_vizier import UploadVizierForm, handle_upload_vizier +from uploader.forms.upload_vizier_v2 import UploadVizierV2Form, handle_upload_vizier_v2 +from uploader.tasks import TaskDefinition, register_task def register_all_tasks() -> None: diff --git a/server/tasks.py b/uploader/tasks.py similarity index 97% rename from server/tasks.py rename to uploader/tasks.py index cc4258d..4f919b5 100644 --- a/server/tasks.py +++ b/uploader/tasks.py @@ -8,9 +8,9 @@ from pydantic import BaseModel -import app.report as report -from app.log import logger -from server import history +import uploader.app.report as report +from uploader import history +from uploader.app.log import logger @dataclass diff --git a/uv.lock b/uv.lock index c0fd920..edde92d 100644 --- a/uv.lock +++ b/uv.lock @@ -88,11 +88,11 @@ dependencies = [ [[package]] name = "attrs" -version = "25.4.0" +version = "26.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, + { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, ] [[package]] @@ -401,11 +401,11 @@ wheels = [ [[package]] name = "jaraco-context" -version = "6.1.1" +version = "6.1.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/27/7b/c3081ff1af947915503121c649f26a778e1a2101fd525f74aef997d75b7e/jaraco_context-6.1.1.tar.gz", hash = "sha256:bc046b2dc94f1e5532bd02402684414575cc11f565d929b6563125deb0a6e581", size = 15832, upload-time = "2026-03-07T15:46:04.63Z" } +sdist = { url = "https://files.pythonhosted.org/packages/af/50/4763cd07e722bb6285316d390a164bc7e479db9d90daa769f22578f698b4/jaraco_context-6.1.2.tar.gz", hash = "sha256:f1a6c9d391e661cc5b8d39861ff077a7dc24dc23833ccee564b234b81c82dfe3", size = 16801, upload-time = "2026-03-20T22:13:33.922Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/49/c152890d49102b280ecf86ba5f80a8c111c3a155dafa3bd24aeb64fde9e1/jaraco_context-6.1.1-py3-none-any.whl", hash = "sha256:0df6a0287258f3e364072c3e40d5411b20cafa30cb28c4839d24319cecf9f808", size = 7005, upload-time = "2026-03-07T15:46:03.515Z" }, + { url = "https://files.pythonhosted.org/packages/f2/58/bc8954bda5fcda97bd7c19be11b85f91973d67a706ed4a3aec33e7de22db/jaraco_context-6.1.2-py3-none-any.whl", hash = "sha256:bf8150b79a2d5d91ae48629d8b427a8f7ba0e1097dd6202a9059f29a36379535", size = 7871, upload-time = "2026-03-20T22:13:32.808Z" }, ] [[package]] @@ -985,27 +985,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.15.6" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/51/df/f8629c19c5318601d3121e230f74cbee7a3732339c52b21daa2b82ef9c7d/ruff-0.15.6.tar.gz", hash = "sha256:8394c7bb153a4e3811a4ecdacd4a8e6a4fa8097028119160dffecdcdf9b56ae4", size = 4597916, upload-time = "2026-03-12T23:05:47.51Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9e/2f/4e03a7e5ce99b517e98d3b4951f411de2b0fa8348d39cf446671adcce9a2/ruff-0.15.6-py3-none-linux_armv6l.whl", hash = "sha256:7c98c3b16407b2cf3d0f2b80c80187384bc92c6774d85fefa913ecd941256fff", size = 10508953, upload-time = "2026-03-12T23:05:17.246Z" }, - { url = "https://files.pythonhosted.org/packages/70/60/55bcdc3e9f80bcf39edf0cd272da6fa511a3d94d5a0dd9e0adf76ceebdb4/ruff-0.15.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ee7dcfaad8b282a284df4aa6ddc2741b3f4a18b0555d626805555a820ea181c3", size = 10942257, upload-time = "2026-03-12T23:05:23.076Z" }, - { url = "https://files.pythonhosted.org/packages/e7/f9/005c29bd1726c0f492bfa215e95154cf480574140cb5f867c797c18c790b/ruff-0.15.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3bd9967851a25f038fc8b9ae88a7fbd1b609f30349231dffaa37b6804923c4bb", size = 10322683, upload-time = "2026-03-12T23:05:33.738Z" }, - { url = "https://files.pythonhosted.org/packages/5f/74/2f861f5fd7cbb2146bddb5501450300ce41562da36d21868c69b7a828169/ruff-0.15.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13f4594b04e42cd24a41da653886b04d2ff87adbf57497ed4f728b0e8a4866f8", size = 10660986, upload-time = "2026-03-12T23:05:53.245Z" }, - { url = "https://files.pythonhosted.org/packages/c1/a1/309f2364a424eccb763cdafc49df843c282609f47fe53aa83f38272389e0/ruff-0.15.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e2ed8aea2f3fe57886d3f00ea5b8aae5bf68d5e195f487f037a955ff9fbaac9e", size = 10332177, upload-time = "2026-03-12T23:05:56.145Z" }, - { url = "https://files.pythonhosted.org/packages/30/41/7ebf1d32658b4bab20f8ac80972fb19cd4e2c6b78552be263a680edc55ac/ruff-0.15.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70789d3e7830b848b548aae96766431c0dc01a6c78c13381f423bf7076c66d15", size = 11170783, upload-time = "2026-03-12T23:06:01.742Z" }, - { url = "https://files.pythonhosted.org/packages/76/be/6d488f6adca047df82cd62c304638bcb00821c36bd4881cfca221561fdfc/ruff-0.15.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:542aaf1de3154cea088ced5a819ce872611256ffe2498e750bbae5247a8114e9", size = 12044201, upload-time = "2026-03-12T23:05:28.697Z" }, - { url = "https://files.pythonhosted.org/packages/71/68/e6f125df4af7e6d0b498f8d373274794bc5156b324e8ab4bf5c1b4fc0ec7/ruff-0.15.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c22e6f02c16cfac3888aa636e9eba857254d15bbacc9906c9689fdecb1953ab", size = 11421561, upload-time = "2026-03-12T23:05:31.236Z" }, - { url = "https://files.pythonhosted.org/packages/f1/9f/f85ef5fd01a52e0b472b26dc1b4bd228b8f6f0435975442ffa4741278703/ruff-0.15.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98893c4c0aadc8e448cfa315bd0cc343a5323d740fe5f28ef8a3f9e21b381f7e", size = 11310928, upload-time = "2026-03-12T23:05:45.288Z" }, - { url = "https://files.pythonhosted.org/packages/8c/26/b75f8c421f5654304b89471ed384ae8c7f42b4dff58fa6ce1626d7f2b59a/ruff-0.15.6-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:70d263770d234912374493e8cc1e7385c5d49376e41dfa51c5c3453169dc581c", size = 11235186, upload-time = "2026-03-12T23:05:50.677Z" }, - { url = "https://files.pythonhosted.org/packages/fc/d4/d5a6d065962ff7a68a86c9b4f5500f7d101a0792078de636526c0edd40da/ruff-0.15.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:55a1ad63c5a6e54b1f21b7514dfadc0c7fb40093fa22e95143cf3f64ebdcd512", size = 10635231, upload-time = "2026-03-12T23:05:37.044Z" }, - { url = "https://files.pythonhosted.org/packages/d6/56/7c3acf3d50910375349016cf33de24be021532042afbed87942858992491/ruff-0.15.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8dc473ba093c5ec238bb1e7429ee676dca24643c471e11fbaa8a857925b061c0", size = 10340357, upload-time = "2026-03-12T23:06:04.748Z" }, - { url = "https://files.pythonhosted.org/packages/06/54/6faa39e9c1033ff6a3b6e76b5df536931cd30caf64988e112bbf91ef5ce5/ruff-0.15.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:85b042377c2a5561131767974617006f99f7e13c63c111b998f29fc1e58a4cfb", size = 10860583, upload-time = "2026-03-12T23:05:58.978Z" }, - { url = "https://files.pythonhosted.org/packages/cb/1e/509a201b843b4dfb0b32acdedf68d951d3377988cae43949ba4c4133a96a/ruff-0.15.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:cef49e30bc5a86a6a92098a7fbf6e467a234d90b63305d6f3ec01225a9d092e0", size = 11410976, upload-time = "2026-03-12T23:05:39.955Z" }, - { url = "https://files.pythonhosted.org/packages/6c/25/3fc9114abf979a41673ce877c08016f8e660ad6cf508c3957f537d2e9fa9/ruff-0.15.6-py3-none-win32.whl", hash = "sha256:bbf67d39832404812a2d23020dda68fee7f18ce15654e96fb1d3ad21a5fe436c", size = 10616872, upload-time = "2026-03-12T23:05:42.451Z" }, - { url = "https://files.pythonhosted.org/packages/89/7a/09ece68445ceac348df06e08bf75db72d0e8427765b96c9c0ffabc1be1d9/ruff-0.15.6-py3-none-win_amd64.whl", hash = "sha256:aee25bc84c2f1007ecb5037dff75cef00414fdf17c23f07dc13e577883dca406", size = 11787271, upload-time = "2026-03-12T23:05:20.168Z" }, - { url = "https://files.pythonhosted.org/packages/7f/d0/578c47dd68152ddddddf31cd7fc67dc30b7cdf639a86275fda821b0d9d98/ruff-0.15.6-py3-none-win_arm64.whl", hash = "sha256:c34de3dd0b0ba203be50ae70f5910b17188556630e2178fd7d79fc030eb0d837", size = 11060497, upload-time = "2026-03-12T23:05:25.968Z" }, +version = "0.15.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/22/9e4f66ee588588dc6c9af6a994e12d26e19efbe874d1a909d09a6dac7a59/ruff-0.15.7.tar.gz", hash = "sha256:04f1ae61fc20fe0b148617c324d9d009b5f63412c0b16474f3d5f1a1a665f7ac", size = 4601277, upload-time = "2026-03-19T16:26:22.605Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/2f/0b08ced94412af091807b6119ca03755d651d3d93a242682bf020189db94/ruff-0.15.7-py3-none-linux_armv6l.whl", hash = "sha256:a81cc5b6910fb7dfc7c32d20652e50fa05963f6e13ead3c5915c41ac5d16668e", size = 10489037, upload-time = "2026-03-19T16:26:32.47Z" }, + { url = "https://files.pythonhosted.org/packages/91/4a/82e0fa632e5c8b1eba5ee86ecd929e8ff327bbdbfb3c6ac5d81631bef605/ruff-0.15.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:722d165bd52403f3bdabc0ce9e41fc47070ac56d7a91b4e0d097b516a53a3477", size = 10955433, upload-time = "2026-03-19T16:27:00.205Z" }, + { url = "https://files.pythonhosted.org/packages/ab/10/12586735d0ff42526ad78c049bf51d7428618c8b5c467e72508c694119df/ruff-0.15.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:7fbc2448094262552146cbe1b9643a92f66559d3761f1ad0656d4991491af49e", size = 10269302, upload-time = "2026-03-19T16:26:26.183Z" }, + { url = "https://files.pythonhosted.org/packages/eb/5d/32b5c44ccf149a26623671df49cbfbd0a0ae511ff3df9d9d2426966a8d57/ruff-0.15.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b39329b60eba44156d138275323cc726bbfbddcec3063da57caa8a8b1d50adf", size = 10607625, upload-time = "2026-03-19T16:27:03.263Z" }, + { url = "https://files.pythonhosted.org/packages/5d/f1/f0001cabe86173aaacb6eb9bb734aa0605f9a6aa6fa7d43cb49cbc4af9c9/ruff-0.15.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:87768c151808505f2bfc93ae44e5f9e7c8518943e5074f76ac21558ef5627c85", size = 10324743, upload-time = "2026-03-19T16:27:09.791Z" }, + { url = "https://files.pythonhosted.org/packages/7a/87/b8a8f3d56b8d848008559e7c9d8bf367934d5367f6d932ba779456e2f73b/ruff-0.15.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb0511670002c6c529ec66c0e30641c976c8963de26a113f3a30456b702468b0", size = 11138536, upload-time = "2026-03-19T16:27:06.101Z" }, + { url = "https://files.pythonhosted.org/packages/e4/f2/4fd0d05aab0c5934b2e1464784f85ba2eab9d54bffc53fb5430d1ed8b829/ruff-0.15.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0d19644f801849229db8345180a71bee5407b429dd217f853ec515e968a6912", size = 11994292, upload-time = "2026-03-19T16:26:48.718Z" }, + { url = "https://files.pythonhosted.org/packages/64/22/fc4483871e767e5e95d1622ad83dad5ebb830f762ed0420fde7dfa9d9b08/ruff-0.15.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4806d8e09ef5e84eb19ba833d0442f7e300b23fe3f0981cae159a248a10f0036", size = 11398981, upload-time = "2026-03-19T16:26:54.513Z" }, + { url = "https://files.pythonhosted.org/packages/b0/99/66f0343176d5eab02c3f7fcd2de7a8e0dd7a41f0d982bee56cd1c24db62b/ruff-0.15.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dce0896488562f09a27b9c91b1f58a097457143931f3c4d519690dea54e624c5", size = 11242422, upload-time = "2026-03-19T16:26:29.277Z" }, + { url = "https://files.pythonhosted.org/packages/5d/3a/a7060f145bfdcce4c987ea27788b30c60e2c81d6e9a65157ca8afe646328/ruff-0.15.7-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:1852ce241d2bc89e5dc823e03cff4ce73d816b5c6cdadd27dbfe7b03217d2a12", size = 11232158, upload-time = "2026-03-19T16:26:42.321Z" }, + { url = "https://files.pythonhosted.org/packages/a7/53/90fbb9e08b29c048c403558d3cdd0adf2668b02ce9d50602452e187cd4af/ruff-0.15.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5f3e4b221fb4bd293f79912fc5e93a9063ebd6d0dcbd528f91b89172a9b8436c", size = 10577861, upload-time = "2026-03-19T16:26:57.459Z" }, + { url = "https://files.pythonhosted.org/packages/2f/aa/5f486226538fe4d0f0439e2da1716e1acf895e2a232b26f2459c55f8ddad/ruff-0.15.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b15e48602c9c1d9bdc504b472e90b90c97dc7d46c7028011ae67f3861ceba7b4", size = 10327310, upload-time = "2026-03-19T16:26:35.909Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/271afdffb81fe7bfc8c43ba079e9d96238f674380099457a74ccb3863857/ruff-0.15.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1b4705e0e85cedc74b0a23cf6a179dbb3df184cb227761979cc76c0440b5ab0d", size = 10840752, upload-time = "2026-03-19T16:26:45.723Z" }, + { url = "https://files.pythonhosted.org/packages/bf/29/a4ae78394f76c7759953c47884eb44de271b03a66634148d9f7d11e721bd/ruff-0.15.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:112c1fa316a558bb34319282c1200a8bf0495f1b735aeb78bfcb2991e6087580", size = 11336961, upload-time = "2026-03-19T16:26:39.076Z" }, + { url = "https://files.pythonhosted.org/packages/26/6b/8786ba5736562220d588a2f6653e6c17e90c59ced34a2d7b512ef8956103/ruff-0.15.7-py3-none-win32.whl", hash = "sha256:6d39e2d3505b082323352f733599f28169d12e891f7dd407f2d4f54b4c2886de", size = 10582538, upload-time = "2026-03-19T16:26:15.992Z" }, + { url = "https://files.pythonhosted.org/packages/2b/e9/346d4d3fffc6871125e877dae8d9a1966b254fbd92a50f8561078b88b099/ruff-0.15.7-py3-none-win_amd64.whl", hash = "sha256:4d53d712ddebcd7dace1bc395367aec12c057aacfe9adbb6d832302575f4d3a1", size = 11755839, upload-time = "2026-03-19T16:26:19.897Z" }, + { url = "https://files.pythonhosted.org/packages/8f/e8/726643a3ea68c727da31570bde48c7a10f1aa60eddd628d94078fec586ff/ruff-0.15.7-py3-none-win_arm64.whl", hash = "sha256:18e8d73f1c3fdf27931497972250340f92e8c861722161a9caeb89a58ead6ed2", size = 11023304, upload-time = "2026-03-19T16:26:51.669Z" }, ] [[package]] @@ -1117,10 +1117,11 @@ wheels = [ [[package]] name = "uploader" version = "0.1.0" -source = { virtual = "." } +source = { editable = "." } dependencies = [ { name = "astropy" }, { name = "astroquery" }, + { name = "click" }, { name = "fastapi" }, { name = "numpy" }, { name = "openapi-python-client" }, @@ -1144,6 +1145,7 @@ dev = [ requires-dist = [ { name = "astropy", specifier = ">=7.1.0" }, { name = "astroquery", git = "https://github.com/astropy/astroquery.git?branch=main" }, + { name = "click", specifier = "~=8.3.1" }, { name = "fastapi", specifier = ">=0.115.0" }, { name = "numpy", specifier = ">=2.3.4" }, { name = "openapi-python-client", specifier = ">=0.27.1" },