python-ort 0.7.0__tar.gz → 0.8.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. {python_ort-0.7.0 → python_ort-0.8.0}/PKG-INFO +28 -2
  2. python_ort-0.8.0/README.md +28 -0
  3. {python_ort-0.7.0 → python_ort-0.8.0}/pyproject.toml +4 -5
  4. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/base_run.py +2 -1
  5. python_ort-0.8.0/src/ort/models/config/file_archiver_configuration.py +32 -0
  6. python_ort-0.8.0/src/ort/models/config/file_list_storage_configuration.py +26 -0
  7. python_ort-0.8.0/src/ort/models/config/file_storage_configuration.py +34 -0
  8. python_ort-0.8.0/src/ort/models/config/http_file_storage_configuration.py +25 -0
  9. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/license_finding_curation_reason.py +8 -8
  10. python_ort-0.8.0/src/ort/models/config/local_file_storage_configuration.py +22 -0
  11. python_ort-0.8.0/src/ort/models/config/postgres_connection.py +97 -0
  12. python_ort-0.8.0/src/ort/models/config/provenance_storage_configuration.py +26 -0
  13. python_ort-0.8.0/src/ort/models/config/s3_file_storage_configuration.py +42 -0
  14. python_ort-0.8.0/src/ort/models/config/scan_storage_configuration.py +84 -0
  15. python_ort-0.8.0/src/ort/models/config/scanner_configuration.py +93 -0
  16. python_ort-0.8.0/src/ort/models/copyright_finding.py +23 -0
  17. python_ort-0.8.0/src/ort/models/file_list.py +55 -0
  18. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/issue.py +8 -0
  19. python_ort-0.8.0/src/ort/models/license_finding.py +45 -0
  20. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/ort_result.py +9 -2
  21. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/provenance.py +48 -26
  22. python_ort-0.8.0/src/ort/models/provenance_resolution_result.py +61 -0
  23. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/resolutions.py +21 -20
  24. python_ort-0.8.0/src/ort/models/scan_result.py +47 -0
  25. python_ort-0.8.0/src/ort/models/scan_summary.py +52 -0
  26. python_ort-0.8.0/src/ort/models/scanner_details.py +27 -0
  27. python_ort-0.8.0/src/ort/models/scanner_run.py +52 -0
  28. python_ort-0.8.0/src/ort/models/snippet.py +72 -0
  29. python_ort-0.8.0/src/ort/models/snippet_finding.py +39 -0
  30. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/source_code_origin.py +4 -4
  31. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/text_location.py +8 -0
  32. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/vcstype.py +1 -1
  33. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/utils/yaml_loader.py +2 -6
  34. python_ort-0.7.0/README.md +0 -3
  35. {python_ort-0.7.0 → python_ort-0.8.0}/LICENSE +0 -0
  36. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/__init__.py +0 -0
  37. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/__init__.py +0 -0
  38. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/advisor_capability.py +0 -0
  39. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/advisor_details.py +0 -0
  40. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/advisor_result.py +0 -0
  41. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/advisor_run.py +0 -0
  42. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/advisor_summary.py +0 -0
  43. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/analyzer_result.py +0 -0
  44. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/analyzer_run.py +0 -0
  45. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/__init__.py +0 -0
  46. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/advisor_configuration.py +0 -0
  47. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/analyzer_configuration.py +0 -0
  48. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/curations.py +0 -0
  49. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/excludes.py +0 -0
  50. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/includes.py +0 -0
  51. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/issue_resolution.py +0 -0
  52. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/issue_resolution_reason.py +0 -0
  53. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/license_choice.py +0 -0
  54. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/license_finding_curation.py +0 -0
  55. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/package_configuration.py +0 -0
  56. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/package_manager_configuration.py +0 -0
  57. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/path_exclude.py +0 -0
  58. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/path_exclude_reason.py +0 -0
  59. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/path_include.py +0 -0
  60. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/path_include_reason.py +0 -0
  61. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/repository_analyzer_configuration.py +0 -0
  62. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/repository_configuration.py +0 -0
  63. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/resolutions.py +0 -0
  64. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/rule_violation_reason.py +0 -0
  65. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/rule_violation_resolution.py +0 -0
  66. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/scope_exclude.py +0 -0
  67. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/scope_exclude_reason.py +0 -0
  68. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/snippet/__init__.py +0 -0
  69. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/snippet/snippet_choice.py +0 -0
  70. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/snippet/snippet_choice_reason.py +0 -0
  71. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/snippet/snippet_choices.py +0 -0
  72. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/snippet/snippet_provenance.py +0 -0
  73. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/vcsmatcher.py +0 -0
  74. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/vulnerability_resolution.py +0 -0
  75. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/config/vulnerability_resolution_reason.py +0 -0
  76. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/defect.py +0 -0
  77. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/dependency_graph.py +0 -0
  78. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/dependency_graph_edge.py +0 -0
  79. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/dependency_graph_node.py +0 -0
  80. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/dependency_reference.py +0 -0
  81. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/evaluator_run.py +0 -0
  82. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/hash.py +0 -0
  83. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/hash_algorithm.py +0 -0
  84. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/identifier.py +0 -0
  85. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/license_source.py +0 -0
  86. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/package.py +0 -0
  87. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/package_curation.py +0 -0
  88. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/package_curation_data.py +0 -0
  89. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/package_linkage.py +0 -0
  90. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/package_reference.py +0 -0
  91. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/project.py +0 -0
  92. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/remote_artifact.py +0 -0
  93. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/repository.py +0 -0
  94. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/root_dependency_index.py +0 -0
  95. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/rule_violation.py +0 -0
  96. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/scope.py +0 -0
  97. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/severity.py +0 -0
  98. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/vcsinfo.py +0 -0
  99. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/vcsinfo_curation_data.py +0 -0
  100. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/vulnerabilities/__init__.py +0 -0
  101. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/vulnerabilities/cvss2_rating.py +0 -0
  102. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/vulnerabilities/cvss3_rating.py +0 -0
  103. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/vulnerabilities/cvss4_rating.py +0 -0
  104. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/vulnerabilities/vulnerability.py +0 -0
  105. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/models/vulnerabilities/vulnerability_reference.py +0 -0
  106. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/severity.py +0 -0
  107. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/types/__init__.py +0 -0
  108. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/types/purl_type.py +0 -0
  109. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/utils/__init__.py +0 -0
  110. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/utils/environment.py +0 -0
  111. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/utils/processed_declared_license.py +0 -0
  112. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/utils/spdx/__init__.py +0 -0
  113. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/utils/spdx/spdx_expression.py +0 -0
  114. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/utils/spdx/spdx_license_choice.py +0 -0
  115. {python_ort-0.7.0 → python_ort-0.8.0}/src/ort/utils/validated_enum.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-ort
3
- Version: 0.7.0
3
+ Version: 0.8.0
4
4
  Summary: A Python Ort model serialization library
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -13,6 +13,7 @@ Classifier: Programming Language :: Python :: 3.12
13
13
  Classifier: Programming Language :: Python :: 3.13
14
14
  Classifier: Programming Language :: Python :: 3.14
15
15
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Requires-Dist: license-expression>=30.4.4
16
17
  Requires-Dist: packageurl-python>=0.17.6
17
18
  Requires-Dist: pydantic>=2.12.5
18
19
  Requires-Python: >=3.10
@@ -20,4 +21,29 @@ Description-Content-Type: text/markdown
20
21
 
21
22
  # Python-Ort
22
23
 
23
- Python-Ort is a pydantic based library to serialize OSS Review Toolkit generated reports using the default models.
24
+ 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.
25
+
26
+ ## Install
27
+
28
+ ```bash
29
+ pip install python-ort
30
+ ```
31
+
32
+ ## Simple usage example based on a report in yml format:
33
+
34
+ ```python
35
+ from pprint import pprint
36
+ from pathlib import Path
37
+ from pydantic import ValidationError
38
+
39
+ from ort import OrtResult, ort_yaml_load
40
+
41
+
42
+ try:
43
+ with Path("some-result.yml").open() as fd:
44
+ data = ort_yaml_load(fd)
45
+ parsed = OrtResult(**data)
46
+ pprint(parsed)
47
+ except ValidationError as e:
48
+ print(e)
49
+ ```
@@ -0,0 +1,28 @@
1
+ # Python-Ort
2
+
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
+ ```
@@ -4,13 +4,14 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "python-ort"
7
- version = "0.7.0"
7
+ version = "0.8.0"
8
8
  description = "A Python Ort model serialization library"
9
9
  readme = "README.md"
10
10
  license = "MIT"
11
11
  license-files = ["LICENSE"]
12
12
  requires-python = ">=3.10"
13
13
  dependencies = [
14
+ "license-expression>=30.4.4",
14
15
  "packageurl-python>=0.17.6",
15
16
  "pydantic>=2.12.5",
16
17
  ]
@@ -38,8 +39,8 @@ dev = [
38
39
  "datamodel-code-generator[http]>=0.55.0",
39
40
  "pytest>=9.0.2",
40
41
  "rich>=14.3.3",
41
- "ruff>=0.15.5",
42
- "ty>=0.0.21",
42
+ "ruff>=0.15.6",
43
+ "ty>=0.0.22",
43
44
  "types-pyyaml>=6.0.12.20250915",
44
45
  ]
45
46
 
@@ -144,9 +145,7 @@ extend-select = [
144
145
  "S", # bandit
145
146
  ]
146
147
  ignore = [
147
- 'N802', # function name should be lowercase
148
148
  'SIM105', # Suggest contextlib instead of try/except with pass
149
- 'A004', # Python shadow builtins
150
149
  ]
151
150
  # Unlike Flake8, default to a complexity level of 10.
152
151
  mccabe.max-complexity = 10
@@ -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
2
3
  # SPDX-License-Identifier: MIT
3
4
 
4
5
  from datetime import datetime
@@ -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
+ )
@@ -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
+ )
@@ -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
+ )
@@ -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")
@@ -3,10 +3,10 @@
3
3
  # SPDX-License-Identifier: MIT
4
4
 
5
5
 
6
- from enum import Enum
6
+ from ...utils.validated_enum import ValidatedIntEnum
7
7
 
8
8
 
9
- class LicenseFindingCurationReason(Enum):
9
+ class LicenseFindingCurationReason(ValidatedIntEnum):
10
10
  """
11
11
  A curation for a license finding. Use it to correct a license finding or to add a license that was not
12
12
  previously detected.
@@ -20,9 +20,9 @@ class LicenseFindingCurationReason(Enum):
20
20
  REFERENCE: The findings reference a file or URL, e.g. SEE LICENSE IN LICENSE or https://jquery.org/license/.
21
21
  """
22
22
 
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
@@ -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,0 +1,97 @@
1
+ # SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <heliocastro@gmail.com>
2
+ # SPDX-FileCopyrightText: 2026 CARIAD SE
3
+ # SPDX-License-Identifier: MIT
4
+
5
+
6
+ from pydantic import BaseModel, ConfigDict, Field
7
+
8
+
9
+ class PostgresConnection(BaseModel):
10
+ """
11
+ PostgreSQL connection configuration and HikariCP pool settings.
12
+ """
13
+
14
+ model_config = ConfigDict(extra="forbid")
15
+
16
+ url: str = Field(
17
+ ...,
18
+ description=("The database URL in JDBC format."),
19
+ )
20
+
21
+ provider_schema: str = Field(
22
+ default="public",
23
+ alias="schema",
24
+ description=("The name of the database to use."),
25
+ )
26
+
27
+ username: str = Field(
28
+ ...,
29
+ description=("The username to use for authentication."),
30
+ )
31
+
32
+ password: str = Field(
33
+ default_factory=str,
34
+ description=("The password to use for authentication."),
35
+ )
36
+
37
+ sslmode: str = Field(
38
+ default="verify-full",
39
+ description='The SSL mode to use, one of "disable", "allow", "prefer", "require", '
40
+ '"verify-ca" or "verify-full". See: '
41
+ "https://jdbc.postgresql.org/documentation/ssl/#configuring-the-client",
42
+ )
43
+
44
+ sslcert: str | None = Field(
45
+ None,
46
+ description="The full path of the certificate file. See: https://jdbc.postgresql.org/documentation/head/connect.html",
47
+ )
48
+
49
+ sslkey: str | None = Field(
50
+ None,
51
+ description="The full path of the key file. See: https://jdbc.postgresql.org/documentation/head/connect.html",
52
+ )
53
+
54
+ sslrootcert: str | None = Field(
55
+ None,
56
+ description="The full path of the root certificate file. See: "
57
+ "https://jdbc.postgresql.org/documentation/head/connect.html",
58
+ )
59
+
60
+ connection_timeout: int | None = Field(
61
+ None,
62
+ description="Maximum milliseconds to wait for connections from the pool. See: "
63
+ "https://github.com/brettwooldridge/HikariCP#frequently-used",
64
+ )
65
+
66
+ idle_timeout: int | None = Field(
67
+ None,
68
+ description="Maximum milliseconds a connection may sit idle in the pool. Requires "
69
+ "minimum_idle < maximum_pool_size. See: "
70
+ "https://github.com/brettwooldridge/HikariCP#frequently-used",
71
+ )
72
+
73
+ keepalive_time: int | None = Field(
74
+ None,
75
+ description="Frequency in milliseconds that the pool will keep an idle connection "
76
+ "alive. Must be lower than max_lifetime. See: "
77
+ "https://github.com/brettwooldridge/HikariCP#frequently-used",
78
+ )
79
+
80
+ max_lifetime: int | None = Field(
81
+ None,
82
+ description=(
83
+ "Maximum lifetime of a connection in milliseconds. See: "
84
+ "https://github.com/brettwooldridge/HikariCP#frequently-used"
85
+ ),
86
+ )
87
+
88
+ maximum_pool_size: int | None = Field(
89
+ None,
90
+ description="Maximum size of the connection pool. See: https://github.com/brettwooldridge/HikariCP#frequently-used",
91
+ )
92
+
93
+ minimum_idle: int | None = Field(
94
+ None,
95
+ description="Minimum number of idle connections that the pool tries to maintain. "
96
+ "See: https://github.com/brettwooldridge/HikariCP#frequently-used",
97
+ )
@@ -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 ProvenanceStorageConfiguration(BaseModel):
13
+ """
14
+ Configuration of the storage to use for provenance information.
15
+ """
16
+
17
+ model_config = ConfigDict(extra="forbid")
18
+
19
+ file_storage: FileStorageConfiguration | None = Field(
20
+ default=None,
21
+ description="Configuration of a file storage.",
22
+ )
23
+ postgres_storage: PostgresStorageConfiguration | None = Field(
24
+ default=None,
25
+ description="Configuration of a PostgreSQL storage.",
26
+ )
@@ -0,0 +1,42 @@
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
+
9
+ class S3FileStorageConfiguration(BaseModel):
10
+ """
11
+ A class to hold the configuration for using an AWS S3 bucket as a storage.
12
+ """
13
+
14
+ model_config = ConfigDict(extra="forbid")
15
+
16
+ access_key_id: str | None = Field(
17
+ default=None,
18
+ description="The AWS access key.",
19
+ )
20
+ aws_region: str | None = Field(
21
+ default=None,
22
+ description="The AWS region to be used.",
23
+ )
24
+ bucket_name: str = Field(
25
+ description="The name of the S3 bucket used to store files in.",
26
+ )
27
+ compression: bool = Field(
28
+ default=False,
29
+ description="Whether to use compression for storing files or not.",
30
+ )
31
+ custom_endpoint: str | None = Field(
32
+ default=None,
33
+ description="Custom endpoint to perform AWS API requests.",
34
+ )
35
+ path_style_access: bool = Field(
36
+ default=False,
37
+ description="Whether to enable path style access or not. Required for many non-AWS S3 providers.",
38
+ )
39
+ secret_access_key: str | None = Field(
40
+ default=None,
41
+ description="The AWS secret for the access key.",
42
+ )
@@ -0,0 +1,84 @@
1
+ # SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <heliocastro@gmail.com>
2
+ # SPDX-FileCopyrightText: 2026 CARIAD SE
3
+ # SPDX-License-Identifier: MIT
4
+
5
+
6
+ from pydantic import BaseModel, ConfigDict, Field, model_validator
7
+
8
+ from ...utils.validated_enum import ValidatedIntEnum
9
+ from .file_storage_configuration import FileStorageConfiguration
10
+ from .postgres_connection import PostgresConnection
11
+
12
+
13
+ class StorageType(ValidatedIntEnum):
14
+ """
15
+ An enum to describe different types of storages.
16
+
17
+ Properties:
18
+ PACKAGE_BASED: A storage that stores scan results by [Package].
19
+ PROVENANCE_BASED: A storage that stores scan results by [Provenance].
20
+ """
21
+
22
+ PACKAGE_BASED = 1
23
+ PROVENANCE_BASED = 2
24
+
25
+
26
+ class ScanStorageConfiguration(BaseModel):
27
+ """
28
+ Root of a class hierarchy for configuration classes for scan storage
29
+ implementations.
30
+
31
+ Based on this hierarchy, it is possible to have multiple different scan
32
+ storages enabled and to configure them dynamically.
33
+ """
34
+
35
+ model_config = ConfigDict(extra="allow")
36
+
37
+ @model_validator(mode="before")
38
+ @classmethod
39
+ def validate_provenance(cls, v):
40
+ if not isinstance(v, dict):
41
+ raise ValueError("Config must be a dictionary.")
42
+ # Return the dict as-is; ScanStorageConfiguration with extra="allow"
43
+ # will store all fields without needing to instantiate subclasses.
44
+ return v
45
+
46
+
47
+ class ClearlyDefinedStorageConfiguration(ScanStorageConfiguration):
48
+ """
49
+ The configuration model of a storage based on ClearlyDefined.
50
+ """
51
+
52
+ server_url: str = Field(
53
+ description="The URL of the ClearlyDefined server.",
54
+ )
55
+
56
+
57
+ class FileBasedStorageConfiguration(ScanStorageConfiguration):
58
+ """
59
+ The configuration model of a file based storage.
60
+ """
61
+
62
+ backend: FileStorageConfiguration = Field(
63
+ description="The configuration of the FileStorage used to store the files."
64
+ )
65
+ ort_type: StorageType = Field(
66
+ alias="type",
67
+ default="PROVENANCE_BASED",
68
+ description=("The way that scan results are stored, defaults to StorageType.PROVENANCE_BASED."),
69
+ )
70
+
71
+
72
+ class PostgresStorageConfiguration(ScanStorageConfiguration):
73
+ """
74
+ A class to hold the configuration for using Postgres as a storage.
75
+ """
76
+
77
+ connection: PostgresConnection = Field(
78
+ description="The configuration of the PostgreSQL database.",
79
+ )
80
+ ort_type: StorageType = Field(
81
+ alias="type",
82
+ default="PROVENANCE_BASED",
83
+ description=("The way that scan results are stored, defaults to StorageType.PROVENANCE_BASED."),
84
+ )
@@ -0,0 +1,93 @@
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 typing import Any
7
+
8
+ from pydantic import BaseModel, ConfigDict, Field
9
+
10
+ from .file_archiver_configuration import FileArchiverConfiguration
11
+ from .file_list_storage_configuration import FileListStorageConfiguration
12
+ from .provenance_storage_configuration import ProvenanceStorageConfiguration
13
+ from .scan_storage_configuration import ScanStorageConfiguration
14
+
15
+
16
+ class ScannerConfiguration(BaseModel):
17
+ """
18
+ The configuration model of the scanner.
19
+
20
+ This is deserialized from "config.yml" as part of OrtConfiguration and
21
+ (de-)serialized as part of org.ossreviewtoolkit.model.OrtResult.
22
+ """
23
+
24
+ model_config = ConfigDict(extra="forbid")
25
+
26
+ skip_concluded: bool = Field(
27
+ default=False,
28
+ description="Skip packages with concluded license and authors (for copyrights) and use only declared info.",
29
+ )
30
+
31
+ skip_excluded: bool = Field(
32
+ default=False,
33
+ description="Control whether excluded scopes and paths are skipped during the scan.",
34
+ )
35
+
36
+ include_files_without_findings: bool = Field(
37
+ default=False,
38
+ description="Whether the scanner should add files without license to the scanner results.",
39
+ )
40
+
41
+ archive: "FileArchiverConfiguration | None" = Field(
42
+ default=None,
43
+ description="Configuration of a FileArchiver that archives selected scanned files in external storage.",
44
+ )
45
+
46
+ # Use empty dict instead of upstream defaults as this class is not intended to provide defaults as upstream
47
+ # Kotlin counterpart, but just do proper parsing of existing pre created result
48
+ detected_license_mapping: dict[str, str] = Field(
49
+ default_factory=dict,
50
+ description="Mappings from scanner-returned licenses to valid SPDX licenses; only applied to new scans.",
51
+ )
52
+
53
+ file_list_storage: FileListStorageConfiguration | None = Field(
54
+ default=None,
55
+ description="The storage to store the file lists by provenance.",
56
+ )
57
+
58
+ scanners: dict[str, Any] | None = Field(
59
+ default=None,
60
+ description="Scanner-specific configuration options. The key needs to match the name of the scanner"
61
+ "class, e.g. 'ScanCode' for the ScanCode wrapper. See the documentation of the scanner for available options.",
62
+ )
63
+
64
+ storages: dict[str, ScanStorageConfiguration] | None = Field(
65
+ default=None,
66
+ description="A map with the configurations of the scan result storages available."
67
+ "Based on this information the actual storages are created."
68
+ "Storages can be configured as readers or writers of scan results. Having "
69
+ "this map makes it possible for storage instances to act in both roles without having to duplicate "
70
+ "configuration.",
71
+ )
72
+
73
+ storage_readers: list[str] | None = Field(
74
+ default=None,
75
+ description="A list with the IDs of scan storages that are queried for existing scan results."
76
+ "The strings in this list must match keys in the storages map.",
77
+ )
78
+
79
+ storage_writers: list[str] | None = Field(
80
+ default=None,
81
+ description="A list with the IDs of scan storages that are called to persist scan results."
82
+ "The strings in this list must match keys in the [storages] map.",
83
+ )
84
+
85
+ ignore_patterns: list[str] = Field(
86
+ default_factory=list,
87
+ description="A list of glob expressions that match file paths which are to be excluded from scan results.",
88
+ )
89
+
90
+ provenance_storage: ProvenanceStorageConfiguration | None = Field(
91
+ default=None,
92
+ description="Configuration of the storage for provenance information.",
93
+ )
@@ -0,0 +1,23 @@
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 .text_location import TextLocation
9
+
10
+
11
+ class CopyrightFinding(BaseModel):
12
+ """
13
+ A class representing a single copyright finding.
14
+ """
15
+
16
+ model_config = ConfigDict(extra="forbid")
17
+
18
+ statement: str = Field(
19
+ description="The copyright statement.",
20
+ )
21
+ location: TextLocation = Field(
22
+ description="The text location where the copyright statement was found.",
23
+ )