Skip to content

Commit 4f3d4fc

Browse files
committed
feat(purl): Creta a pydantic safe type from PackageUrl
The upstream packageurl python library is not designed to modern python solutions, exposing ClassVar and adding expectations that __future__ imports will always be respected. Signed-off-by: Helio Chissini de Castro <dev@heliocastro.info>
1 parent 39e4ffb commit 4f3d4fc

5 files changed

Lines changed: 54 additions & 4 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ license = "MIT"
1111
license-files = ["LICENSE"]
1212
requires-python = ">=3.10"
1313
dependencies = [
14+
"packageurl-python>=0.17.6",
1415
"pydantic>=2.12.5",
1516
]
1617
classifiers = [

src/ort/models/config/snippet/snippet_choice.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from pydantic import BaseModel, ConfigDict, Field
55

6+
from ....types.purl_type import PurlType
67
from ...text_location import TextLocation
78
from .snippet_choice_reason import SnippetChoiceReason
89

@@ -29,7 +30,7 @@ class Choice(BaseModel):
2930
model_config = ConfigDict(
3031
extra="forbid",
3132
)
32-
purl: str = Field(
33+
purl: PurlType = Field(
3334
...,
3435
description="The purl of the snippet chosen by this snippet choice."
3536
"If [reason] is [SnippetChoiceReason.NO_RELEVANT_FINDING], it is null.",
@@ -52,5 +53,11 @@ class SnippetChoice(BaseModel):
5253
model_config = ConfigDict(
5354
extra="forbid",
5455
)
55-
given: Given = Field(..., description="The source file criteria for which the snippet choice is made.")
56-
choice: Choice = Field(..., description="The snippet criteria to make the snippet choice.")
56+
given: Given = Field(
57+
...,
58+
description="The source file criteria for which the snippet choice is made.",
59+
)
60+
choice: Choice = Field(
61+
...,
62+
description="The snippet criteria to make the snippet choice.",
63+
)

src/ort/types/__init__.py

Whitespace-only changes.

src/ort/types/purl_type.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <heliocastro@gmail.com>
2+
# SPDX-License-Identifier: MIT
3+
4+
from packageurl import PackageURL
5+
from pydantic import GetCoreSchemaHandler
6+
from pydantic_core import core_schema
7+
8+
9+
class PurlType:
10+
@classmethod
11+
def __get_pydantic_core_schema__(cls, source_type, handler: GetCoreSchemaHandler):
12+
return core_schema.no_info_after_validator_function(
13+
cls.validate,
14+
core_schema.str_schema(),
15+
serialization=core_schema.plain_serializer_function_ser_schema(
16+
cls.serialize,
17+
return_schema=core_schema.str_schema(),
18+
),
19+
)
20+
21+
@staticmethod
22+
def validate(value: str) -> PackageURL:
23+
if isinstance(value, PackageURL):
24+
return value
25+
return PackageURL.from_string(value)
26+
27+
@staticmethod
28+
def serialize(value: PackageURL) -> str:
29+
return str(value)

uv.lock

Lines changed: 14 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)