python-ort 0.5.0__tar.gz → 0.6.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 (62) hide show
  1. {python_ort-0.5.0 → python_ort-0.6.0}/PKG-INFO +1 -1
  2. {python_ort-0.5.0 → python_ort-0.6.0}/pyproject.toml +5 -7
  3. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/__init__.py +2 -2
  4. python_ort-0.6.0/src/ort/models/__init__.py +64 -0
  5. python_ort-0.6.0/src/ort/models/advisor_capability.py +21 -0
  6. python_ort-0.6.0/src/ort/models/advisor_details.py +41 -0
  7. python_ort-0.6.0/src/ort/models/advisor_result.py +42 -0
  8. python_ort-0.6.0/src/ort/models/advisor_run.py +39 -0
  9. python_ort-0.6.0/src/ort/models/advisor_summary.py +38 -0
  10. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/analyzer_result.py +5 -5
  11. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/analyzer_run.py +1 -1
  12. python_ort-0.6.0/src/ort/models/config/advisor_configuration.py +28 -0
  13. python_ort-0.6.0/src/ort/models/defect.py +87 -0
  14. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/dependency_graph.py +5 -5
  15. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/dependency_graph_node.py +13 -3
  16. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/dependency_reference.py +2 -2
  17. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/hash.py +1 -1
  18. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/ort_result.py +14 -2
  19. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/package.py +5 -4
  20. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/package_curation_data.py +4 -9
  21. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/package_linkage.py +6 -6
  22. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/package_reference.py +2 -2
  23. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/project.py +4 -3
  24. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/remote_artifact.py +4 -2
  25. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/repository.py +3 -3
  26. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/repository_configuration.py +1 -1
  27. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/scope.py +1 -1
  28. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/vcsinfo.py +3 -2
  29. python_ort-0.6.0/src/ort/models/vulnerabilities/__init__.py +8 -0
  30. python_ort-0.6.0/src/ort/models/vulnerabilities/cvss2_rating.py +39 -0
  31. python_ort-0.6.0/src/ort/models/vulnerabilities/cvss3_rating.py +45 -0
  32. python_ort-0.6.0/src/ort/models/vulnerabilities/cvss4_rating.py +45 -0
  33. python_ort-0.6.0/src/ort/models/vulnerabilities/vulnerability.py +39 -0
  34. python_ort-0.6.0/src/ort/models/vulnerabilities/vulnerability_reference.py +78 -0
  35. python_ort-0.5.0/src/ort/models/__init__.py +0 -10
  36. {python_ort-0.5.0 → python_ort-0.6.0}/LICENSE +0 -0
  37. {python_ort-0.5.0 → python_ort-0.6.0}/README.md +0 -0
  38. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/config/analyzer_configuration.py +0 -0
  39. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/config/curations.py +0 -0
  40. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/config/license_finding_curation.py +0 -0
  41. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/config/license_finding_curation_reason.py +0 -0
  42. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/config/package_configuration.py +0 -0
  43. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/config/package_manager_configuration.py +0 -0
  44. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/config/path_exclude.py +0 -0
  45. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/config/path_exclude_reason.py +0 -0
  46. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/config/path_include_reason.py +0 -0
  47. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/config/repository_analyzer_configuration.py +0 -0
  48. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/config/vcsmatcher.py +0 -0
  49. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/dependency_graph_edge.py +0 -0
  50. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/hash_algorithm.py +0 -0
  51. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/identifier.py +0 -0
  52. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/issue.py +0 -0
  53. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/package_curation.py +0 -0
  54. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/resolutions.py +0 -0
  55. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/root_dependency_index.py +0 -0
  56. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/source_code_origin.py +0 -0
  57. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/vcsinfo_curation_data.py +0 -0
  58. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/models/vcstype.py +0 -0
  59. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/severity.py +0 -0
  60. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/utils/__init__.py +0 -0
  61. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/utils/environment.py +0 -0
  62. {python_ort-0.5.0 → python_ort-0.6.0}/src/ort/utils/processed_declared_license.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-ort
3
- Version: 0.5.0
3
+ Version: 0.6.0
4
4
  Summary: A Python Ort model serialization library
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "python-ort"
7
- version = "0.5.0"
7
+ version = "0.6.0"
8
8
  description = "A Python Ort model serialization library"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -31,13 +31,11 @@ module-root = "src"
31
31
 
32
32
  [dependency-groups]
33
33
  dev = [
34
- "datamodel-code-generator[http]>=0.53.0",
35
- "pre-commit>=4.5.1",
36
- "pycodestyle>=2.14.0",
37
- "pyrefly>=0.49.0",
34
+ "datamodel-code-generator[http]>=0.54.0",
38
35
  "pytest>=9.0.2",
39
- "rich>=14.2.0",
40
- "ruff>=0.14.14",
36
+ "rich>=14.3.2",
37
+ "ruff>=0.15.1",
38
+ "ty>=0.0.17",
41
39
  "types-pyyaml>=6.0.12.20250915",
42
40
  ]
43
41
 
@@ -4,10 +4,10 @@
4
4
 
5
5
  from ort.models.analyzer_result import AnalyzerResult
6
6
  from ort.models.ort_result import OrtResult
7
- from ort.models.repository_configuration import OrtRepositoryConfiguration
7
+ from ort.models.repository_configuration import RepositoryConfiguration
8
8
 
9
9
  __all__ = [
10
10
  "AnalyzerResult",
11
- "OrtRepositoryConfiguration",
11
+ "RepositoryConfiguration",
12
12
  "OrtResult",
13
13
  ]
@@ -0,0 +1,64 @@
1
+ # SPDX-FileCopyrightText: 2025 Helio Chissini de Castro <heliocastro@gmail.com>
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ from .advisor_capability import AdvisorCapability
5
+ from .advisor_result import AdvisorResult
6
+ from .advisor_run import AdvisorRun
7
+ from .analyzer_result import AnalyzerResult
8
+ from .analyzer_run import AnalyzerRun
9
+ from .dependency_graph import DependencyGraph
10
+ from .dependency_graph_edge import DependencyGraphEdge
11
+ from .dependency_graph_node import DependencyGraphNode
12
+ from .dependency_reference import DependencyReference
13
+ from .hash import Hash
14
+ from .hash_algorithm import HashAlgorithm
15
+ from .identifier import Identifier
16
+ from .issue import Issue
17
+ from .ort_result import OrtResult
18
+ from .package import Package
19
+ from .package_curation import PackageCuration
20
+ from .package_curation_data import PackageCurationData
21
+ from .package_linkage import PackageLinkage
22
+ from .package_reference import PackageReference
23
+ from .project import Project
24
+ from .remote_artifact import RemoteArtifact
25
+ from .repository import Repository
26
+ from .repository_configuration import RepositoryConfiguration
27
+ from .root_dependency_index import RootDependencyIndex
28
+ from .scope import Scope
29
+ from .source_code_origin import SourceCodeOrigin
30
+ from .vcsinfo import VcsInfo
31
+ from .vcsinfo_curation_data import VcsInfoCurationData
32
+ from .vcstype import VcsType
33
+
34
+ __all__ = [
35
+ "AdvisorCapability",
36
+ "AdvisorResult",
37
+ "AdvisorRun",
38
+ "AnalyzerResult",
39
+ "AnalyzerRun",
40
+ "DependencyGraph",
41
+ "DependencyGraphEdge",
42
+ "DependencyGraphNode",
43
+ "DependencyReference",
44
+ "Hash",
45
+ "HashAlgorithm",
46
+ "Identifier",
47
+ "Issue",
48
+ "OrtResult",
49
+ "Package",
50
+ "PackageCuration",
51
+ "PackageCurationData",
52
+ "PackageLinkage",
53
+ "PackageReference",
54
+ "Project",
55
+ "RemoteArtifact",
56
+ "Repository",
57
+ "RepositoryConfiguration",
58
+ "RootDependencyIndex",
59
+ "Scope",
60
+ "SourceCodeOrigin",
61
+ "VcsInfo",
62
+ "VcsInfoCurationData",
63
+ "VcsType",
64
+ ]
@@ -0,0 +1,21 @@
1
+ # SPDX-FileCopyrightText: 2025 Helio Chissini de Castro <heliocastro@gmail.com>
2
+ # SPDX-License-Identifier: MIT
3
+
4
+
5
+ from enum import IntEnum
6
+
7
+
8
+ class AdvisorCapability(IntEnum):
9
+ """
10
+ An enum class that defines the capabilities of a specific advisor implementation.
11
+
12
+ There are multiple types of findings that can be retrieved by an advisor, such as security vulnerabilities or
13
+ defects. An [AdvisorResult] has different fields for the different findings types. This enum corresponds to these
14
+ fields. It allows an advisor implementation to declare, which of these fields it can populate. This information is
15
+ of interest, for instance, when generating reports for specific findings to determine, which advisor may have
16
+ contributed.
17
+
18
+ """
19
+
20
+ DEFECTS = 1
21
+ VULNERABILITIES = 2
@@ -0,0 +1,41 @@
1
+ # SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <heliocastro@gmail.com>
2
+ # SPDX-License-Identifier: MIT
3
+
4
+
5
+ from pydantic import BaseModel, ConfigDict, Field, field_validator
6
+
7
+ from ort.models import AdvisorCapability
8
+
9
+
10
+ class AdvisorDetails(BaseModel):
11
+ """
12
+ Details about the used provider of vulnerability information.
13
+
14
+ """
15
+
16
+ model_config = ConfigDict(
17
+ extra="forbid",
18
+ )
19
+
20
+ name: str = Field(description="The name of the used advisor.")
21
+ capabilities: set[AdvisorCapability] = Field(
22
+ description="The capabilities of the used advisor. This property indicates, which kind of findings"
23
+ "are retrieved by the advisor."
24
+ )
25
+
26
+ @field_validator("capabilities", mode="before")
27
+ @classmethod
28
+ def convert_capability(cls, v):
29
+ def _convert(item):
30
+ if isinstance(item, str):
31
+ try:
32
+ return AdvisorCapability[item]
33
+ except KeyError:
34
+ raise ValueError(f"Invalid capability: {item}")
35
+ return item
36
+
37
+ if isinstance(v, (list, set)):
38
+ return {_convert(item) for item in v}
39
+ if isinstance(v, str):
40
+ return _convert(v)
41
+ return v
@@ -0,0 +1,42 @@
1
+ # SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <heliocastro@gmail.com>
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ from pydantic import BaseModel, ConfigDict, Field
5
+
6
+ from ort.models.vulnerabilities import Vulnerability
7
+
8
+ from .advisor_details import AdvisorDetails
9
+ from .advisor_summary import AdvisorSummary
10
+ from .defect import Defect
11
+
12
+
13
+ class AdvisorResult(BaseModel):
14
+ """
15
+ The result of a specific advisor execution for a single package.
16
+
17
+ Different advisor implementations may produce findings of different types. To reflect this, this class has multiple
18
+ fields for findings of these types. It is up to a concrete advisor, which of these fields it populates.
19
+
20
+ """
21
+
22
+ model_config = ConfigDict(
23
+ extra="forbid",
24
+ )
25
+
26
+ advisor: AdvisorDetails = Field(
27
+ description="Details about the used advisor.",
28
+ )
29
+
30
+ summary: AdvisorSummary = Field(
31
+ description="A summary of the advisor results.",
32
+ )
33
+
34
+ defects: list[Defect] = Field(
35
+ default_factory=list,
36
+ description="The defects.",
37
+ )
38
+
39
+ vulnerabilities: list[Vulnerability] = Field(
40
+ default_factory=list,
41
+ description="The vulnerabilities.",
42
+ )
@@ -0,0 +1,39 @@
1
+ # SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <heliocastro@gmail.com>
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ from datetime import datetime
5
+
6
+ from pydantic import BaseModel, ConfigDict, Field
7
+
8
+ from ort.models import AdvisorResult
9
+ from ort.models.config.advisor_configuration import AdvisorConfiguration
10
+ from ort.utils.environment import Environment
11
+
12
+ from .identifier import Identifier
13
+
14
+
15
+ class AdvisorRun(BaseModel):
16
+ """
17
+ Type alias for a function that allows filtering of [AdvisorResult]s.
18
+
19
+ """
20
+
21
+ model_config = ConfigDict(
22
+ extra="forbid",
23
+ )
24
+ start_time: datetime = Field(
25
+ description="The time the advisor was started.",
26
+ )
27
+ end_time: datetime = Field(
28
+ description="The time the advisor has finished.",
29
+ )
30
+ environment: Environment = Field(
31
+ description="The [Environment] in which the advisor was executed.",
32
+ )
33
+ config: AdvisorConfiguration = Field(
34
+ description="The [AdvisorConfiguration] used for this run.",
35
+ )
36
+ results: dict[Identifier, list[AdvisorResult]] = Field(
37
+ default_factory=dict,
38
+ description="The result of this run.",
39
+ )
@@ -0,0 +1,38 @@
1
+ # SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <heliocastro@gmail.com>
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ from datetime import datetime
5
+
6
+ from pydantic import BaseModel, ConfigDict, Field, field_validator
7
+
8
+ from .issue import Issue
9
+
10
+
11
+ class AdvisorSummary(BaseModel):
12
+ """
13
+ A short summary of the advisor result.
14
+
15
+ """
16
+
17
+ model_config = ConfigDict(
18
+ extra="forbid",
19
+ )
20
+
21
+ start_time: datetime = Field(
22
+ description="The time the advisor started.",
23
+ )
24
+ end_time: datetime = Field(
25
+ description="The time the advisor finished.",
26
+ )
27
+ issues: list[Issue] = Field(
28
+ default_factory=list,
29
+ description="The list of issues that occurred during the advisor run."
30
+ "This property is not serialized if the list is empty to reduce the size of the result file.",
31
+ )
32
+
33
+ @field_validator("start_time", "end_time", mode="before")
34
+ @classmethod
35
+ def transform_date(cls, v):
36
+ if isinstance(v, str):
37
+ return datetime.fromisoformat(v.replace("Z", "+00:00"))
38
+ return v
@@ -4,11 +4,11 @@
4
4
 
5
5
  from pydantic import BaseModel, ConfigDict, Field
6
6
 
7
- from ort.models.dependency_graph import DependencyGraph
8
- from ort.models.identifier import Identifier
9
- from ort.models.issue import Issue
10
- from ort.models.package import Package
11
- from ort.models.project import Project
7
+ from .dependency_graph import DependencyGraph
8
+ from .identifier import Identifier
9
+ from .issue import Issue
10
+ from .package import Package
11
+ from .project import Project
12
12
 
13
13
 
14
14
  class AnalyzerResult(BaseModel):
@@ -5,7 +5,7 @@ from datetime import datetime
5
5
 
6
6
  from pydantic import BaseModel, ConfigDict, Field
7
7
 
8
- from ort.models.analyzer_result import AnalyzerResult
8
+ from ort.models import AnalyzerResult
9
9
  from ort.models.config.analyzer_configuration import AnalyzerConfiguration
10
10
  from ort.utils.environment import Environment
11
11
 
@@ -0,0 +1,28 @@
1
+ # SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <heliocastro@gmail.com>
2
+ # SPDX-License-Identifier: MIT
3
+
4
+
5
+ from typing import Any
6
+
7
+ from pydantic import BaseModel, ConfigDict, Field
8
+
9
+
10
+ class AdvisorConfiguration(BaseModel):
11
+ """
12
+ The configuration model of the advisor. This class is (de-)serialized in the following places:
13
+ - Deserialized from "config.yml" as part of [OrtConfiguration].
14
+ - (De-)Serialized as part of [org.ossreviewtoolkit.model.OrtResult].
15
+ """
16
+
17
+ model_config = ConfigDict(
18
+ extra="forbid",
19
+ )
20
+ skip_excluded: bool = Field(
21
+ default=False,
22
+ description="A flag to control whether excluded scopes and paths should be skipped when giving the advice.",
23
+ )
24
+ advisors: dict[str, Any] | None = Field(
25
+ default=None,
26
+ description="A map with [configuration][PluginConfig] for advice providers using the"
27
+ "[plugin id][PluginDescriptor.id] as key.",
28
+ )
@@ -0,0 +1,87 @@
1
+ # SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <heliocastro@gmail.com>
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ from datetime import datetime
5
+
6
+ from pydantic import AnyUrl, BaseModel, ConfigDict, Field
7
+
8
+
9
+ class Defect(BaseModel):
10
+ """
11
+ A data model for software defects.
12
+
13
+ Instances of this class are created by advisor implementations that retrieve information about
14
+ known defects in packages.
15
+
16
+ """
17
+
18
+ model_config = ConfigDict(
19
+ extra="forbid",
20
+ )
21
+
22
+ id: str = Field(
23
+ description="The (external) ID of this defect. This is a string used by a concrete issue tracker"
24
+ "system to reference this defect, such as a bug ID or ticket number.",
25
+ )
26
+
27
+ url: AnyUrl = Field(
28
+ description="The URL pointing to the source of this defect. This is typically a reference into "
29
+ "the issue tracker system that contains this defect.",
30
+ )
31
+ title: str | None = Field(
32
+ default=None,
33
+ description="A title for this defect if available. This is a short summary describing the problem at hand.",
34
+ )
35
+ state: str | None = Field(
36
+ default=None,
37
+ description="A state of the associated defect if available. The concrete meaning of this string depends"
38
+ "on the source from where it was obtained, as different issue tracker systems use their specific "
39
+ "terminology. Possible values could be OPEN, IN PROGRESS, BLOCKED, etc.",
40
+ )
41
+ severity: str | None = Field(
42
+ default=None,
43
+ description="The severity assigned to the defect if available. The meaning of this string depends"
44
+ "on the source system.",
45
+ )
46
+ description: str | None = Field(
47
+ default=None,
48
+ description="An optional description of this defect. It can contain more detailed information about"
49
+ "the defect and its impact. The field may be undefined if the url of this defect already points to"
50
+ "a website with all this information.",
51
+ )
52
+ creation_time: datetime | None = Field(
53
+ default=None,
54
+ description="The creation time of this defect if available.",
55
+ )
56
+ modification_time: datetime | None = Field(
57
+ default=None,
58
+ description="Contains a time when this defect has been modified the last time in the tracker system"
59
+ "it has been obtained from. This information can be useful for instance to find out how up-to-date"
60
+ "this defect report might be.",
61
+ )
62
+ closing_time: datetime | None = Field(
63
+ default=None,
64
+ description="Contains a time when this defect has been closed if it has been resolved already"
65
+ "(and this information is available in the source system). For users of the component affected"
66
+ "by this defect, this information can be of interest to find out whether a fix is available,"
67
+ "maybe in a newer version.",
68
+ )
69
+ fix_release_version: str | None = Field(
70
+ default=None,
71
+ description="Contains the version of the release, in which this defect was fixed if available."
72
+ "This is important information for consumers of the component affected by the defect, so they"
73
+ "can upgrade to this version.",
74
+ )
75
+ fix_release_url: AnyUrl | None = Field(
76
+ default=None,
77
+ description="A URL pointing to the release, in which this defect was fixed if available."
78
+ "Depending on the information provided by a source, this URL could point to a website with detail"
79
+ "information about the release, to release notes, or something like that. This information is"
80
+ "important for consumers of the component affected by this defect, so they can upgrade to this release.",
81
+ )
82
+ labels: dict[str, str] = Field(
83
+ default_factory=dict,
84
+ description="A map with labels assigned to this defect. Labels provide a means frequently used by issue"
85
+ "tracker systems to classify defects based on defined criteria. The exact meaning of these labels is"
86
+ "depending on the source system.",
87
+ )
@@ -4,11 +4,11 @@
4
4
 
5
5
  from pydantic import BaseModel, ConfigDict, Field, field_validator
6
6
 
7
- from ort.models.dependency_graph_edge import DependencyGraphEdge
8
- from ort.models.dependency_graph_node import DependencyGraphNode
9
- from ort.models.dependency_reference import DependencyReference
10
- from ort.models.identifier import Identifier
11
- from ort.models.root_dependency_index import RootDependencyIndex
7
+ from .dependency_graph_edge import DependencyGraphEdge
8
+ from .dependency_graph_node import DependencyGraphNode
9
+ from .dependency_reference import DependencyReference
10
+ from .identifier import Identifier
11
+ from .root_dependency_index import RootDependencyIndex
12
12
 
13
13
 
14
14
  class DependencyGraph(BaseModel):
@@ -2,10 +2,10 @@
2
2
  # SPDX-License-Identifier: MIT
3
3
 
4
4
 
5
- from pydantic import BaseModel, ConfigDict, Field
5
+ from pydantic import BaseModel, ConfigDict, Field, field_validator
6
6
 
7
- from ort.models.issue import Issue
8
- from ort.models.package_linkage import PackageLinkage
7
+ from .issue import Issue
8
+ from .package_linkage import PackageLinkage
9
9
 
10
10
 
11
11
  class DependencyGraphNode(BaseModel):
@@ -42,3 +42,13 @@ class DependencyGraphNode(BaseModel):
42
42
  issues: list[Issue] = Field(
43
43
  default_factory=list, description="A list of Issue objects that occurred handling this dependency."
44
44
  )
45
+
46
+ @field_validator("linkage", mode="before")
47
+ @classmethod
48
+ def convert_linkage(cls, v):
49
+ if isinstance(v, str):
50
+ try:
51
+ return PackageLinkage[v]
52
+ except KeyError:
53
+ raise ValueError(f"Invalid linkage: {v}")
54
+ return v
@@ -4,8 +4,8 @@
4
4
 
5
5
  from pydantic import BaseModel, ConfigDict, Field
6
6
 
7
- from ort.models.issue import Issue
8
- from ort.models.package_linkage import PackageLinkage
7
+ from .issue import Issue
8
+ from .package_linkage import PackageLinkage
9
9
 
10
10
 
11
11
  class DependencyReference(BaseModel):
@@ -3,7 +3,7 @@
3
3
 
4
4
  from pydantic import BaseModel, Field
5
5
 
6
- from ort.models.hash_algorithm import HashAlgorithm
6
+ from .hash_algorithm import HashAlgorithm
7
7
 
8
8
 
9
9
  class Hash(BaseModel):
@@ -4,8 +4,9 @@
4
4
 
5
5
  from pydantic import BaseModel, ConfigDict, Field
6
6
 
7
- from ort.models.analyzer_run import AnalyzerRun
8
- from ort.models.repository import Repository
7
+ from .advisor_run import AdvisorRun
8
+ from .analyzer_run import AnalyzerRun
9
+ from .repository import Repository
9
10
 
10
11
 
11
12
  class OrtResult(BaseModel):
@@ -30,3 +31,14 @@ class OrtResult(BaseModel):
30
31
  description="An [AnalyzerRun] containing details about the analyzer that was run using [repository]"
31
32
  "as input. Can be null if the [repository] was not yet analyzed."
32
33
  )
34
+ advisor: AdvisorRun | None = Field(
35
+ default=None,
36
+ description="An [AdvisorRun] containing details about the advisor that was run using the result from"
37
+ "[analyzer] as input. Can be null if no advisor was run.",
38
+ )
39
+ labels: dict[str, str] = Field(
40
+ default_factory=dict,
41
+ description="User defined labels associated to this result. Labels are not used by ORT itself, "
42
+ "but can be used in parts of ORT which are customizable by the user, for example in evaluator"
43
+ "rules or in the notice reporter.",
44
+ )
@@ -4,12 +4,13 @@
4
4
 
5
5
  from pydantic import BaseModel, ConfigDict, Field
6
6
 
7
- from ort.models.identifier import Identifier
8
- from ort.models.remote_artifact import RemoteArtifact
9
- from ort.models.source_code_origin import SourceCodeOrigin
10
- from ort.models.vcsinfo import VcsInfo
11
7
  from ort.utils.processed_declared_license import ProcessedDeclaredLicense
12
8
 
9
+ from .identifier import Identifier
10
+ from .remote_artifact import RemoteArtifact
11
+ from .source_code_origin import SourceCodeOrigin
12
+ from .vcsinfo import VcsInfo
13
+
13
14
 
14
15
  class Package(BaseModel):
15
16
  """
@@ -3,18 +3,13 @@
3
3
 
4
4
  from typing import Any
5
5
 
6
- from pydantic import AnyUrl, BaseModel, ConfigDict, Field
6
+ from pydantic import BaseModel, ConfigDict, Field
7
7
 
8
- from .hash import Hash
8
+ from .remote_artifact import RemoteArtifact
9
9
  from .source_code_origin import SourceCodeOrigin
10
10
  from .vcsinfo_curation_data import VcsInfoCurationData
11
11
 
12
12
 
13
- class CurationArtifact(BaseModel):
14
- url: AnyUrl
15
- hash: Hash
16
-
17
-
18
13
  class PackageCurationData(BaseModel):
19
14
  """
20
15
  Data model for package curation data.
@@ -47,8 +42,8 @@ class PackageCurationData(BaseModel):
47
42
  concluded_license: str | None = None
48
43
  description: str | None = None
49
44
  homepage_url: str | None = None
50
- binary_artifact: CurationArtifact | None = None
51
- source_artifact: CurationArtifact | None = None
45
+ binary_artifact: RemoteArtifact | None = None
46
+ source_artifact: RemoteArtifact | None = None
52
47
  vcs: VcsInfoCurationData | None = None
53
48
  is_metadata_only: bool | None = None
54
49
  is_modified: bool | None = None
@@ -2,10 +2,10 @@
2
2
  # SPDX-License-Identifier: MIT
3
3
 
4
4
 
5
- from enum import Enum, auto
5
+ from enum import IntEnum
6
6
 
7
7
 
8
- class PackageLinkage(Enum):
8
+ class PackageLinkage(IntEnum):
9
9
  """
10
10
  A class to denote the linkage type between two packages.
11
11
 
@@ -27,7 +27,7 @@ class PackageLinkage(Enum):
27
27
  e.g. a subproject of a multi-project.
28
28
  """
29
29
 
30
- DYNAMIC = auto()
31
- STATIC = auto()
32
- PROJECT_DYNAMIC = auto()
33
- PROJECT_STATIC = auto()
30
+ DYNAMIC = 1
31
+ STATIC = 2
32
+ PROJECT_DYNAMIC = 3
33
+ PROJECT_STATIC = 4
@@ -4,8 +4,8 @@
4
4
 
5
5
  from pydantic import BaseModel, ConfigDict, Field
6
6
 
7
- from ort.models.issue import Issue
8
- from ort.models.package_linkage import PackageLinkage
7
+ from .issue import Issue
8
+ from .package_linkage import PackageLinkage
9
9
 
10
10
 
11
11
  class PackageReference(BaseModel):
@@ -4,11 +4,12 @@
4
4
 
5
5
  from pydantic import BaseModel, ConfigDict, Field
6
6
 
7
- from ort.models.identifier import Identifier
8
- from ort.models.scope import Scope
9
- from ort.models.vcsinfo import VcsInfo
10
7
  from ort.utils.processed_declared_license import ProcessedDeclaredLicense
11
8
 
9
+ from .identifier import Identifier
10
+ from .scope import Scope
11
+ from .vcsinfo import VcsInfo
12
+
12
13
 
13
14
  class Project(BaseModel):
14
15
  """
@@ -4,7 +4,7 @@
4
4
 
5
5
  from pydantic import BaseModel, Field
6
6
 
7
- from ort.models.hash import Hash
7
+ from .hash import Hash
8
8
 
9
9
 
10
10
  class RemoteArtifact(BaseModel):
@@ -13,8 +13,10 @@ class RemoteArtifact(BaseModel):
13
13
  """
14
14
 
15
15
  url: str = Field(
16
+ default_factory=str,
16
17
  description="The URL of the remote artifact.",
17
18
  )
18
- hash: Hash = Field(
19
+ hash: Hash | None = Field(
20
+ default=None,
19
21
  description="The hash of the remote artifact.",
20
22
  )
@@ -4,8 +4,8 @@
4
4
 
5
5
  from pydantic import BaseModel, ConfigDict, Field
6
6
 
7
- from ort.models.repository_configuration import OrtRepositoryConfiguration
8
- from ort.models.vcsinfo import VcsInfo
7
+ from .repository_configuration import RepositoryConfiguration
8
+ from .vcsinfo import VcsInfo
9
9
 
10
10
 
11
11
  class Repository(BaseModel):
@@ -37,6 +37,6 @@ class Repository(BaseModel):
37
37
  description="A map of nested repositories, for example Git submodules or Git-Repo"
38
38
  "modules. The key is the path to the nested repository relative to the root of the main repository.",
39
39
  )
40
- config: OrtRepositoryConfiguration = Field(
40
+ config: RepositoryConfiguration = Field(
41
41
  description="The configuration of the repository, parsed from [ORT_REPO_CONFIG_FILENAME]."
42
42
  )
@@ -260,7 +260,7 @@ class OrtRepositoryConfigurationCurations1(BaseModel):
260
260
  packages: Curations
261
261
 
262
262
 
263
- class OrtRepositoryConfiguration(BaseModel):
263
+ class RepositoryConfiguration(BaseModel):
264
264
  """
265
265
  Represents the configuration for an OSS-Review-Toolkit (ORT) repository.
266
266
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  from pydantic import BaseModel, ConfigDict, Field
6
6
 
7
- from ort.models.package_reference import PackageReference
7
+ from .package_reference import PackageReference
8
8
 
9
9
 
10
10
  class Scope(BaseModel):
@@ -1,7 +1,7 @@
1
1
  # SPDX-FileCopyrightText: 2025 Helio Chissini de Castro <heliocastro@gmail.com>
2
2
  # SPDX-License-Identifier: MIT
3
3
 
4
- from pydantic import AnyUrl, BaseModel, Field
4
+ from pydantic import BaseModel, Field
5
5
 
6
6
  from .vcstype import VcsType
7
7
 
@@ -22,7 +22,8 @@ class VcsInfo(BaseModel):
22
22
  default_factory=VcsType,
23
23
  description="The type of the VCS, for example Git, GitRepo, Mercurial, etc.",
24
24
  )
25
- url: AnyUrl = Field(
25
+ url: str = Field(
26
+ default_factory=str,
26
27
  description="The URL to the VCS repository.",
27
28
  )
28
29
 
@@ -0,0 +1,8 @@
1
+ # SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <heliocastro@gmail.com>
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ from .vulnerability import Vulnerability
5
+
6
+ __all__ = [
7
+ "Vulnerability",
8
+ ]
@@ -0,0 +1,39 @@
1
+ # SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <heliocastro@gmail.com>
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ from enum import Enum
5
+
6
+
7
+ class Cvss2Rating(Enum):
8
+ """
9
+ A CVSS version 2 rating, see https://nvd.nist.gov/vuln-metrics/cvss.
10
+ """
11
+
12
+ LOW = 4.0
13
+ MEDIUM = 7.0
14
+ HIGH = 10.0
15
+
16
+ def __init__(self, upper_bound: float):
17
+ self._upper_bound = upper_bound
18
+
19
+ @classmethod
20
+ def prefixes(cls) -> set[str]:
21
+ """A set of prefixes that refer to the CVSS version 2 scoring system."""
22
+ return {"CVSS2", "CVSSV2", "CVSS_V2", "CVSS:2"}
23
+
24
+ @classmethod
25
+ def from_score(cls, score: float) -> "Cvss2Rating | None":
26
+ """Get the Cvss2Rating from a score, or None if the score does not map to any Cvss2Rating."""
27
+ if score < 0.0 or score > cls.HIGH.upper_bound:
28
+ return None
29
+ if score < cls.LOW.upper_bound:
30
+ return cls.LOW
31
+ if score < cls.MEDIUM.upper_bound:
32
+ return cls.MEDIUM
33
+ if score <= cls.HIGH.upper_bound:
34
+ return cls.HIGH
35
+ return None
36
+
37
+ @property
38
+ def upper_bound(self) -> float:
39
+ return self._upper_bound
@@ -0,0 +1,45 @@
1
+ # SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <heliocastro@gmail.com>
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ from enum import Enum
5
+
6
+
7
+ class Cvss3Rating(Enum):
8
+ """
9
+ A CVSS version 3 rating as defined by https://www.first.org/cvss/v3.1/specification-document#Qualitative-Severity-Rating-Scale.
10
+ """
11
+
12
+ NONE = 0.0
13
+ LOW = 4.0
14
+ MEDIUM = 7.0
15
+ HIGH = 9.0
16
+ CRITICAL = 10.0
17
+
18
+ def __init__(self, upper_bound: float):
19
+ self._upper_bound = upper_bound
20
+
21
+ @classmethod
22
+ def prefixes(cls) -> set[str]:
23
+ """A set of prefixes that refer to the CVSS version 3 scoring system."""
24
+ return {"CVSS3", "CVSSV3", "CVSS_V3", "CVSS:3"}
25
+
26
+ @classmethod
27
+ def from_score(cls, score: float) -> "Cvss3Rating | None":
28
+ """Get the Cvss3Rating from a score, or None if the score does not map to any Cvss3Rating."""
29
+ if score < 0.0 or score > cls.CRITICAL.upper_bound:
30
+ return None
31
+ if score < cls.NONE.upper_bound:
32
+ return cls.NONE
33
+ if score < cls.LOW.upper_bound:
34
+ return cls.LOW
35
+ if score < cls.MEDIUM.upper_bound:
36
+ return cls.MEDIUM
37
+ if score < cls.HIGH.upper_bound:
38
+ return cls.HIGH
39
+ if score <= cls.CRITICAL.upper_bound:
40
+ return cls.CRITICAL
41
+ return None
42
+
43
+ @property
44
+ def upper_bound(self) -> float:
45
+ return self._upper_bound
@@ -0,0 +1,45 @@
1
+ # SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <heliocastro@gmail.com>
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ from enum import Enum
5
+
6
+
7
+ class Cvss4Rating(Enum):
8
+ """
9
+ A CVSS version 4 rating as defined by https://www.first.org/cvss/v4.0/specification-document#Qualitative-Severity-Rating-Scale.
10
+ """
11
+
12
+ NONE = 0.0
13
+ LOW = 4.0
14
+ MEDIUM = 7.0
15
+ HIGH = 9.0
16
+ CRITICAL = 10.0
17
+
18
+ def __init__(self, upper_bound: float):
19
+ self._upper_bound = upper_bound
20
+
21
+ @classmethod
22
+ def prefixes(cls) -> set[str]:
23
+ """A set of prefixes that refer to the CVSS version 4 scoring system."""
24
+ return {"CVSS4", "CVSSV4", "CVSS_V4", "CVSS:4"}
25
+
26
+ @classmethod
27
+ def from_score(cls, score: float) -> "Cvss4Rating | None":
28
+ """Get the Cvss4Rating from a score, or None if the score does not map to any Cvss4Rating."""
29
+ if score < 0.0 or score > cls.CRITICAL.upper_bound:
30
+ return None
31
+ if score < cls.NONE.upper_bound:
32
+ return cls.NONE
33
+ if score < cls.LOW.upper_bound:
34
+ return cls.LOW
35
+ if score < cls.MEDIUM.upper_bound:
36
+ return cls.MEDIUM
37
+ if score < cls.HIGH.upper_bound:
38
+ return cls.HIGH
39
+ if score <= cls.CRITICAL.upper_bound:
40
+ return cls.CRITICAL
41
+ return None
42
+
43
+ @property
44
+ def upper_bound(self) -> float:
45
+ return self._upper_bound
@@ -0,0 +1,39 @@
1
+ # SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <heliocastro@gmail.com>
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ from pydantic import BaseModel, ConfigDict, Field
5
+
6
+ from .vulnerability_reference import VulnerabilityReference
7
+
8
+
9
+ class Vulnerability(BaseModel):
10
+ """
11
+ Base model for all vulnerability providers supported by the advisor.
12
+
13
+ This class stores the information about a single vulnerability, which may have been retrieved from multiple
14
+ vulnerability providers. For each source of information a [VulnerabilityReference] is contained.
15
+ """
16
+
17
+ model_config = ConfigDict(
18
+ extra="forbid",
19
+ )
20
+
21
+ id: str = Field(
22
+ ...,
23
+ description="The ID of a vulnerability. Most likely a CVE identifier.",
24
+ )
25
+
26
+ summary: str | None = Field(
27
+ None,
28
+ description="A short summary of this Vulnerability.",
29
+ )
30
+
31
+ description: str | None = Field(
32
+ None,
33
+ description="A full description of this Vulnerability.",
34
+ )
35
+
36
+ references: list["VulnerabilityReference"] = Field(
37
+ ...,
38
+ description="A list with detailed information for this vulnerability obtained from different sources.",
39
+ )
@@ -0,0 +1,78 @@
1
+ # SPDX-FileCopyrightText: 2026 Helio Chissini de Castro <heliocastro@gmail.com>
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ from __future__ import annotations
5
+
6
+ from enum import Enum
7
+
8
+ from pydantic import BaseModel, ConfigDict, Field
9
+
10
+ from .cvss2_rating import Cvss2Rating
11
+ from .cvss3_rating import Cvss3Rating
12
+ from .cvss4_rating import Cvss4Rating
13
+
14
+
15
+ class VulnerabilityReference(BaseModel):
16
+ """
17
+ A data class representing detailed information about a vulnerability obtained from a specific source.
18
+
19
+ A single vulnerability can be listed by multiple sources using different scoring systems to denote its severity.
20
+ So when ORT queries different providers for vulnerability information it may well find multiple records for a single
21
+ vulnerability, which could even contain contradicting information. To model this, a [Vulnerability] is associated
22
+ with a list of references; each reference points to the source of the information and has some detailed information
23
+ provided by this source.
24
+
25
+ """
26
+
27
+ model_config = ConfigDict(
28
+ extra="forbid",
29
+ )
30
+
31
+ url: str = Field(
32
+ ...,
33
+ description="The URI pointing to details of the belonging vulnerability.",
34
+ )
35
+
36
+ scoring_system: str | None = Field(
37
+ default=None,
38
+ description="The name of the scoring system (like CVSS, EPSS), if any, as reported by the advice provider.",
39
+ )
40
+
41
+ severity: str | None = Field(
42
+ default=None,
43
+ description="The severity, if any, this reference assigns to the belonging vulnerability. This "
44
+ 'string is supposed to be a qualitative rating like "LOW" or "HIGH".',
45
+ )
46
+
47
+ score: float | None = Field(
48
+ default=None,
49
+ description="The (base) score, if any, this reference assigns to the belonging vulnerability. "
50
+ "The meaning of this number depends on the scoring system.",
51
+ )
52
+
53
+ vector: str | None = Field(
54
+ default=None,
55
+ description="For CVSS, this is the full vector this reference assigns to the belonging "
56
+ "vulnerability, if any. While the vector usually contains the scoring system as a "
57
+ "prefix, that is not the case for CVSS v2. For EPSS, this is the percentile, which "
58
+ "provides a measure of probability relative to all other scores.",
59
+ )
60
+
61
+ @staticmethod
62
+ def get_qualitative_rating(scoring_system: str | None, score: float | None) -> Enum | None:
63
+ """
64
+ Get the qualitative rating for the given scoring system and score.
65
+
66
+ Returns the corresponding CVSS rating enum member, or None if the scoring system is unknown
67
+ or the score does not map to any rating.
68
+ """
69
+ if scoring_system is None or score is None:
70
+ return None
71
+
72
+ upper = scoring_system.upper()
73
+
74
+ for rating_cls in (Cvss2Rating, Cvss3Rating, Cvss4Rating):
75
+ if any(upper.startswith(prefix) for prefix in rating_cls.prefixes()):
76
+ return rating_cls.from_score(score)
77
+
78
+ return None
@@ -1,10 +0,0 @@
1
- # SPDX-FileCopyrightText: 2025 Helio Chissini de Castro <heliocastro@gmail.com>
2
- # SPDX-License-Identifier: MIT
3
-
4
- from .identifier import Identifier
5
- from .vcstype import VcsType
6
-
7
- __all__ = [
8
- "Identifier",
9
- "VcsType",
10
- ]
File without changes
File without changes