Skip to content

Commit

Permalink
Merge pull request #150 from lsst-sqre/tickets/DM-42937
Browse files Browse the repository at this point in the history
DM-42937: Use Safir datetime utility functions
  • Loading branch information
rra authored Feb 19, 2024
2 parents 79720e7 + 4cd63e6 commit f8ce0b8
Show file tree
Hide file tree
Showing 17 changed files with 292 additions and 216 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ repos:
- id: trailing-whitespace

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.2.1
rev: v0.2.2
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
Expand Down
6 changes: 4 additions & 2 deletions requirements/dev.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@

-c main.txt

# Testing and linting
asgi-lifespan
coverage[toml]
httpx
mypy
pre-commit
pytest
pytest-asyncio
pytest-cov
pytest-timeout
sqlalchemy[mypy]
uvicorn

# Documentation
scriv[toml]
294 changes: 195 additions & 99 deletions requirements/dev.txt

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions requirements/main.in
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ jinja2
psycopg2
pydantic
pydantic-settings
safir[db,gcs]
safir[db,gcs]>=5.2.1
sqlalchemy[asyncio]
structlog

# Uncomment this, change the branch, comment out safir above, and run make
# update-deps-no-hashes to test against an unreleased version of Safir.
#git+https://github.com/lsst-sqre/safir@main#egg=safir[db,gcs]
# safir[db,gcs] @ git+https://github.com/lsst-sqre/safir@main
89 changes: 49 additions & 40 deletions requirements/main.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# This file was autogenerated by uv v0.1.2 via the following command:
# This file was autogenerated by uv v0.1.5 via the following command:
# uv pip compile --upgrade --generate-hashes --output-file requirements/main.txt requirements/main.in
annotated-types==0.6.0 \
--hash=sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43 \
--hash=sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d
# via pydantic
anyio==4.2.0 \
--hash=sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee \
--hash=sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f
anyio==4.3.0 \
--hash=sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8 \
--hash=sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6
# via
# httpx
# starlette
Expand Down Expand Up @@ -41,9 +41,9 @@ astropy==6.0.0 \
--hash=sha256:eedd46d5c50b977ebb368f8df6cd34a720999cb4fdfd4d2d6b459262a8ac8ec2 \
--hash=sha256:fa10e80bd3ff8b053c56e402246d4171c6e9658da37341fe28d99212d809ebe4 \
--hash=sha256:fcf2da6f59d3c9636872c533ee358293c743800fff953da3d57deb0d2ee0481f
astropy-iers-data==0.2024.2.12.0.31.0 \
--hash=sha256:76f7149ac85adc8345ab9f8ab231aff29ce6fceab689f01059b42291aa75bf9b \
--hash=sha256:f137474f07361adbc9fd55a85bb48cbd6a073fc2a80be0830f069cdff84a0c68
astropy-iers-data==0.2024.2.19.0.28.47 \
--hash=sha256:29af64fc932fec656c1f75478d693aef4ba6364b8d32a5862d5d908fe8848248 \
--hash=sha256:8ccf83b8e35b300fb77eeb189ed728ec6d8150c40f8788a42e542fdcf960fe49
# via astropy
asyncpg==0.29.0 \
--hash=sha256:0009a300cae37b8c525e5b449233d59cd9868fd35431abc470a3e364d2b85cb9 \
Expand Down Expand Up @@ -251,30 +251,39 @@ click==8.1.7 \
# via
# safir
# uvicorn
cryptography==41.0.7 \
--hash=sha256:079b85658ea2f59c4f43b70f8119a52414cdb7be34da5d019a77bf96d473b960 \
--hash=sha256:09616eeaef406f99046553b8a40fbf8b1e70795a91885ba4c96a70793de5504a \
--hash=sha256:13f93ce9bea8016c253b34afc6bd6a75993e5c40672ed5405a9c832f0d4a00bc \
--hash=sha256:37a138589b12069efb424220bf78eac59ca68b95696fc622b6ccc1c0a197204a \
--hash=sha256:3c78451b78313fa81607fa1b3f1ae0a5ddd8014c38a02d9db0616133987b9cdf \
--hash=sha256:43f2552a2378b44869fe8827aa19e69512e3245a219104438692385b0ee119d1 \
--hash=sha256:48a0476626da912a44cc078f9893f292f0b3e4c739caf289268168d8f4702a39 \
--hash=sha256:49f0805fc0b2ac8d4882dd52f4a3b935b210935d500b6b805f321addc8177406 \
--hash=sha256:5429ec739a29df2e29e15d082f1d9ad683701f0ec7709ca479b3ff2708dae65a \
--hash=sha256:5a1b41bc97f1ad230a41657d9155113c7521953869ae57ac39ac7f1bb471469a \
--hash=sha256:68a2dec79deebc5d26d617bfdf6e8aab065a4f34934b22d3b5010df3ba36612c \
--hash=sha256:7a698cb1dac82c35fcf8fe3417a3aaba97de16a01ac914b89a0889d364d2f6be \
--hash=sha256:841df4caa01008bad253bce2a6f7b47f86dc9f08df4b433c404def869f590a15 \
--hash=sha256:90452ba79b8788fa380dfb587cca692976ef4e757b194b093d845e8d99f612f2 \
--hash=sha256:928258ba5d6f8ae644e764d0f996d61a8777559f72dfeb2eea7e2fe0ad6e782d \
--hash=sha256:af03b32695b24d85a75d40e1ba39ffe7db7ffcb099fe507b39fd41a565f1b157 \
--hash=sha256:b640981bf64a3e978a56167594a0e97db71c89a479da8e175d8bb5be5178c003 \
--hash=sha256:c5ca78485a255e03c32b513f8c2bc39fedb7f5c5f8535545bdc223a03b24f248 \
--hash=sha256:c7f3201ec47d5207841402594f1d7950879ef890c0c495052fa62f58283fde1a \
--hash=sha256:d5ec85080cce7b0513cfd233914eb8b7bbd0633f1d1703aa28d1dd5a72f678ec \
--hash=sha256:d6c391c021ab1f7a82da5d8d0b3cee2f4b2c455ec86c8aebbc84837a631ff309 \
--hash=sha256:e3114da6d7f95d2dee7d3f4eec16dacff819740bbab931aff8648cb13c5ff5e7 \
--hash=sha256:f983596065a18a2183e7f79ab3fd4c475205b839e02cbc0efbbf9666c4b3083d
cryptography==42.0.3 \
--hash=sha256:04859aa7f12c2b5f7e22d25198ddd537391f1695df7057c8700f71f26f47a129 \
--hash=sha256:069d2ce9be5526a44093a0991c450fe9906cdf069e0e7cd67d9dee49a62b9ebe \
--hash=sha256:0d3ec384058b642f7fb7e7bff9664030011ed1af8f852540c76a1317a9dd0d20 \
--hash=sha256:0fab2a5c479b360e5e0ea9f654bcebb535e3aa1e493a715b13244f4e07ea8eec \
--hash=sha256:0fea01527d4fb22ffe38cd98951c9044400f6eff4788cf52ae116e27d30a1ba3 \
--hash=sha256:1b797099d221df7cce5ff2a1d272761d1554ddf9a987d3e11f6459b38cd300fd \
--hash=sha256:1e935c2900fb53d31f491c0de04f41110351377be19d83d908c1fd502ae8daa5 \
--hash=sha256:20100c22b298c9eaebe4f0b9032ea97186ac2555f426c3e70670f2517989543b \
--hash=sha256:20180da1b508f4aefc101cebc14c57043a02b355d1a652b6e8e537967f1e1b46 \
--hash=sha256:25b09b73db78facdfd7dd0fa77a3f19e94896197c86e9f6dc16bce7b37a96504 \
--hash=sha256:2619487f37da18d6826e27854a7f9d4d013c51eafb066c80d09c63cf24505306 \
--hash=sha256:2eb6368d5327d6455f20327fb6159b97538820355ec00f8cc9464d617caecead \
--hash=sha256:35772a6cffd1f59b85cb670f12faba05513446f80352fe811689b4e439b5d89e \
--hash=sha256:39d5c93e95bcbc4c06313fc6a500cee414ee39b616b55320c1904760ad686938 \
--hash=sha256:3d96ea47ce6d0055d5b97e761d37b4e84195485cb5a38401be341fabf23bc32a \
--hash=sha256:4dcab7c25e48fc09a73c3e463d09ac902a932a0f8d0c568238b3696d06bf377b \
--hash=sha256:5fbf0f3f0fac7c089308bd771d2c6c7b7d53ae909dce1db52d8e921f6c19bb3a \
--hash=sha256:6c25e1e9c2ce682d01fc5e2dde6598f7313027343bd14f4049b82ad0402e52cd \
--hash=sha256:762f3771ae40e111d78d77cbe9c1035e886ac04a234d3ee0856bf4ecb3749d54 \
--hash=sha256:90147dad8c22d64b2ff7331f8d4cddfdc3ee93e4879796f837bdbb2a0b141e0c \
--hash=sha256:935cca25d35dda9e7bd46a24831dfd255307c55a07ff38fd1a92119cffc34857 \
--hash=sha256:93fbee08c48e63d5d1b39ab56fd3fdd02e6c2431c3da0f4edaf54954744c718f \
--hash=sha256:9541c69c62d7446539f2c1c06d7046aef822940d248fa4b8962ff0302862cc1f \
--hash=sha256:c23f03cfd7d9826cdcbad7850de67e18b4654179e01fe9bc623d37c2638eb4ef \
--hash=sha256:c3d1f5a1d403a8e640fa0887e9f7087331abb3f33b0f2207d2cc7f213e4a864c \
--hash=sha256:d1998e545081da0ab276bcb4b33cce85f775adb86a516e8f55b3dac87f469548 \
--hash=sha256:d5cf11bc7f0b71fb71af26af396c83dfd3f6eed56d4b6ef95d57867bf1e4ba65 \
--hash=sha256:db0480ffbfb1193ac4e1e88239f31314fe4c6cdcf9c0b8712b55414afbf80db4 \
--hash=sha256:de4ae486041878dc46e571a4c70ba337ed5233a1344c14a0790c4c4be4bbb8b4 \
--hash=sha256:de5086cd475d67113ccb6f9fae6d8fe3ac54a4f9238fd08bfdb07b03d791ff0a \
--hash=sha256:df34312149b495d9d03492ce97471234fd9037aa5ba217c2a6ea890e9166f151 \
--hash=sha256:ead69ba488f806fe1b1b4050febafdbf206b81fa476126f3e16110c818bac396
# via
# pyjwt
# safir
Expand Down Expand Up @@ -754,9 +763,9 @@ pydantic-core==2.16.2 \
--hash=sha256:fe56851c3f1d6f5384b3051c536cc81b3a93a73faf931f404fef95217cf1e10d \
--hash=sha256:ff7c97eb7a29aba230389a2661edf2e9e06ce616c7e35aa764879b6894a44b25
# via pydantic
pydantic-settings==2.2.0 \
--hash=sha256:5f7bcaf9ad4419559dc5ac155c0324a9aeb2547c60471ee7c7d026f467a6b515 \
--hash=sha256:648d0a76673e69c51278979cba2e83cf16a23d57519bfd7e553d1c3f37db5560
pydantic-settings==2.2.1 \
--hash=sha256:00b9f6a5e95553590434c0fa01ead0b216c3e10bc54ae02e37f359948643c5ed \
--hash=sha256:0235391d26db4d2190cb9b31051c4b46882d28a51533f97440867f012d4da091
pyerfa==2.0.1.1 \
--hash=sha256:08b5abb90b34e819c1fca69047a76c0d344cb0c8fe4f7c8773f032d8afd623b4 \
--hash=sha256:0e95cf3d11f76f473bf011980e9ea367ca7e68ca675d8b32499814fb6e387d4c \
Expand Down Expand Up @@ -852,9 +861,9 @@ rsa==4.9 \
--hash=sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7 \
--hash=sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21
# via google-auth
safir==5.2.0 \
--hash=sha256:93636256dbeea847d63de6d3b434c952f81d6729f6541da09bfc7823d3f61806 \
--hash=sha256:fe8f51d00449a60544f9eccdb8e603f085fdd4f641f5d5f13cef0f29393aad3f
safir==5.2.1 \
--hash=sha256:1b61cc72881ddfb66e1f84b6c34ca7e062f27b5669b9d1d07377ebd117ce3ebf \
--hash=sha256:e39e2260e87303de9aaac157b45743ec9f82d2e84065d10b21008fceaa8aa407
sniffio==1.3.0 \
--hash=sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101 \
--hash=sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384
Expand Down Expand Up @@ -934,9 +943,9 @@ uritemplate==4.1.1 \
--hash=sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0 \
--hash=sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e
# via gidgethub
urllib3==2.2.0 \
--hash=sha256:051d961ad0c62a94e50ecf1af379c3aba230c66c710493493560c0c223c49f20 \
--hash=sha256:ce3711610ddce217e6d113a2732fafad960a03fd0318c91faa79481e35c11224
urllib3==2.2.1 \
--hash=sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d \
--hash=sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19
# via requests
uvicorn==0.27.1 \
--hash=sha256:3d9a267296243532db80c83a959a3400502165ade2c1338dea4e67915fd4745a \
Expand Down
4 changes: 1 addition & 3 deletions src/vocutouts/actors.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@

import dramatiq
import structlog
from safir.datetime import parse_isodatetime

from . import broker
from .uws.jobs import uws_job_completed, uws_job_failed, uws_job_started
from .uws.utils import parse_isodatetime

__all__ = [
"cutout",
Expand Down Expand Up @@ -114,8 +114,6 @@ def job_started(job_id: str, message_id: str, start_time: str) -> None:
start = parse_isodatetime(start_time)
if not broker.worker_session:
raise RuntimeError("Worker database connection not initalized")
if not start:
raise RuntimeError(f"Invalid start timestamp {start_time}")
uws_job_started(job_id, message_id, start, broker.worker_session, logger)


Expand Down
9 changes: 5 additions & 4 deletions src/vocutouts/uws/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from fastapi import APIRouter, Depends, Form, Query, Request, Response
from fastapi.responses import PlainTextResponse, RedirectResponse
from safir.datetime import isodatetime, parse_isodatetime
from safir.dependencies.gafaelfawr import (
auth_delegated_token_dependency,
auth_dependency,
Expand All @@ -35,7 +36,6 @@
)
from .exceptions import DataMissingError, ParameterError, PermissionDeniedError
from .models import ExecutionPhase, JobParameter
from .utils import isodatetime, parse_isodatetime

__all__ = ["uws_router"]

Expand Down Expand Up @@ -238,9 +238,10 @@ async def post_job_destruction(
if param.parameter_id != "destruction":
msg = f"Unknown parameter {param.parameter_id}={param.value}"
raise ParameterError(msg)
destruction = parse_isodatetime(param.value)
if destruction is None:
raise ParameterError(f"Invalid date {param.value}")
try:
destruction = parse_isodatetime(param.value)
except Exception as e:
raise ParameterError(f"Invalid date {param.value}") from e
if not destruction:
raise ParameterError("No new destruction time given")

Expand Down
2 changes: 1 addition & 1 deletion src/vocutouts/uws/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

from fastapi import Request, Response
from fastapi.templating import Jinja2Templates
from safir.datetime import isodatetime

from .models import Availability, Job, JobDescription, JobError
from .results import ResultStore
from .utils import isodatetime

__all__ = ["UWSTemplates"]

Expand Down
8 changes: 4 additions & 4 deletions src/vocutouts/uws/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from __future__ import annotations

from collections.abc import Awaitable, Callable
from datetime import UTC, datetime, timedelta
from datetime import datetime, timedelta
from functools import wraps
from typing import Any, TypeVar, cast

Expand Down Expand Up @@ -288,7 +288,7 @@ async def list_jobs(
owner=j.owner,
phase=j.phase,
run_id=j.run_id,
creation_time=j.creation_time,
creation_time=datetime_from_db(j.creation_time),
)
for j in jobs.all()
]
Expand Down Expand Up @@ -405,7 +405,7 @@ def mark_completed(self, job_id: str, results: list[JobResult]) -> None:
with self._session.begin():
job = self._get_job(job_id)
job.phase = ExecutionPhase.COMPLETED
job.end_time = datetime_to_db(datetime.now(tz=UTC))
job.end_time = datetime_to_db(current_datetime())
for sequence, result in enumerate(results, start=1):
sql_result = SQLJobResult(
job_id=job.id,
Expand All @@ -423,7 +423,7 @@ def mark_errored(self, job_id: str, error: JobError) -> None:
with self._session.begin():
job = self._get_job(job_id)
job.phase = ExecutionPhase.ERROR
job.end_time = datetime_to_db(datetime.now(tz=UTC))
job.end_time = datetime_to_db(current_datetime())
job.error_type = error.error_type
job.error_code = error.error_code
job.error_message = error.message
Expand Down
29 changes: 0 additions & 29 deletions src/vocutouts/uws/utils.py

This file was deleted.

6 changes: 3 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from __future__ import annotations

from collections.abc import AsyncIterator, Iterator
from datetime import UTC, datetime, timedelta
from datetime import timedelta
from typing import Any

import dramatiq
Expand All @@ -15,6 +15,7 @@
from fastapi import FastAPI
from httpx import AsyncClient
from safir.database import create_database_engine, initialize_database
from safir.datetime import current_datetime, isodatetime
from safir.testing.gcs import MockStorageClient, patch_google_storage

from vocutouts import main
Expand All @@ -24,7 +25,6 @@
from vocutouts.policy import ImageCutoutPolicy
from vocutouts.uws.dependencies import uws_dependency
from vocutouts.uws.schema import Base
from vocutouts.uws.utils import isodatetime


@dramatiq.actor(queue_name="cutout", store_results=True)
Expand All @@ -35,7 +35,7 @@ def cutout_test(
access_token: str,
) -> list[dict[str, Any]]:
message = CurrentMessage.get_current_message()
now = isodatetime(datetime.now(tz=UTC))
now = isodatetime(current_datetime())
job_started.send(job_id, message.message_id, now)
assert len(dataset_ids) == 1
assert access_token == "sometoken"
Expand Down
7 changes: 3 additions & 4 deletions tests/support/uws.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import asyncio
import os
from datetime import UTC, datetime, timedelta
from datetime import datetime, timedelta
from typing import Any

import dramatiq
Expand All @@ -15,6 +15,7 @@
from dramatiq.results import Results
from dramatiq.results.backends import StubBackend
from safir.database import create_sync_session
from safir.datetime import current_datetime, isodatetime, parse_isodatetime
from sqlalchemy.future import select
from sqlalchemy.orm import scoped_session

Expand All @@ -28,7 +29,6 @@
from vocutouts.uws.policy import UWSPolicy
from vocutouts.uws.schema import Job as SQLJob
from vocutouts.uws.service import JobService
from vocutouts.uws.utils import isodatetime, parse_isodatetime

uws_broker = StubBroker()
"""Dramatiq broker for use in tests."""
Expand Down Expand Up @@ -71,7 +71,7 @@ def before_worker_boot(self, broker: Broker, worker: Worker) -> None:
@dramatiq.actor(broker=uws_broker, queue_name="job", store_results=True)
def trivial_job(job_id: str) -> list[dict[str, Any]]:
message = CurrentMessage.get_current_message()
now = datetime.now(tz=UTC)
now = current_datetime()
job_started.send(job_id, message.message_id, isodatetime(now))
return [
{
Expand All @@ -87,7 +87,6 @@ def job_started(job_id: str, message_id: str, start_time: str) -> None:
logger = structlog.get_logger("uws")
start = parse_isodatetime(start_time)
assert worker_session
assert start, f"Invalid start timestamp {start_time}"
uws_job_started(job_id, message_id, start, worker_session, logger)


Expand Down
2 changes: 1 addition & 1 deletion tests/uws/job_api_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
from dramatiq import Worker
from fastapi import FastAPI
from httpx import AsyncClient
from safir.datetime import isodatetime
from structlog.stdlib import BoundLogger

from tests.support.uws import uws_broker, wait_for_job
from vocutouts.uws.config import UWSConfig
from vocutouts.uws.dependencies import UWSFactory
from vocutouts.uws.models import JobParameter
from vocutouts.uws.utils import isodatetime

PENDING_JOB = """
<uws:job
Expand Down
Loading

0 comments on commit f8ce0b8

Please sign in to comment.