Skip to content

Commit 917126c

Browse files
committed
fix: migrate from Pydantic v1 .dict() to v2 .model_dump() for iscc-schema compatibility
Replace deprecated skip_defaults parameter with exclude_none and by_alias in model_dump() calls. Update test expectations for new iscc-schema 0.5.0 versioned URLs. Includes formatting fixes from linter.
1 parent 837583d commit 917126c

12 files changed

Lines changed: 313 additions & 246 deletions

File tree

develop/format_openapi.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import pathlib
33
import yaml
44

5-
65
HERE = pathlib.Path(__file__).parent.absolute()
76
OPENAPI = HERE.parent / "iscc_web/static/docs/openapi.yaml"
87

develop/lf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""Poor Windows Users :) - Convert line endings to LF"""
2+
23
import pathlib
34

45
HERE = pathlib.Path(__file__).parent.parent.absolute()

iscc_web/api/common.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""Common helper functions"""
2+
23
from blacksheep import Request
34
import shutil
45
from aiofiles.os import wrap

iscc_web/api/iscc.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,6 @@ async def create_iscc(self, request: Request):
5050
location = f"{base_url(request)}/media/{result.media_id}"
5151
proc_result.media_id = result.media_id
5252
proc_result.content = location
53-
return self.created(location=location_header, value=proc_result.dict(skip_defaults=False))
53+
return self.created(
54+
location=location_header, value=proc_result.model_dump(exclude_none=True, by_alias=True)
55+
)

iscc_web/api/metadata.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ async def extract(self, media_id: str, pool: Pool):
2929

3030
loop = asyncio.get_event_loop()
3131
metadata = await loop.run_in_executor(pool, idk.extract_metadata, file_path)
32-
cleaned = metadata.dict(
32+
cleaned = metadata.model_dump(
3333
include={
3434
"name",
3535
"description",
@@ -42,7 +42,7 @@ async def extract(self, media_id: str, pool: Pool):
4242
}
4343
)
4444
obj = InlineMetadata(**cleaned)
45-
return self.json(obj.dict(exclude_none=True))
45+
return self.json(obj.model_dump(exclude_none=True))
4646

4747
@post("{mid:media_id}")
4848
async def embed(self, request: Request, media_id: str, meta: InlineMetadata, pool: Pool):
@@ -89,4 +89,6 @@ async def embed(self, request: Request, media_id: str, meta: InlineMetadata, poo
8989
location_header = f"/api/v1/media/{new_media_id}".encode("ascii")
9090
proc_result.media_id = new_media_id
9191
proc_result.content = location
92-
return self.created(location=location_header, value=proc_result.dict(skip_defaults=False))
92+
return self.created(
93+
location=location_header, value=proc_result.model_dump(exclude_none=True, by_alias=True)
94+
)

iscc_web/api/schema.py

Lines changed: 52 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
# generated by datamodel-codegen:
22
# filename: openapi.yaml
3-
# version: 0.30.1
3+
# version: 0.55.0
44

55
from __future__ import annotations
66

7-
from enum import Enum
8-
from typing import List, Optional, Union
7+
from enum import StrEnum
98

109
from pydantic import AnyUrl, BaseModel, Field, RootModel, confloat, conint, constr
1110

@@ -21,10 +20,7 @@ class MediaID(RootModel[constr(pattern=r"[a-v0-9]{13}$", min_length=13, max_leng
2120
class Iscc(RootModel[constr(pattern=r"^ISCC:[A-Z2-7]{10,73}$", min_length=15, max_length=73)]):
2221
root: constr(pattern=r"^ISCC:[A-Z2-7]{10,73}$", min_length=15, max_length=73) = Field(
2322
...,
24-
description=(
25-
"An **ISCC** in canonical representation. This is the minimal required field for a"
26-
" valid ISCC Metadata object."
27-
),
23+
description="An **ISCC** in canonical representation. This is the minimal required field for a valid ISCC Metadata object.",
2824
examples=["ISCC:KACYPXW445FTYNJ3CYSXHAFJMA2HUWULUNRFE3BLHRSCXYH2M5AEGQY"],
2925
)
3026

@@ -34,13 +30,11 @@ class UploadResponse(BaseModel):
3430
Information required to download the newly created media resource.
3531
"""
3632

37-
content: Optional[str] = Field(
38-
None, examples=["http://localhost:8000/api/v1/media/061knt35ejv6o"]
39-
)
40-
media_id: Optional[MediaID] = None
33+
content: str | None = Field(None, examples=["http://localhost:8000/api/v1/media/061knt35ejv6o"])
34+
media_id: MediaID | None = None
4135

4236

43-
class FieldType(Enum):
37+
class FieldType(StrEnum):
4438
"""
4539
The type of digital content according to schema.org classes (TextDigitalDocument, ImageObject, AudioObject, VideoObject).
4640
"""
@@ -57,108 +51,82 @@ class BasicMetadata(BaseModel):
5751
Minimal ISCC Metadata
5852
"""
5953

60-
field_context: Optional[AnyUrl] = Field(
54+
field_context: AnyUrl | None = Field(
6155
None,
6256
alias="@context",
6357
description="The [JSON-LD](https://json-ld.org/) Context URI for ISCC metadata.",
6458
examples=["http://purl.org/iscc/context/0.4.0.jsonld"],
6559
)
66-
field_type: Optional[FieldType] = Field(
60+
field_type: FieldType | None = Field(
6761
"CreativeWork",
6862
alias="@type",
69-
description=(
70-
"The type of digital content according to schema.org classes (TextDigitalDocument,"
71-
" ImageObject, AudioObject, VideoObject)."
72-
),
63+
description="The type of digital content according to schema.org classes (TextDigitalDocument, ImageObject, AudioObject, VideoObject).",
7364
)
74-
field_schema: Optional[AnyUrl] = Field(
65+
field_schema: AnyUrl | None = Field(
7566
None,
7667
alias="$schema",
7768
description="The [JSON Schema](https://json-schema.org/) URI for ISCC metadata.",
7869
examples=["http://purl.org/iscc/schema/0.4.0.json"],
7970
)
80-
iscc: Optional[Iscc] = None
71+
iscc: Iscc | None = None
8172

8273

8374
class InlineMetadata(BaseModel):
8475
"""
8576
Metadata intended to be embedded into the media asset.
8677
"""
8778

88-
name: Optional[constr(max_length=128)] = Field(
79+
name: constr(max_length=128) | None = Field(
8980
None,
90-
description=(
91-
"The title or name of the intangible creation manifested by the identified *digital"
92-
" content*. **Used as input for ISCC Meta-Code generation**."
93-
),
81+
description="The title or name of the intangible creation manifested by the identified *digital content*. **Used as input for ISCC Meta-Code generation**.",
9482
examples=["The Never Ending Story"],
9583
)
96-
description: Optional[constr(max_length=4096)] = Field(
84+
description: constr(max_length=4096) | None = Field(
9785
None,
98-
description=(
99-
"Description of the *digital content* identified by the **ISCC**. **Used as input for"
100-
" ISCC Meta-Code generation**. Any user presentable text string (including Markdown"
101-
" text) indicative of the identity of the referent may be used."
102-
),
86+
description="Description of the *digital content* identified by the **ISCC**. **Used as input for ISCC Meta-Code generation**. Any user presentable text string (including Markdown text) indicative of the identity of the referent may be used.",
10387
examples=["a 1984 fantasy film co-written and directed by *Wolfgang Petersen*"],
10488
)
105-
meta: Optional[constr(max_length=16384)] = Field(
89+
meta: constr(max_length=16384) | None = Field(
10690
None,
10791
description="Subject, industry, or use-case specific metadata encoded as Data-URL.",
10892
examples=["data:application/json;charset=utf-8;base64,eyJleHRlbmRlZCI6Im1ldGFkYXRhIn0="],
10993
)
110-
identifier: Optional[str] = Field(
94+
identifier: str | None = Field(
11195
None,
112-
description=(
113-
"Other identifier(s) referencing the work, product or other abstraction of which the"
114-
" referenced **digital content** is a full or partial manifestation."
115-
),
96+
description="Other identifier(s) referencing the work, product or other abstraction of which the referenced **digital content** is a full or partial manifestation.",
11697
)
117-
creator: Optional[str] = Field(
98+
creator: str | None = Field(
11899
None,
119100
description="An entity primarily responsible for making the resource.",
120101
examples=["Joanne K. Rowling"],
121102
)
122-
license: Optional[str] = Field(
103+
license: str | None = Field(
123104
None,
124105
description="URI of license for the identified *digital content*.",
125106
examples=["https://example.com/license-terms-for-this-item"],
126107
)
127-
acquire: Optional[AnyUrl] = Field(
108+
acquire: AnyUrl | None = Field(
128109
None,
129-
description=(
130-
"This field must contain a valid URL referring to a page showing information about how"
131-
" one can acquire a license for the item. This may be a page of a web shop or NFT"
132-
" marketplace ready for providing a license."
133-
),
110+
description="This field must contain a valid URL referring to a page showing information about how one can acquire a license for the item. This may be a page of a web shop or NFT marketplace ready for providing a license.",
134111
examples=["https://example.com/buy-license-for-item-here"],
135112
)
136-
credit: Optional[str] = Field(
113+
credit: str | None = Field(
137114
None,
138-
description=(
139-
"A line of text that you expect users of the image (such as Google Images) to display"
140-
" alongside the image."
141-
),
115+
description="A line of text that you expect users of the image (such as Google Images) to display alongside the image.",
142116
examples=["Frank Farian - Getty Images"],
143117
)
144-
rights: Optional[str] = Field(
118+
rights: str | None = Field(
145119
None,
146-
description=(
147-
"Contains any necessary copyright notice and should identify the current owner of the"
148-
" copyright of this work with associated intellectual property rights."
149-
),
120+
description="Contains any necessary copyright notice and should identify the current owner of the copyright of this work with associated intellectual property rights.",
150121
examples=["Copyright 2022 ISCC Foundation - www.iscc.codes"],
151122
)
152-
keywords: Optional[Union[str, List[str]]] = Field(
123+
keywords: str | list[str] | None = Field(
153124
None,
154-
description=(
155-
"Keywords or tags used to describe this content. Multiple entries in a keywords list"
156-
" are typically delimited by commas."
157-
),
125+
description="Keywords or tags used to describe this content. Multiple entries in a keywords list are typically delimited by commas.",
158126
)
159127

160128

161-
class Mode(Enum):
129+
class Mode(StrEnum):
162130
"""
163131
The perceptual mode used to create the ISCC.
164132
"""
@@ -175,53 +143,45 @@ class TechnicalMetadata(BaseModel):
175143
Technical ISCC Metadata automaticaly inferred from the media file by the ISCC processor
176144
"""
177145

178-
mode: Optional[Mode] = Field(
146+
mode: Mode | None = Field(
179147
None, description="The perceptual mode used to create the ISCC.", examples=["image"]
180148
)
181-
filename: Optional[str] = Field(
149+
filename: str | None = Field(
182150
None,
183151
description="Filename of the referenced **digital content**",
184152
examples=["your-media-file.jpg"],
185153
)
186-
filesize: Optional[int] = Field(
187-
None, description="File size of media asset in number of bytes."
188-
)
189-
mediatype: Optional[str] = Field(
154+
filesize: int | None = Field(None, description="File size of media asset in number of bytes.")
155+
mediatype: str | None = Field(
190156
None,
191-
description=(
192-
"An [IANA Media Type](https://www.iana.org/assignments/media-types/media-types.xhtml)"
193-
" (MIME type)"
194-
),
157+
description="An [IANA Media Type](https://www.iana.org/assignments/media-types/media-types.xhtml) (MIME type)",
195158
examples=["image/jpeg"],
196159
)
197-
duration: Optional[int] = Field(
160+
duration: int | None = Field(
198161
None, description="Duration of audio-visual media in seconds.", examples=[60]
199162
)
200-
fps: Optional[confloat(ge=1.0)] = Field(
163+
fps: confloat(ge=1.0) | None = Field(
201164
None, description="Frames per second of video assets.", examples=[24]
202165
)
203-
width: Optional[int] = Field(
166+
width: int | None = Field(
204167
None, description="Width of visual media in number of pixels.", examples=[640]
205168
)
206-
height: Optional[conint(ge=1)] = Field(
169+
height: conint(ge=1) | None = Field(
207170
None, description="Height of visual media in number of pixels.", examples=[480]
208171
)
209-
characters: Optional[int] = Field(
172+
characters: int | None = Field(
210173
None,
211174
description="Number of text characters (code points after Unicode normalization)",
212175
examples=[55689],
213176
)
214-
language: Optional[str] = Field(
177+
language: str | None = Field(
215178
None,
216179
description="Primary language of content [BCP 47](https://tools.ietf.org/search/bcp47).",
217180
examples=["en-US"],
218181
)
219-
thumbnail: Optional[AnyUrl] = Field(
182+
thumbnail: AnyUrl | None = Field(
220183
None,
221-
description=(
222-
"URI an autogenerated user-presentable thumbnail-image that serves as a preview of the"
223-
" digital content. The URI may be a Data-URL RFC2397."
224-
),
184+
description="URI an autogenerated user-presentable thumbnail-image that serves as a preview of the digital content. The URI may be a Data-URL RFC2397.",
225185
examples=["https://picsum.photos/200/300.jpg"],
226186
)
227187

@@ -231,25 +191,25 @@ class Unit(BaseModel):
231191
An ISCC-UNIT in different representations
232192
"""
233193

234-
iscc_unit: Optional[str] = Field(
194+
iscc_unit: str | None = Field(
235195
None,
236196
description="Canonical representation of ISCC-UNIT",
237197
examples=["ISCC:AAA4RJYGHHVRCZ5T"],
238198
)
239-
readable: Optional[str] = Field(
199+
readable: str | None = Field(
240200
None,
241201
description="Human readable version of ISCC-UNIT",
242202
examples=["META-NONE-V0-64-c8a70639eb1167b3"],
243203
)
244-
hash_hex: Optional[str] = Field(
204+
hash_hex: str | None = Field(
245205
None, description="Hex representation of ISCC-BODY", examples=["e1fb7dc4e3dbb4be"]
246206
)
247-
hash_uint: Optional[str] = Field(
207+
hash_uint: str | None = Field(
248208
None,
249209
description="Unsigned integer representation of ISCC-BODY",
250210
examples=["16283747162278048958"],
251211
)
252-
hash_bits: Optional[str] = Field(
212+
hash_bits: str | None = Field(
253213
None,
254214
description="Bitpattern of ISCC-BODY",
255215
examples=["1110000111111011011111011100010011100011110110111011010010111110"],
@@ -261,25 +221,25 @@ class IsccDetail(BaseModel):
261221
Detailed decomposition of an ISCC
262222
"""
263223

264-
iscc: Optional[Iscc] = None
265-
readable: Optional[str] = Field(
224+
iscc: Iscc | None = None
225+
readable: str | None = Field(
266226
None,
267227
description="Human readable version of ISCC",
268228
examples=[
269229
"ISCC-VIDEO-V0-MSDI-c8a70639eb1167b367a9c3787c65c1e582e2e662f728b4fa42485e3a0a5d2f34"
270230
],
271231
)
272-
multiformat: Optional[str] = Field(
232+
multiformat: str | None = Field(
273233
None,
274234
description="Multiformats representation base64url representation of ISCC",
275235
examples=["uzAFTBsinBjnrEWezZ6nDeHxlweWC4uZi9yi0-kJIXjoKXS80"],
276236
)
277-
decomposed: Optional[str] = Field(
237+
decomposed: str | None = Field(
278238
None,
279239
description="ISCC decomomposed into a dash seperated secquence of ISCC-UNITs",
280240
examples=["AAA4RJYGHHVRCZ5T-CMAWPKODPB6GLQPF-GAAYFYXGML3SRNH2-IAAUESC6HIFF2LZU"],
281241
)
282-
units: Optional[List[Unit]] = Field(
242+
units: list[Unit] | None = Field(
283243
None, description="Different representations of the individial units of the ISCC"
284244
)
285245

iscc_web/asgi.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""ASGI entrypoint for uvicorn dev server."""
2+
23
from iscc_web.main import app
34

45
application = app

iscc_web/vite.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from typing import Optional
77
from iscc_web.options import opts
88

9-
109
PROJECT_DIR = pathlib.Path(__file__).parent.parent
1110

1211
VITE_DEV_MODE = opts.environment == "development"

0 commit comments

Comments
 (0)