Skip to content

Commit 8686736

Browse files
authored
Merge pull request #132 from openzim/big_rework
Big rework
2 parents 29af0d8 + 3fc946c commit 8686736

File tree

74 files changed

+1983
-5320
lines changed

Some content is hidden

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

74 files changed

+1983
-5320
lines changed

backend/src/cms_backend/api/main.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010
from pydantic import ValidationError
1111

1212
from cms_backend.api.routes.books import router as books_router
13+
from cms_backend.api.routes.collection import router as collection_router
1314
from cms_backend.api.routes.healthcheck import router as healthcheck_router
1415
from cms_backend.api.routes.http_errors import BadRequestError
15-
from cms_backend.api.routes.library import router as library_router
1616
from cms_backend.api.routes.titles import router as titles_router
17-
from cms_backend.api.routes.warehouse_paths import router as warehouse_paths_router
1817
from cms_backend.api.routes.zimfarm_notifications import (
1918
router as zimfarm_notification_router,
2019
)
20+
from cms_backend.context import Context
2121
from cms_backend.db.exceptions import (
2222
RecordAlreadyExistsError,
2323
RecordDisabledError,
@@ -30,7 +30,8 @@
3030

3131
@asynccontextmanager
3232
async def lifespan(_: FastAPI):
33-
upgrade_db_schema()
33+
if Context.alembic_upgrade_head_on_start:
34+
upgrade_db_schema()
3435
yield
3536

3637

@@ -58,8 +59,7 @@ def create_app(*, debug: bool = True):
5859
main_router.include_router(router=healthcheck_router)
5960
main_router.include_router(router=titles_router)
6061
main_router.include_router(router=books_router)
61-
main_router.include_router(router=warehouse_paths_router)
62-
main_router.include_router(router=library_router)
62+
main_router.include_router(router=collection_router)
6363

6464
app.include_router(router=main_router)
6565

backend/src/cms_backend/api/routes/books.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
BookFullSchema,
1515
BookLightSchema,
1616
BookLocationSchema,
17-
ProducerSchema,
1817
)
1918

2019
router = APIRouter(prefix="/books", tags=["books"])
@@ -67,9 +66,8 @@ async def get_book(
6766
# Separate current and target locations
6867
current_locations = [
6968
BookLocationSchema(
70-
warehouse_path_id=location.warehouse_path_id,
71-
warehouse_name=location.warehouse_path.warehouse.name,
72-
folder_name=location.warehouse_path.folder_name,
69+
warehouse_name=location.warehouse.name,
70+
path=str(location.path),
7371
filename=location.filename,
7472
status=location.status,
7573
)
@@ -79,9 +77,8 @@ async def get_book(
7977

8078
target_locations = [
8179
BookLocationSchema(
82-
warehouse_path_id=location.warehouse_path_id,
83-
warehouse_name=location.warehouse_path.warehouse.name,
84-
folder_name=location.warehouse_path.folder_name,
80+
warehouse_name=location.warehouse.name,
81+
path=str(location.path),
8582
filename=location.filename,
8683
status=location.status,
8784
)
@@ -103,11 +100,6 @@ async def get_book(
103100
zimcheck_result=db_book.zimcheck_result,
104101
zim_metadata=db_book.zim_metadata,
105102
events=db_book.events,
106-
producer=ProducerSchema(
107-
display_name=db_book.producer_display_name,
108-
display_url=db_book.producer_display_url,
109-
unique_id=db_book.producer_unique_id,
110-
),
111103
current_locations=current_locations,
112104
target_locations=target_locations,
113105
)

backend/src/cms_backend/api/routes/library.py renamed to backend/src/cms_backend/api/routes/collection.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
from sqlalchemy.orm import Session as OrmSession
99

1010
from cms_backend.db import gen_dbsession
11-
from cms_backend.db.exceptions import RecordDoesNotExistError
12-
from cms_backend.db.library import (
13-
get_latest_books_for_library,
14-
get_library,
15-
get_library_by_name_or_none,
11+
from cms_backend.db.collection import (
12+
get_collection,
13+
get_collection_by_name_or_none,
14+
get_latest_books_for_collection,
1615
)
16+
from cms_backend.db.exceptions import RecordDoesNotExistError
1717
from cms_backend.db.models import Book
1818

19-
router = APIRouter(prefix="/libraries", tags=["libraries"])
19+
router = APIRouter(prefix="/collections", tags=["collections"])
2020

2121

2222
def _build_library_xml(books: list[Book]) -> str:
@@ -67,33 +67,33 @@ def _build_library_xml(books: list[Book]) -> str:
6767
return ET.tostring(library_elem, encoding="unicode")
6868

6969

70-
@router.get("/{library_id_or_name}/catalog.xml")
70+
@router.get("/{collection_id_or_name}/catalog.xml")
7171
async def get_library_catalog_xml(
72-
library_id_or_name: Annotated[str, Path()],
72+
collection_id_or_name: Annotated[str, Path()],
7373
session: Annotated[OrmSession, Depends(gen_dbsession)],
7474
):
75-
"""Get library catalog as XML. Library can be specified by ID (UUID) or name."""
75+
"""Get collection catalog as XML library by collection ID (UUID) or name."""
7676
# Try to parse as UUID first, otherwise treat as name
77-
library = None
77+
collection = None
7878
try:
79-
library_id = UUID(library_id_or_name)
79+
collection_id = UUID(collection_id_or_name)
8080
try:
81-
library = get_library(session, library_id)
81+
collection = get_collection(session, collection_id)
8282
except RecordDoesNotExistError:
8383
pass
8484
except ValueError:
8585
# Not a valid UUID, try as name
86-
library = get_library_by_name_or_none(session, library_id_or_name)
86+
collection = get_collection_by_name_or_none(session, collection_id_or_name)
8787

88-
if library is None:
88+
if collection is None:
8989
return Response(
9090
content='<?xml version="1.0" encoding="UTF-8"?>'
9191
'<library version="20110515"></library>',
9292
status_code=HTTPStatus.NOT_FOUND,
9393
media_type="application/xml",
9494
)
9595

96-
books = get_latest_books_for_library(session, library.id)
96+
books = get_latest_books_for_collection(session, collection.id)
9797
xml_content = _build_library_xml(books)
9898

9999
return Response(

backend/src/cms_backend/api/routes/titles.py

Lines changed: 13 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
from cms_backend.schemas import BaseModel
1414
from cms_backend.schemas.orms import (
1515
BookLightSchema,
16+
TitleCollectionSchema,
1617
TitleFullSchema,
1718
TitleLightSchema,
18-
WarehousePathInfoSchema,
1919
)
2020

2121
router = APIRouter(prefix="/titles", tags=["titles"])
@@ -29,12 +29,7 @@ class TitlesGetSchema(BaseModel):
2929

3030
class TitleCreateSchema(BaseModel):
3131
name: str
32-
producer_unique_id: str
33-
producer_display_name: str | None = None
34-
producer_display_url: str | None = None
35-
dev_warehouse_path_ids: list[UUID]
36-
prod_warehouse_path_ids: list[UUID]
37-
in_prod: bool = False
32+
maturity: str | None = None
3833

3934

4035
@router.get("")
@@ -67,29 +62,10 @@ def get_title(
6762
"""Get a title by ID with full details including books"""
6863
title = db_get_title_by_id(session, title_id=title_id)
6964

70-
# Build sorted warehouse path lists by path_type
71-
def build_warehouse_paths(path_type: str) -> list[WarehousePathInfoSchema]:
72-
paths = [
73-
WarehousePathInfoSchema(
74-
path_id=twp.warehouse_path.id,
75-
folder_name=twp.warehouse_path.folder_name,
76-
warehouse_name=twp.warehouse_path.warehouse.name,
77-
)
78-
for twp in title.warehouse_paths
79-
if twp.path_type == path_type
80-
]
81-
# Sort alphabetically by warehouse_name then folder_name
82-
return sorted(paths, key=lambda p: (p.warehouse_name, p.folder_name))
83-
8465
return TitleFullSchema(
8566
id=title.id,
8667
name=title.name,
87-
producer_unique_id=title.producer_unique_id,
88-
producer_display_name=title.producer_display_name,
89-
producer_display_url=title.producer_display_url,
90-
dev_warehouse_paths=build_warehouse_paths("dev"),
91-
prod_warehouse_paths=build_warehouse_paths("prod"),
92-
in_prod=title.in_prod,
68+
maturity=title.maturity,
9369
events=title.events,
9470
books=[
9571
BookLightSchema(
@@ -103,6 +79,14 @@ def build_warehouse_paths(path_type: str) -> list[WarehousePathInfoSchema]:
10379
)
10480
for book in title.books
10581
],
82+
collections=[
83+
TitleCollectionSchema(
84+
collection_id=tc.collection_id,
85+
collection_name=tc.collection.name,
86+
path=str(tc.path),
87+
)
88+
for tc in title.collections
89+
],
10690
)
10791

10892

@@ -115,17 +99,10 @@ def create_title(
11599
title = db_create_title(
116100
session,
117101
name=title_data.name,
118-
producer_unique_id=title_data.producer_unique_id,
119-
producer_display_name=title_data.producer_display_name,
120-
producer_display_url=title_data.producer_display_url,
121-
dev_warehouse_path_ids=title_data.dev_warehouse_path_ids,
122-
prod_warehouse_path_ids=title_data.prod_warehouse_path_ids,
123-
in_prod=title_data.in_prod,
102+
maturity=title_data.maturity,
124103
)
125104
return TitleLightSchema(
126105
id=title.id,
127106
name=title.name,
128-
producer_unique_id=title.producer_unique_id,
129-
producer_display_name=title.producer_display_name,
130-
producer_display_url=title.producer_display_url,
107+
maturity=title.maturity,
131108
)

backend/src/cms_backend/api/routes/warehouse_paths.py

Lines changed: 0 additions & 19 deletions
This file was deleted.

backend/src/cms_backend/db/book.py

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
from pathlib import Path
12
from typing import Any
23
from uuid import UUID
34

45
from sqlalchemy import select
56
from sqlalchemy.orm import Session as OrmSession
67

7-
from cms_backend.db.models import Book, BookLocation, WarehousePath, ZimfarmNotification
8+
from cms_backend.db.models import Book, BookLocation, Warehouse, ZimfarmNotification
89
from cms_backend.utils.datetime import getnow
910

1011

@@ -18,9 +19,6 @@ def create_book(
1819
zim_metadata: dict[str, Any],
1920
zimcheck_result: dict[str, Any],
2021
zimfarm_notification: ZimfarmNotification,
21-
producer_display_name: str,
22-
producer_display_url: str,
23-
producer_unique_id: str,
2422
) -> Book:
2523
"""Create a new book"""
2624

@@ -41,9 +39,6 @@ def create_book(
4139
date=date,
4240
flavour=flavour,
4341
zimfarm_notification=zimfarm_notification,
44-
producer_display_name=producer_display_name,
45-
producer_display_url=producer_display_url,
46-
producer_unique_id=producer_unique_id,
4742
)
4843
session.add(book)
4944
zimfarm_notification.events.append(
@@ -60,7 +55,8 @@ def create_book_location(
6055
session: OrmSession,
6156
*,
6257
book: Book,
63-
warehouse_path_id: UUID,
58+
warehouse_id: UUID,
59+
path: Path,
6460
filename: str,
6561
status: str = "current",
6662
) -> BookLocation:
@@ -69,32 +65,33 @@ def create_book_location(
6965
Args:
7066
session: SQLAlchemy session
7167
book: Book instance
72-
warehouse_path_id: ID of the warehouse path
68+
warehouse_id: ID of the warehouse
69+
path: Folder path within the warehouse (e.g., "dev-zim")
7370
filename: Filename in warehouse
7471
status: Location status ('current' or 'target'), defaults to 'current'
7572
7673
Returns:
7774
Created BookLocation instance
7875
"""
79-
# Get warehouse path info for event message
80-
warehouse_path = session.get(WarehousePath, warehouse_path_id)
81-
if not warehouse_path:
82-
raise ValueError(f"WarehousePath with id {warehouse_path_id} not found")
76+
# Get warehouse info for event message
77+
warehouse = session.get(Warehouse, warehouse_id)
78+
if not warehouse:
79+
raise ValueError(f"Warehouse with id {warehouse_id} not found")
8380

84-
warehouse_name = warehouse_path.warehouse.name
85-
folder_name = warehouse_path.folder_name
81+
warehouse_name = warehouse.name
8682

8783
location = BookLocation(
8884
book_id=book.id,
85+
warehouse_id=warehouse_id,
86+
path=path,
8987
status=status,
9088
filename=filename,
9189
)
92-
location.warehouse_path_id = warehouse_path_id
9390
session.add(location)
9491
book.locations.append(location)
9592
book.events.append(
9693
f"{getnow()}: added {status} location: {filename} in {warehouse_name}: "
97-
f"{folder_name} ({warehouse_path_id})"
94+
f"{path} ({warehouse_id})"
9895
)
9996

10097
return location

0 commit comments

Comments
 (0)