Skip to content

Releases: lsst-sqre/safir

6.4.0

16 Sep 20:35
@rra rra
6.4.0
f0330dc
Compare
Choose a tag to compare

New features

  • Add support functions for using Alembic to manage database schema migrations and to verify that the current database schema matches the expectations of the running application. The support in Safir is designed to use asyncpg for all database operations, which avoids having to add a separate dependency on a sync database client.
  • Add Alembic schema management support to the UWS library. This support is likely temporary and will probably be replaced in the future with a standalone UWS database service.

What's Changed

  • DM-46034: Remove now-unnecessary type: ignore markers by @rra in #295
  • DM-46034: Add new pytest-asyncio configuration by @rra in #296
  • DM-46034: Reorganize database documentation by @rra in #294
  • DM-46034: Reorganize UWS database schema by @rra in #297
  • DM-46034: Fix nox init and venv-init sessions by @rra in #298
  • DM-46034: Remove remaining declarative_base references by @rra in #300
  • DM-46034: Add support functions for Alembic by @rra in #299
  • DM-46034: Prepare 6.4.0 release by @rra in #301

Full Changelog: 6.3.0...6.4.0

6.3.0

20 Aug 21:58
@rra rra
6.3.0
1f77fd9
Compare
Choose a tag to compare

New features

  • safir.logging is now available as a separate PyPI package, safir-logging, so that it can be installed in environments where the full Safir dependency may be too heavy-weight or conflict with other packages. Packages that do depend on safir can and should ignore this change and continue to assume depending on safir will be sufficient to provide safir.logging.
  • Allow the database URL passed to DatabaseSessionDependency.initialize to be a Pydantic Url. This simplifies logic for applications that use EnvAsyncPostgresDsn or other Pydantic URL types for their configuration.
  • Allow the hook URL argument to safir.testing.slack.mock_slack_webhook to be a Pydantic SecretStr.

Bug fixes

  • safir.logging previously exported a logger_name variable holding the logger name configured via safir.logging.configure_logging. This variable was never documented and was not intended for use outside of the library. It is no longer exported, has been renamed, and is now private to the library.
  • Fix construction of an Availability object reporting problems with the UWS database layer to use the correct field names and data type for the model.

What's Changed

  • DM-45575: Restructure code to move it out of __init__.py files by @rra in #283
  • DM-45779: Allow a Url for database session initialization by @rra in #284
  • DM-45779: Allow mock_slack_webhook to take SecretStr by @rra in #285
  • DM-45794: Update to the current shared Ruff configuration by @rra in #286
  • DM-45818: Fix UWS Availability during errors by @rra in #287
  • DM-45824: Update to the latest Ruff by @rra in #289
  • DM-45824: Split safir.logging into a separate PyPI package by @rra in #288
  • DM-45824: Cap dependency on safir-logging by @rra in #290
  • DM-45824: Document logging in Safir UWS workers by @rra in #292
  • DM-45824: Prepare 6.3.0 release by @rra in #291
  • DM-45824: Fix release date for 6.3.0 by @rra in #293

Full Changelog: 6.2.0...6.3.0

6.2.0

02 Aug 18:53
@rra rra
6.2.0
1265eee
Compare
Choose a tag to compare

New features

  • Add new safir.uws and safir.arq.uws modules that provide the framework of an IVOA Universal Worker Service implementation.
  • Add new safir.testing.uws module that provides a mock UWS job runner for testing UWS applications.
  • safir.arq is now available as a separate PyPI package, safir-arq, so that it can be installed in environments where the full Safir dependency may be too heavy-weight or conflict with other packages. The safir[arq] dependency will continue to work as before (by installing safir-arq behind the scenes).
  • Add new abort_job method to instances of safir.arq.ArqQueue, which tells arq to abort a job that has been queued or in progress. To successfully abort a job that has already started, the arq worker must enable support for aborting jobs.
  • Add new utility function safir.arq.build_arq_redis_settings, which constructs the RedisSettings object used to create an arq Redis queue from a Pydantic Redis DSN.
  • Add new safir.arq.WorkerSettings class that models the acceptable parameters for an arq WorkerSettings object or class that Safir applications have needed.
  • Add new safir.pydantic.SecondsDatetime and safir.pydantic.HumanDatetime types for use in Pydantic models. These behave the same as datetime.timedelta fields but use custom validation. Both support a stringified number of seconds as input, and the latter also supports the interval strings parsed by safir.datetime.parse_timedelta.
  • Add new types safir.pydantic.EnvAsyncPostgresDsn and safir.pydantic.EnvRedisDsn, which validate PostgreSQL and Redis DSNs but rewrite them based on the environment variables set by tox-docker. Programs using these types for their configuration will therefore automatically honor tox-docker environment variables when running the test suite. EnvAsyncPostgresDsn also enforces that the scheme of the DSN is compatible with asyncpg and the Safir database support.
  • Add the decorator safir.database.retry_async_transaction, which retries a function or method a configurable number of times if it raises a SQLAlchemy exception from the underlying database API. This is primarily intended to retry database operations aborted due to transaction isolation.
  • safir.database.create_database_engine now accepts the database URL as a Pydantic Url as well as a str.
  • Allow the Slack webhook URL argument to SlackWebhookClient and SlackRouteErrorHandler to be given as a Pydantic SecretStr instead of a str. This simplifies code in applications that get that value from a secret.

Other changes

  • Safir is now built with nox instead of tox.

What's Changed

  • DM-45137: Switch to a shared Ruff configuration by @rra in #263
  • DM-45138: Add support for aborting arq jobs by @rra in #266
  • DM-45281: Add new timedelta data types for Pydantic models by @rra in #269
  • DM-45281: Add Pydantic types for Postgres and Redis DSNs by @rra in #270
  • DM-45281: Break apart safir.database for ease of maintenance by @rra in #271
  • DM-45281: Add decorator to retry async transactions by @rra in #272
  • DM-45281: Allow create_database_engine to take a Url by @rra in #273
  • DM-45281: Accept SecretStr as the Slack webhook URL by @rra in #274
  • Update cryptography requirement from <43 to <44 by @dependabot in #276
  • DM-45281: Add function to build arq RedisSettings by @rra in #275
  • DM-45281: Switch to testcontainers from tox-docker by @rra in #277
  • DM-45281: Convert to nox for the build system by @rra in #279
  • DM-45281: Separate safir-arq from safir by @rra in #280
  • DM-45281: Add UWS support library by @rra in #281
  • DM-45281: Collect change log for 6.2.0 release by @rra in #282

Full Changelog: 6.1.0...6.2.0

6.1.0

12 Jul 16:44
6.1.0
631897e
Compare
Choose a tag to compare

New features

  • Add pull_requests to GitHubCheckSuiteModel to capture info about any pull requests associated with a GitHub check suite event.

What's Changed

  • DM-44758: Remove outdated reference in 6.0.0 change log by @rra in #260
  • DM-45137: Stop importing from _pytest by @rra in #264
  • DM-45137: Update GitHub Actions settings from the template by @rra in #261
  • DM-45137: Update dependencies, switch to uv by @rra in #262
  • Add pull_requests to GitHubCheckSuiteModel by @fajpunk in #267
  • Prepare 6.1.0 release by @fajpunk in #268

New Contributors

Full Changelog: 6.0.0...6.1.0

6.0.0

10 Jun 21:04
@rra rra
6.0.0
e462eea
Compare
Choose a tag to compare

Backwards-incompatible changes

  • Drop safir.database.create_sync_session. This was only used by services that used Dramatiq for task management, since Dramatiq is sync-only. Services based on Safir should switch to arq and use only async database connections.
  • Drop DatabaseSessionDependency.override_engine. This was used for Gafaelfawr to share a database engine across all tests for speed, but this technique breaks with current versions of pytest-asyncio and is no longer used or safe to use.

New features

  • Allow the database password to be passed to create_database_engine and DatabaseSessionDependency.initialize as a Pydantic SecretStr.
  • Add new function safir.datetime.parse_timedelta, which parses a human-friendly syntax for specifying time durations into a Python datetime.timedelta.
  • Add support for gs URLs to safir.gcs.SignedURLService.
  • Support pickling of SlackException so that subclasses of it can be thrown by arq workers and unpickled correctly when retrieving results.

Bug fixes

  • Correctly honor the default_queue_name argument to RedisArqQueue.initialize.

What's Changed

  • Update and adjust for dependencies by @rra in #244
  • Fix exception logging test by @rra in #245
  • DM-44444: Allow database passwords to be SecretStrs by @rra in #246
  • DM-44444: Add parse_timedelta function to parse durations by @rra in #247
  • DM-44444: Update to latest tox-docker by @rra in #248
  • DM-44444: Remove version cap on structlog by @rra in #249
  • DM-44444: Use Python 3.12 for GitHub actions by @rra in #250
  • DM-44606: Allow SecretStr in DatabaseSessionDependency by @rra in #251
  • DM-44606: Fix ArqQueue.enqueue parameter documentation by @rra in #253
  • DM-44606: Fix default_queue_name in RedisArqQueue by @rra in #254
  • DM-44606: Support gs URLs in SignedURLService by @rra in #255
  • DM-44606: Drop DatabaseSessionDependency.override_engine by @rra in #252
  • DM-44720: Support pickling of SlackException by @rra in #256
  • Update kubernetes-asyncio requirement from <30 to <31 by @dependabot in #257
  • DM-44758: Drop safir.database.create_sync_session by @rra in #258
  • DM-44758: Prepare 6.0.0 release by @rra in #259

Full Changelog: 5.2.2...6.0.0

5.2.2

15 Mar 22:57
@rra rra
5.2.2
f848a0c
Compare
Choose a tag to compare

Bug fixes

  • Ensure that per-request database sessions provided by db_session_dependency are cleaned up even if the request aborts with an uncaught exception.

What's Changed

  • Update dependencies, fix deprecations by @rra in #240
  • Update Ruff configuration by @rra in #241
  • DM-43288: Ensure per-request database sessions are closed by @rra in #242
  • DM-43288: Prepare release 5.2.2 by @rra in #243

Full Changelog: 5.2.1...5.2.2

5.2.1

19 Feb 21:15
@rra rra
5.2.1
bedf4f7
Compare
Choose a tag to compare

Bug fixes

  • Fix the return type of safir.datetime.parse_isodatetime to not include None since the function never returns None.

What's Changed

  • Update kubernetes-asyncio requirement from <29 to <30 by @dependabot in #233
  • Update cryptography requirement from <42 to <43 by @dependabot in #234
  • Bump pre-commit/action from 3.0.0 to 3.0.1 by @dependabot in #236
  • DM-42714: Use Annotated for dependency arguments by @rra in #235
  • Fix minor documentation build issues by @rra in #237
  • DM-42937: Fix return type of parse_isodatetime by @rra in #238
  • DM-42937: Prepare 5.2.1 release by @rra in #239

Full Changelog: 5.2.0...5.2.1

5.2.0

19 Jan 23:34
@rra rra
5.2.0
36689b7
Compare
Choose a tag to compare

New features

  • Add a FastAPI dependency for retrieving a Gafaelfawr delegated token from the request headers: safir.dependencies.gafaelfawr.auth_delegated_token_dependency.

Bug fixes

  • Rewrite CaseInsensitiveQueryMiddleware and XForwardedMiddleware as pure ASGI middleware rather than using the Starlette BaseHTTPMiddleware class. The latter seems to be behind some poor error reporting of application exceptions, has caused problems in the past due to its complexity, and is not used internally by Starlette middleware.

What's Changed

  • Bump actions/setup-python from 4 to 5 by @dependabot in #227
  • Exclude buggy version of structlog by @rra in #228
  • Update structlog requirement from !=23.3.0,<24,>=21.2.0 to >=21.2.0,!=23.3.0,<25 by @dependabot in #229
  • DM-42527: Rewrite middleware as pure ASGI middleware by @rra in #230
  • DM-42190: Add gafaelfawr delegated token FastAPI dependency by @dhirving in #231
  • DM-42527: Prepare release 5.2.0 by @rra in #232

New Contributors

Full Changelog: 5.1.0...5.2.0

5.1.0

07 Dec 16:19
@rra rra
5.1.0
d9574ed
Compare
Choose a tag to compare

New features

  • Add support for label selectors in the list_node method of the Kubernetes mock.

What's Changed

  • DM-42029: Add support for label selectors in mock list_node by @rra in #225
  • DM-42029: Prepare release 5.1.0 by @rra in #226

Full Changelog: 5.0.0...5.1.0

5.0.0

05 Dec 17:59
@rra rra
5.0.0
d35831d
Compare
Choose a tag to compare

Backwards-incompatible changes

  • Safir now depends on Pydantic v2. Python code that uses any part of Safir related to Pydantic will also need to update to Pydantic v2, since the API is significantly different. See the Pydantic migration guide for more information.
  • safir.pydantic.validate_exactly_one_of is now a Pydantic model validator. It must be called with mode="after", since it operates in the model rather than on a raw dictionary.
  • Remove the GitHubAppClientFactory.create_app_client method, which does not work with the Gidgethub API. Instead, the documentation shows how to create a JWT with the GitHubAppClientFactory and pass it with requests.
  • safir.github.GitHubAppClientFactory now expects the application ID and installation ID (for create_installation_client) to be of type int, not str. This appears to match what GitHub's API returns, but not what Gidgethub expects. The ID is converted to a string when passing it to Gidgethub.

New features

  • Allow the safir.logging.LogLevel enum to be created from strings of any case, which will allow the logging level to be specified with any case for Safir applications that use Pydantic to validate the field.
  • Add validated but ignored optional propagation_policy arguments to every delete method of the Kubernetes mock for better compatibility with the actual Kubernetes API. Previously, this argument was only accepted by delete_namespaced_job.
  • All mock Kubernetes methods now accept and ignore a _request_timeout error for better compatibility with the Kubernetes API.
  • Add delete, list, and watch support for persistent volume claims to the Kubernetes mock.

Bug fixes

  • safir.database.datetime_to_db, safir.datetime.format_datetime_for_logging, and safir.datetime.isodatetime now accept any datetime object with a time zone whose offset from UTC is 0, rather than only the datetime.UTC time zone object.
  • safir.pydantic.normalize_datetime now explicitly rejects input other than seconds since epoch or datetime objects with a validation error rather than attempting to treat the input as a datetime object and potentially throwing more obscure errors.
  • The _request_timeout parameters to mock Kubernetes methods now accept a float instead of an int to more correctly match the types of kubernetes_asyncio. The mock still does not accept a tuple of timeouts.
  • Avoid reusing the same metadata object when creating a Pod from a Job. Previous versions modified the spec part of the Job when adding additional metadata to the child Pod.

Other changes

  • Safir is now tested with Python 3.12 as well as Python 3.11.

What's Changed

  • DM-398710: Remove GitHubAppClientFactory.create_app_client by @jonathansick in #207
  • DM-40744: Convert to Pydantic v2 by @rra in #204
  • Doc fix: spawn_uvicorn example by @fritzm in #209
  • Update kubernetes-asyncio requirement from <26 to <27 by @dependabot in #208
  • Update kubernetes-asyncio requirement from <27 to <28 by @dependabot in #210
  • Fix spawn_uvicorn documentation by @rra in #211
  • DM-23878: Allow log level enum with any case by @rra in #212
  • Update kubernetes-asyncio requirement from <28 to <29 by @dependabot in #213
  • DM-41630: Add propagation_policy to Kubernetes mock deletes by @rra in #214
  • DM-41630: Support _request_timeout in Kubernetes mock by @rra in #215
  • DM-41630: Fix type of Kubernetes mock _request_timeout by @rra in #218
  • DM-41630: Update development Redis dependencies by @rra in #216
  • DM-41630: Convert to FastAPI lifespan functions by @rra in #217
  • DM-41708: Fix Pod creation from Job in Kubernetes mock by @rra in #221
  • DM-41708: Add more mocks for Kubernetes PVCs by @rra in #220
  • DM-41820: Fix annotations on Pod created from Job by @rra in #222
  • DM-41998: Add support for Python 3.12 by @rra in #223
  • DM-41998: Prepare 5.0.0 release by @rra in #224

Full Changelog: 4.5.0...5.0.0