API reference#

safir Package#

Safir is the Rubin Observatory’s library for building FastAPI services for the Rubin Science Platform.

Variables#

__version__

The version string of Safir (PEP 440 / SemVer compatible).

version_info

The decomposed version, split across ".."

safir.arq Module#

An arq client with a mock for testing.

Classes#

ArqJobError(message, job_id)

A base class for errors related to arq jobs.

JobNotQueued(job_id)

The job was not successfully queued.

JobNotFound(job_id)

A job cannot be found.

JobResultUnavailable(job_id)

The job's result is unavailable.

ArqMode(value[, names, module, qualname, ...])

Mode configuration for the Arq queue.

JobMetadata(id, name, args, kwargs, ...)

Information about a queued job.

JobResult(id, name, args, kwargs, ...)

The full result of a job, as well as its metadata.

ArqQueue(*[, default_queue_name])

A common interface for working with an arq queue that can be implemented either with a real Redis backend, or an in-memory repository for testing.

RedisArqQueue(pool, *[, default_queue_name])

A distributed queue, based on arq and Redis.

MockArqQueue(*[, default_queue_name])

A mocked queue for testing API services.

Class Inheritance Diagram#

Inheritance diagram of safir.arq.ArqJobError, safir.arq.JobNotQueued, safir.arq.JobNotFound, safir.arq.JobResultUnavailable, safir.arq.ArqMode, safir.arq.JobMetadata, safir.arq.JobResult, safir.arq.ArqQueue, safir.arq.RedisArqQueue, safir.arq.MockArqQueue

safir.asyncio Module#

Utility functions for asyncio code.

Functions#

run_with_asyncio(f)

Run the decorated function with asyncio.run.

Classes#

AsyncMultiQueue()

An asyncio multiple reader, multiple writer queue.

AsyncMultiQueueError

Invalid sequence of calls when writing to AsyncMultiQueue.

Variables#

F

Type variable for return type of decorated by run_with_asyncio.

P

Parameter spec for functions decorated by run_with_asyncio.

T

Type variable of objects being stored in AsyncMultiQueue.

Class Inheritance Diagram#

Inheritance diagram of safir.asyncio.AsyncMultiQueue, safir.asyncio.AsyncMultiQueueError

safir.click Module#

Click command-line interface support.

Functions#

display_help(main, ctx[, topic, subtopic])

Show help for a Click command.

safir.database Module#

Utility functions for database management.

Functions#

create_async_session(engine[, logger, statement])

Create a new async database session.

create_database_engine(url, password, *[, ...])

Create a new async database engine.

create_sync_session(url, password[, logger, ...])

Create a new sync database session.

datetime_from_db(time)

Add the UTC time zone to a naive datetime from the database.

datetime_to_db(time)

Strip time zone for storing a datetime in the database.

initialize_database(engine, logger, *, schema)

Create and initialize a new database.

Classes#

DatabaseInitializationError

Database initialization failed.

Class Inheritance Diagram#

Inheritance diagram of safir.database.DatabaseInitializationError

safir.datetime Module#

Date and time manipulation utility functions.

Functions#

current_datetime(*[, microseconds])

Construct a ~datetime.datetime for the current time.

format_datetime_for_logging(timestamp)

Format a datetime for logging and human readabilty.

isodatetime(timestamp)

Format a timestamp in UTC in a standard ISO date format.

parse_isodatetime(time_string)

Parse a string in a standard ISO date format.

safir.dependencies.arq Module#

A FastAPI dependency that supplies a Redis connection for arq.

Classes#

ArqDependency()

A FastAPI dependency that maintains a Redis client for enqueuing tasks to the worker pool.

Variables#

arq_dependency

Singleton instance of ArqDependency that serves as a FastAPI dependency.

Class Inheritance Diagram#

Inheritance diagram of safir.dependencies.arq.ArqDependency

safir.dependencies.db_session Module#

Manage an async database session.

Classes#

DatabaseSessionDependency()

Manages an async per-request SQLAlchemy session.

Variables#

db_session_dependency

The dependency that will return the async session proxy.

Class Inheritance Diagram#

Inheritance diagram of safir.dependencies.db_session.DatabaseSessionDependency

safir.dependencies.gafaelfawr Module#

Gafaelfawr authentication dependencies.

Functions#

auth_dependency([x_auth_request_user])

Retrieve authentication information from HTTP headers.

auth_logger_dependency([user, logger])

Logger bound to the authenticated user.

safir.dependencies.http_client Module#

HTTP client dependency for FastAPI.

Classes#

HTTPClientDependency()

Provides an httpx.AsyncClient as a dependency.

Variables#

DEFAULT_HTTP_TIMEOUT

Default timeout (in seconds) for outbound HTTP requests.

http_client_dependency

The dependency that will return the HTTP client.

Class Inheritance Diagram#

Inheritance diagram of safir.dependencies.http_client.HTTPClientDependency

safir.dependencies.logger Module#

Logger dependency for FastAPI.

Provides a structlog logger as a FastAPI dependency. The logger will incorporate information from the request in its bound context.

Classes#

LoggerDependency()

Provides a structlog logger configured with request information.

Variables#

logger_dependency

The dependency that will return the logger for the current request.

Class Inheritance Diagram#

Inheritance diagram of safir.dependencies.logger.LoggerDependency

safir.fastapi Module#

Helper code for FastAPI (other than dependencies and middleware).

Functions#

client_request_error_handler(request, exc)

Exception handler for exceptions derived from ClientRequestError.

Classes#

ClientRequestError(message[, location, ...])

Represents an error in a client request.

Class Inheritance Diagram#

Inheritance diagram of safir.fastapi.ClientRequestError

safir.gcs Module#

Utilities for interacting with Google Cloud Storage.

Classes#

SignedURLService(service_account[, lifetime])

Generate signed URLs for Google Cloud Storage blobs.

Class Inheritance Diagram#

Inheritance diagram of safir.gcs.SignedURLService

safir.github Package#

GitHub API client factory and Pydantic models.

Classes#

GitHubAppClientFactory(*, id, key, name, ...)

Factory for creating GitHub App clients authenticated either as an app or as an installation of that app.

Class Inheritance Diagram#

Inheritance diagram of safir.github._client.GitHubAppClientFactory

safir.github.models Module#

Pydantic models for GitHub v3 REST API resources.

Classes#

GitHubRepoOwnerModel

A Pydantic model for the owner field found in repository objects.

GitHubUserModel

A Pydantic model for the user field found in GitHub API resources.

GitHubRepositoryModel

A Pydantic model for the repository field, often found in webhook payloads.

GitHubPullState(value[, names, module, ...])

The state of a GitHub pull request (PR).

GitHubPullRequestModel

A Pydantic model for a GitHub Pull Request.

GitHubBranchCommitModel

A Pydantic model for the commit field found in GitHubBranchModel.

GitHubBranchModel

A Pydantic model for a GitHub branch.

GitHubBlobModel

A Pydantic model for a blob, returned by the GitHub blob endpoint.

GitHubCheckSuiteStatus(value[, names, ...])

The status of a GitHub check suite.

GitHubCheckSuiteConclusion(value[, names, ...])

The conclusion state of a GitHub check suite.

GitHubCheckSuiteModel

A Pydantic model for the check_suite field in a check_suite webhook (~safir.github.webhooks.GitHubCheckSuiteEventModel).

GitHubCheckRunStatus(value[, names, module, ...])

The check run status.

GitHubCheckRunConclusion(value[, names, ...])

The check run conclusion state.

GitHubCheckRunAnnotationLevel(value[, ...])

The level of a check run output annotation.

GitHubCheckSuiteId

Brief information about a check suite in the GitHubCheckRunModel.

GitHubCheckRunOutput

Check run output report.

GitHubCheckRunPrInfoModel

A Pydantic model of the pull_requests[] items in a check run GitHub API model (GitHubCheckRunModel).

GitHubCheckRunModel

A Pydantic model for the "check_run" field in a check_run webhook payload (~safir.github.webhooks.GitHubCheckRunEventModel).

Class Inheritance Diagram#

Inheritance diagram of safir.github.models.GitHubRepoOwnerModel, safir.github.models.GitHubUserModel, safir.github.models.GitHubRepositoryModel, safir.github.models.GitHubPullState, safir.github.models.GitHubPullRequestModel, safir.github.models.GitHubBranchCommitModel, safir.github.models.GitHubBranchModel, safir.github.models.GitHubBlobModel, safir.github.models.GitHubCheckSuiteStatus, safir.github.models.GitHubCheckSuiteConclusion, safir.github.models.GitHubCheckSuiteModel, safir.github.models.GitHubCheckRunStatus, safir.github.models.GitHubCheckRunConclusion, safir.github.models.GitHubCheckRunAnnotationLevel, safir.github.models.GitHubCheckSuiteId, safir.github.models.GitHubCheckRunOutput, safir.github.models.GitHubCheckRunPrInfoModel, safir.github.models.GitHubCheckRunModel

safir.github.webhooks Module#

Pydantic models for GitHub webhook payloads.

Classes#

GitHubAppInstallationModel

A Pydantic model for the installation field found in webhook payloads for GitHub Apps.

GitHubPushEventModel

A Pydantic model for the push event webhook when a commit or tag is pushed.

GitHubAppInstallationEventRepoModel

A pydantic model for repository objects used by GitHubAppInstallationRepositoriesEventModel.

GitHubAppInstallationEventAction(value[, ...])

The action performed on an GitHub App installation webhook (GitHubAppInstallationEventModel).

GitHubAppInstallationEventModel

A Pydantic model for an installation webhook.

GitHubAppInstallationRepositoriesEventAction(value)

The action performed on a GitHub App installation_repositories webhook (GitHubAppInstallationRepositoriesEventModel).

GitHubAppInstallationRepositoriesEventModel

A Pydantic model for a installation_repositories webhook.

GitHubPullRequestEventAction(value[, names, ...])

The action performed on a GitHub pull_request webhook (GitHubPullRequestEventModel).

GitHubPullRequestEventModel

A Pydantic model for a pull_request webhook.

GitHubCheckSuiteEventAction(value[, names, ...])

The action performed in a GitHub check_suite webhook (GitHubCheckSuiteEventModel).

GitHubCheckSuiteEventModel

A Pydantic model for the check_suite webhook payload.

GitHubCheckRunEventAction(value[, names, ...])

The action performed in a GitHub check_run webhook (GitHubCheckRunEventModel).

GitHubCheckRunEventModel

A Pydantic model for the check_run webhook payload.

Class Inheritance Diagram#

Inheritance diagram of safir.github.webhooks.GitHubAppInstallationModel, safir.github.webhooks.GitHubPushEventModel, safir.github.webhooks.GitHubAppInstallationEventRepoModel, safir.github.webhooks.GitHubAppInstallationEventAction, safir.github.webhooks.GitHubAppInstallationEventModel, safir.github.webhooks.GitHubAppInstallationRepositoriesEventAction, safir.github.webhooks.GitHubAppInstallationRepositoriesEventModel, safir.github.webhooks.GitHubPullRequestEventAction, safir.github.webhooks.GitHubPullRequestEventModel, safir.github.webhooks.GitHubCheckSuiteEventAction, safir.github.webhooks.GitHubCheckSuiteEventModel, safir.github.webhooks.GitHubCheckRunEventAction, safir.github.webhooks.GitHubCheckRunEventModel

safir.kubernetes Module#

Utilities for configuring a Kubernetes client.

Functions#

initialize_kubernetes()

Load the Kubernetes configuration.

safir.logging Module#

Utilities for configuring structlog-based logging.

Functions#

add_log_severity(logger, method_name, event_dict)

Add the log level to the event dict as severity.

configure_logging(*, name[, profile, ...])

Configure logging and structlog.

configure_uvicorn_logging([log_level])

Set up logging.

Classes#

LogLevel(value[, names, module, qualname, ...])

Python logging level.

Profile(value[, names, module, qualname, ...])

Logging profile for the application.

Variables#

logger_name

Name of the configured global logger.

Class Inheritance Diagram#

Inheritance diagram of safir.logging.LogLevel, safir.logging.Profile

safir.metadata Module#

Standardized metadata for Roundtable HTTP services.

Functions#

get_metadata(*, package_name, application_name)

Retrieve metadata for the application.

get_project_url(meta, label)

Get a specific URL from a package's project_urls metadata.

Classes#

Metadata

Metadata about a package.

Class Inheritance Diagram#

Inheritance diagram of safir.metadata.Metadata

safir.models Module#

Standard models for FastAPI applications.

Notes

FastAPI does not appear to export its error response model in a usable form, so define a copy of it so that we can reference it in API definitions to generate good documentation.

Classes#

ErrorDetail

The detail of the error message.

ErrorLocation(value[, names, module, ...])

Possible locations for an error.

ErrorModel

A structured API error message.

Class Inheritance Diagram#

Inheritance diagram of safir.models.ErrorDetail, safir.models.ErrorLocation, safir.models.ErrorModel

safir.middleware.ivoa Module#

Middleware for IVOA services.

Classes#

CaseInsensitiveQueryMiddleware(app[, dispatch])

Make query parameter keys all lowercase.

Class Inheritance Diagram#

Inheritance diagram of safir.middleware.ivoa.CaseInsensitiveQueryMiddleware

safir.middleware.x_forwarded Module#

Update the request based on X-Forwarded-For headers.

Classes#

XForwardedMiddleware(app, *[, proxies])

Middleware to update the request based on X-Forwarded-For.

Class Inheritance Diagram#

Inheritance diagram of safir.middleware.x_forwarded.XForwardedMiddleware

safir.pydantic Module#

Utility functions for Pydantic models.

Functions#

normalize_datetime(v)

Pydantic field validator for datetime fields.

normalize_isodatetime(v)

Pydantic field validator for datetime fields in ISO format.

to_camel_case(string)

Convert a string to camel case.

validate_exactly_one_of(*settings)

Generate a model validator imposing a one and only one constraint.

Classes#

CamelCaseModel

pydantic.BaseModel configured to accept camel-case input.

Class Inheritance Diagram#

Inheritance diagram of safir.pydantic.CamelCaseModel

safir.redis Module#

Redis database support.

Classes#

PydanticRedisStorage(*, datatype, redis[, ...])

JSON-serialized encrypted storage in Redis.

EncryptedPydanticRedisStorage(*, datatype, ...)

A Pydantic-based Redis store that encrypts data.

DeserializeError(msg, key, error)

Raised when a stored Pydantic object in Redis cannot be decoded (and possibly decrypted) or deserialized.

Variables#

S

Type variable of Pydantic object being stored in PydanticRedisStorage.

Class Inheritance Diagram#

Inheritance diagram of safir.redis.PydanticRedisStorage, safir.redis.EncryptedPydanticRedisStorage, safir.redis.DeserializeError

safir.slack.blockkit Module#

Slack Block Kit message models.

Classes#

SlackBaseBlock

Base class for any Slack Block Kit block.

SlackBaseField

Base class for Slack Block Kit blocks for the fields section.

SlackCodeBlock

A component of a Slack message with a heading and a code block.

SlackCodeField

An attachment in a Slack message with a heading and text body.

SlackException(message[, user, failed_at])

Parent class of exceptions that can be reported to Slack.

SlackMessage

Message to post to Slack.

SlackTextBlock

A component of a Slack message with a heading and a text body.

SlackTextField

One field in a Slack message with a heading and text body.

SlackWebException(message, *[, failed_at, ...])

Parent class of exceptions arising from HTTPX failures.

Class Inheritance Diagram#

Inheritance diagram of safir.slack.blockkit.SlackBaseBlock, safir.slack.blockkit.SlackBaseField, safir.slack.blockkit.SlackCodeBlock, safir.slack.blockkit.SlackCodeField, safir.slack.blockkit.SlackException, safir.slack.blockkit.SlackMessage, safir.slack.blockkit.SlackTextBlock, safir.slack.blockkit.SlackTextField, safir.slack.blockkit.SlackWebException

safir.slack.webhook Module#

Send messages to Slack.

Classes#

SlackIgnoredException

Parent class for exceptions that should not be reported to Slack.

SlackRouteErrorHandler(path, endpoint, *[, ...])

Custom fastapi.routing.APIRoute that reports exceptions to Slack.

SlackWebhookClient(hook_url, application, logger)

Send messages to a Slack webhook.

Class Inheritance Diagram#

Inheritance diagram of safir.slack.webhook.SlackIgnoredException, safir.slack.webhook.SlackRouteErrorHandler, safir.slack.webhook.SlackWebhookClient

safir.testing.gcs Module#

Mock Google Cloud Storage API for testing.

Functions#

patch_google_storage(*[, ...])

Replace the Google Cloud Storage API with a mock class.

Classes#

MockBlob(name[, expected_expiration])

Mock version of google.cloud.storage.blob.Blob.

MockBucket(bucket_name[, ...])

Mock version of google.cloud.storage.bucket.Bucket.

MockStorageClient([expected_expiration, ...])

Mock version of google.cloud.storage.Client.

Class Inheritance Diagram#

Inheritance diagram of safir.testing.gcs.MockBlob, safir.testing.gcs.MockBucket, safir.testing.gcs.MockStorageClient

safir.testing.kubernetes Module#

Mock Kubernetes API for testing.

Functions#

patch_kubernetes()

Replace the Kubernetes API with a mock class.

strip_none(model)

Strip None values from a serialized Kubernetes object.

Classes#

MockKubernetesApi()

Mock Kubernetes API for testing.

Class Inheritance Diagram#

Inheritance diagram of safir.testing.kubernetes.MockKubernetesApi

safir.testing.slack Module#

Mock Slack server for testing Slack messaging.

Functions#

mock_slack_webhook(hook_url, respx_mock)

Set up a mocked Slack server.

Classes#

MockSlackWebhook(url)

Represents a Slack incoming webhook and remembers what was posted.

Class Inheritance Diagram#

Inheritance diagram of safir.testing.slack.MockSlackWebhook

safir.testing.uvicorn Module#

Utiility functions for managing an external Uvicorn test process.

Normally, ASGI apps are tested via the built-in support in HTTPX for running an ASGI app directly. However, sometimes the app has to be spawned in a separate process so that it can be accessed over HTTP, such as when testing it with Selenium or when testing Uvicorn integration. This module provides utility functions to aid with that test setup.

Functions#

spawn_uvicorn(*, working_directory[, app, ...])

Spawn an ASGI app as a separate Uvicorn process.

Classes#

ServerNotListeningError

Timeout waiting for the server to start listening.

UvicornProcess(process, url)

Properties of the running Uvicorn service.

Class Inheritance Diagram#

Inheritance diagram of safir.testing.uvicorn.ServerNotListeningError, safir.testing.uvicorn.UvicornProcess