Skip to content

Commit d22102d

Browse files
committed
Extract palace.opds into a uv workspace package
Stacked on the palace-util extraction. Move palace.manager.opds into a new workspace package at packages/palace-opds/ (namespace palace.opds) and retarget all callers. The OPDS model tree is generic and reusable across Palace projects; making it a standalone workspace member lets us publish it independently without dragging in palace-manager. palace-opds depends on palace-util for the three small cross-cutting symbols the models need (PalaceValueError, utc_now/to_utc, LoggerMixin). Callers rewritten (palace.manager.opds.* → palace.opds.*): - 17 source files across palace.manager.{api, celery, data_layer, feed, integration, sqlalchemy}. - 15 test files across tests/manager/**. Moved tests: - tests/manager/opds/** → packages/palace-opds/tests/opds/**. The 5 tests that only use OPDS2FilesFixture / OPDS2WithODLFilesFixture as type annotations now import them under TYPE_CHECKING so the package tests don't need tests.fixtures.files at import time; pytest still injects the fixtures at runtime via the root-conftest plugin. - tests/manager/opds/types/test_language.py: replace LogLevel.warning with stdlib logging.WARNING so the test has no palace.manager import. Tooling: - pyproject.toml: palace-opds added to [project.dependencies], workspace members, mypy files/mypy_path, coverage source, pytest testpaths. tests-mypy override picks up "opds.*". - docker/Dockerfile, docker/Dockerfile.baseimage: copy packages/palace-opds/pyproject.toml in the cache layer alongside palace-util. - README.md, CLAUDE.md: workspace section extended with palace-opds.
1 parent 5001201 commit d22102d

78 files changed

Lines changed: 260 additions & 151 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CLAUDE.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ This repository is a [`uv` workspace](https://docs.astral.sh/uv/concepts/project
6161
- `/data_layer` - Pydantic models for content import and validation
6262
- `/feed` - OPDS (Open Publication Distribution System) feed generation
6363
- `/integration` - Third-party service integrations and content provider APIs
64-
- `/opds` - Pydantic models for OPDS feed parsing and validation
6564
- `/scripts` - Legacy CLI utilities (**deprecated - no new code**)
6665
- `/search` - OpenSearch integration and indexing logic
6766
- `/service` - Dependency injection container and service layer

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ live under `packages/`:
2323

2424
- [`palace-util`](packages/palace-util/README.md) — shared utilities (exceptions, datetime helpers,
2525
`LoggerMixin`) under the `palace.util` namespace.
26+
- [`palace-opds`](packages/palace-opds/README.md) — Pydantic models for OPDS 2.0, RWPM, ODL, LCP, and
27+
Palace extensions under the `palace.opds` namespace.
2628

2729
## Installation
2830

docker/Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ RUN mv /etc/cron.daily/logrotate /etc/cron.hourly/logrotate
2222
# uv can resolve workspace members without invalidating this layer on source changes.
2323
COPY --chown=palace:palace uv.lock pyproject.toml /var/www/circulation/
2424
COPY --chown=palace:palace packages/palace-util/pyproject.toml /var/www/circulation/packages/palace-util/
25+
COPY --chown=palace:palace packages/palace-opds/pyproject.toml /var/www/circulation/packages/palace-opds/
2526
RUN uv sync --frozen --no-dev --no-install-workspace
2627

2728
COPY --chown=palace:palace . /var/www/circulation

docker/Dockerfile.baseimage

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ COPY --chown=palace:palace uv.lock pyproject.toml /var/www/circulation/
6464
# workspace; we copy just the manifests (not the source) so this layer doesn't
6565
# get invalidated by source changes.
6666
COPY --chown=palace:palace packages/palace-util/pyproject.toml /var/www/circulation/packages/palace-util/
67+
COPY --chown=palace:palace packages/palace-opds/pyproject.toml /var/www/circulation/packages/palace-opds/
6768

6869
# Setup virtualenv and install our python dependencies.
6970
# What we install is based on the uv.lock file in the repo at the time this

packages/palace-opds/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# palace-opds
2+
3+
Pydantic models for OPDS 2.0, RWPM, ODL, LCP, Authentication for OPDS, and Palace Project extensions.
4+
Exposes the `palace.opds` namespace module.
5+
6+
Top-level modules:
7+
8+
- `palace.opds.opds2` — OPDS 2.0 publication and feed models.
9+
- `palace.opds.rwpm` — Readium Web Publication Manifest.
10+
- `palace.opds.authentication` — Authentication for OPDS 1.0.
11+
- `palace.opds.palace` — Palace-specific extensions.
12+
- `palace.opds.a11y` — W3C accessibility metadata.
13+
- `palace.opds.schema_org` — Schema.org vocabulary.
14+
- `palace.opds.types.*` — Shared Pydantic types (`BaseLink`, language, date, currency).
15+
- `palace.opds.odl.*` — ODL 1.0 license metadata and status.
16+
- `palace.opds.lcp.*` — LCP license and loan status documents.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[build-system]
2+
build-backend = "hatchling.build"
3+
requires = ["hatchling"]
4+
5+
[project]
6+
authors = [{name = "The Palace Project", email = "info@thepalaceproject.org"}]
7+
dependencies = [
8+
"palace-util",
9+
"pycountry>=26.2.16,<27",
10+
"pydantic-xml>=2.17.0,<3",
11+
"pydantic[email]>=2.12,<3",
12+
"uritemplate==4.2.0",
13+
]
14+
description = "Pydantic models for OPDS 2.0, RWPM, ODL, LCP, and Palace Project extensions."
15+
license = "Apache-2.0"
16+
name = "palace-opds"
17+
readme = "README.md"
18+
requires-python = ">=3.12,<4"
19+
version = "0"
20+
21+
[project.urls]
22+
Homepage = "https://thepalaceproject.org"
23+
Repository = "https://github.com/ThePalaceProject/circulation"
24+
25+
[tool.hatch.build.targets.wheel]
26+
packages = ["src/palace"]
27+
28+
[tool.uv.sources]
29+
palace-util = {workspace = true}
File renamed without changes.

src/palace/manager/opds/a11y.py renamed to packages/palace-opds/src/palace/opds/a11y.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414

1515
from pydantic import Field, SerializerFunctionWrapHandler, model_serializer
1616

17-
from palace.manager.opds.base import BaseOpdsModel
18-
from palace.manager.opds.util import StrOrTuple, drop_if_falsy, obj_or_tuple_to_tuple
17+
from palace.opds.base import BaseOpdsModel
18+
from palace.opds.util import StrOrTuple, drop_if_falsy, obj_or_tuple_to_tuple
1919

2020

2121
class AccessMode(StrEnum):

src/palace/manager/opds/authentication.py renamed to packages/palace-opds/src/palace/opds/authentication.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55

66
from pydantic import BaseModel, Field, field_validator
77

8-
from palace.manager.core.exceptions import PalaceValueError
9-
from palace.manager.opds.rwpm import Link
10-
from palace.manager.opds.types.link import CompactCollection
8+
from palace.opds.rwpm import Link
9+
from palace.opds.types.link import CompactCollection
10+
from palace.util.exceptions import PalaceValueError
1111

1212

1313
class AuthenticationLabels(BaseModel):
File renamed without changes.

0 commit comments

Comments
 (0)