Skip to content

Commit d1f88bc

Browse files
authored
Merge pull request #24 from heliocastro/feat/scanner_result
feat(scanner): Add scan result parser
2 parents 45f9f81 + be13bc8 commit d1f88bc

35 files changed

+1566
-122
lines changed

README.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,28 @@
11
# Python-Ort
22

3-
Python-Ort is a pydantic based library to serialize OSS Review Toolkit generated reports using the default models.
3+
Python-Ort is a pydantic v2 based library to serialize [OSS Review Toolkit](https://oss-review-toolkit.org/ort/) generated reports using the default models.
4+
5+
## Install
6+
7+
```bash
8+
pip install python-ort
9+
```
10+
11+
## Simple usage example based on a report in yml format:
12+
13+
```python
14+
from pprint import pprint
15+
from pathlib import Path
16+
from pydantic import ValidationError
17+
18+
from ort import OrtResult, ort_yaml_load
19+
20+
21+
try:
22+
with Path("some-result.yml").open() as fd:
23+
data = ort_yaml_load(fd)
24+
parsed = OrtResult(**data)
25+
pprint(parsed)
26+
except ValidationError as e:
27+
print(e)
28+
```

prek.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ hooks = [
2222

2323
[[repos]]
2424
repo = "https://github.com/astral-sh/ruff-pre-commit"
25-
rev = "v0.15.4"
25+
rev = "v0.15.6"
2626
hooks = [
2727
{
2828
id = "ruff",
@@ -43,21 +43,21 @@ hooks = [
4343

4444
[[repos]]
4545
repo = "https://github.com/astral-sh/uv-pre-commit"
46-
rev = "0.10.8"
46+
rev = "0.10.9"
4747
hooks = [
4848
{ id = "uv-lock" }
4949
]
5050

5151
[[repos]]
5252
repo = "https://github.com/codespell-project/codespell"
53-
rev = "v2.4.1"
53+
rev = "v2.4.2"
5454
hooks = [
5555
{ id = "codespell" }
5656
]
5757

5858
[[repos]]
5959
repo = "https://github.com/allganize/ty-pre-commit"
60-
rev = "v0.0.20"
60+
rev = "v0.0.22"
6161
hooks = [
6262
{
6363
id = "ty-check",
@@ -72,6 +72,7 @@ hooks = [
7272
"packageurl-python",
7373
"click",
7474
"rich",
75+
"license-expression",
7576
]
7677
}
7778
]

pyproject.toml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ build-backend = "uv_build"
44

55
[project]
66
name = "python-ort"
7-
version = "0.7.0"
7+
version = "0.8.0"
88
description = "A Python Ort model serialization library"
99
readme = "README.md"
1010
license = "MIT"
1111
license-files = ["LICENSE"]
1212
requires-python = ">=3.10"
1313
dependencies = [
14+
"license-expression>=30.4.4",
1415
"packageurl-python>=0.17.6",
1516
"pydantic>=2.12.5",
1617
]
@@ -38,8 +39,8 @@ dev = [
3839
"datamodel-code-generator[http]>=0.55.0",
3940
"pytest>=9.0.2",
4041
"rich>=14.3.3",
41-
"ruff>=0.15.5",
42-
"ty>=0.0.21",
42+
"ruff>=0.15.6",
43+
"ty>=0.0.22",
4344
"types-pyyaml>=6.0.12.20250915",
4445
]
4546

@@ -144,9 +145,7 @@ extend-select = [
144145
"S", # bandit
145146
]
146147
ignore = [
147-
'N802', # function name should be lowercase
148148
'SIM105', # Suggest contextlib instead of try/except with pass
149-
'A004', # Python shadow builtins
150149
]
151150
# Unlike Flake8, default to a complexity level of 10.
152151
mccabe.max-complexity = 10

src/ort/models/base_run.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
# SPDX-FileCopyrightText: 2025 Helio Chissini de Castro <heliocastro@gmail.com>
1+
# SPDX-FileCopyrightText: 2025 Helio Chissini de Castro <dev@heliocastro.info>
2+
# # SPDX-FileCopyrightText: 2026 CARIAD SE
23
# SPDX-License-Identifier: MIT
34

45
from datetime import datetime
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <dev@heliocastro.info>
2+
# SPDX-FileCopyrightText: 2026 CARIAD SE
3+
# SPDX-License-Identifier: MIT
4+
5+
6+
from pydantic import BaseModel, ConfigDict, Field
7+
8+
from .file_storage_configuration import FileStorageConfiguration
9+
from .scan_storage_configuration import PostgresStorageConfiguration
10+
11+
12+
class FileArchiverConfiguration(BaseModel):
13+
"""
14+
The configuration model for a FileArchiver.
15+
"""
16+
17+
model_config = ConfigDict(
18+
extra="forbid",
19+
)
20+
21+
enabled: bool = Field(
22+
default=True,
23+
description="Toggle to enable or disable the file archiver functionality altogether.",
24+
)
25+
file_storage: FileStorageConfiguration | None = Field(
26+
default=None,
27+
description="Configuration of the FileStorage used for archiving the files.",
28+
)
29+
postgres_storage: PostgresStorageConfiguration | None = Field(
30+
default=None,
31+
description="Configuration of the PostgresProvenanceFileStorage used for archiving the files.",
32+
)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <dev@heliocastro.info>
2+
# SPDX-FileCopyrightText: 2026 CARIAD SE
3+
# SPDX-License-Identifier: MIT
4+
5+
6+
from pydantic import BaseModel, ConfigDict, Field
7+
8+
from .file_storage_configuration import FileStorageConfiguration
9+
from .scan_storage_configuration import PostgresStorageConfiguration
10+
11+
12+
class FileListStorageConfiguration(BaseModel):
13+
"""
14+
Configuration for the storage backends used for persisting file lists.
15+
"""
16+
17+
model_config = ConfigDict(extra="forbid")
18+
19+
file_storage: FileStorageConfiguration | None = Field(
20+
default=None,
21+
description=("Configuration of the FileStorage used for storing the file lists."),
22+
)
23+
postgres_storage: PostgresStorageConfiguration | None = Field(
24+
default=None,
25+
description="Configuration of the PostgresProvenanceFileStorage used for storing the file lists.",
26+
)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <dev@heliocastro.info>
2+
# SPDX-FileCopyrightText: 2026 CARIAD SE
3+
# SPDX-License-Identifier: MIT
4+
5+
6+
from pydantic import BaseModel, ConfigDict, Field
7+
8+
from .http_file_storage_configuration import HttpFileStorageConfiguration
9+
from .local_file_storage_configuration import LocalFileStorageConfiguration
10+
from .s3_file_storage_configuration import S3FileStorageConfiguration
11+
12+
13+
class FileStorageConfiguration(BaseModel):
14+
"""
15+
The configuration model for a FileStorage. Only one of the storage options
16+
can be configured.
17+
"""
18+
19+
model_config = ConfigDict(
20+
extra="forbid",
21+
)
22+
23+
http_file_storage: HttpFileStorageConfiguration | None = Field(
24+
default=None,
25+
description="The configuration of a HttpFileStorage.",
26+
)
27+
local_file_storage: LocalFileStorageConfiguration | None = Field(
28+
default=None,
29+
description="The configuration of a LocalFileStorage.",
30+
)
31+
s3_file_storage: S3FileStorageConfiguration | None = Field(
32+
default=None,
33+
description="The configuration of a S3FileStorage.",
34+
)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <dev@heliocastro.info>
2+
# SPDX-FileCopyrightText: 2026 CARIAD SE
3+
# SPDX-License-Identifier: MIT
4+
5+
from pydantic import BaseModel, ConfigDict, Field
6+
7+
8+
class HttpFileStorageConfiguration(BaseModel):
9+
"""
10+
Configuration for HTTP-based file storage.
11+
"""
12+
13+
url: str = Field(
14+
description='The URL of the HTTP server, e.g. "https://example.com/storage".',
15+
)
16+
query: str = Field(
17+
default="",
18+
description='Query string appended to the URL and path. Can contain auth data, e.g. "?user=standard&pwd=123".',
19+
)
20+
headers: dict[str, str] = Field(
21+
default_factory=dict,
22+
description="Custom headers added to all HTTP requests. Values may contain credentials.",
23+
)
24+
25+
model_config = ConfigDict(extra="forbid")

src/ort/models/config/license_finding_curation_reason.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
# SPDX-License-Identifier: MIT
44

55

6-
from enum import Enum
6+
from ...utils.validated_enum import ValidatedIntEnum
77

88

9-
class LicenseFindingCurationReason(Enum):
9+
class LicenseFindingCurationReason(ValidatedIntEnum):
1010
"""
1111
A curation for a license finding. Use it to correct a license finding or to add a license that was not
1212
previously detected.
@@ -20,9 +20,9 @@ class LicenseFindingCurationReason(Enum):
2020
REFERENCE: The findings reference a file or URL, e.g. SEE LICENSE IN LICENSE or https://jquery.org/license/.
2121
"""
2222

23-
CODE = "CODE"
24-
DATA_OF = "DATA_OF"
25-
DOCUMENTATION_OF = "DOCUMENTATION_OF"
26-
INCORRECT = "INCORRECT"
27-
NOT_DETECTED = "NOT_DETECTED"
28-
REFERENCE = "REFERENCE"
23+
CODE = 1
24+
DATA_OF = 2
25+
DOCUMENTATION_OF = 3
26+
INCORRECT = 4
27+
NOT_DETECTED = 5
28+
REFERENCE = 6
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <dev@heliocastro.info>
2+
# SPDX-FileCopyrightText: 2026 CARIAD SE
3+
# SPDX-License-Identifier: MIT
4+
5+
from pydantic import BaseModel, ConfigDict, Field
6+
7+
8+
class LocalFileStorageConfiguration(BaseModel):
9+
"""
10+
A class to hold the configuration for using local files as a storage.
11+
"""
12+
13+
model_config = ConfigDict(extra="forbid")
14+
15+
directory: str = Field(
16+
...,
17+
description="The directory to use as a storage root.",
18+
)
19+
compression: bool = Field(
20+
default=True,
21+
description="Whether to use compression for storing files or not. Defaults to true.",
22+
)

0 commit comments

Comments
 (0)