Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,3 @@ updates:
schedule:
interval: "daily"
open-pull-requests-limit: 10

8 changes: 4 additions & 4 deletions prek.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ hooks = [

[[repos]]
repo = "https://github.com/astral-sh/ruff-pre-commit"
rev = "v0.15.12"
rev = "v0.16.0"
hooks = [
{
id = "ruff",
Expand All @@ -43,21 +43,21 @@ hooks = [

[[repos]]
repo = "https://github.com/astral-sh/uv-pre-commit"
rev = "0.11.13"
rev = "0.11.33"
hooks = [
{ id = "uv-lock" }
]

[[repos]]
repo = "https://github.com/codespell-project/codespell"
rev = "v2.4.2"
rev = "v2.4.3"
hooks = [
{ id = "codespell" }
]

[[repos]]
repo = "https://github.com/allganize/ty-pre-commit"
rev = "v0.0.35"
rev = "v0.0.64"
hooks = [
{
id = "ty-check",
Expand Down
27 changes: 14 additions & 13 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "python-ort"
version = "0.9.5"
version = "0.10.0"
description = "A Python Ort model serialization library"
readme = "README.md"
requires-python = ">=3.10"
Expand All @@ -18,24 +18,24 @@ classifiers = [
"Topic :: Software Development :: Libraries :: Python Modules",
]
dependencies = [
"click>=8.4.1",
"license-expression>=30.4.4",
"packageurl-python>=0.17.6",
"pydantic>=2.13.4",
"pyyaml>=6.0.3",
"click>=8.4.2",
"license-expression>=30.4.4",
"packageurl-python>=0.17.6",
"pydantic>=2.13.4",
"pyyaml>=6.0.3",
]

[project.scripts]
ort-validate = "tools.ort_validate:main"

[dependency-groups]
dev = [
"datamodel-code-generator[http]>=0.64.0",
"pytest>=9.1.0",
"rich>=15.0.0",
"ruff>=0.15.17",
"ty>=0.0.50",
"types-pyyaml>=6.0.12.20260518",
"datamodel-code-generator[http]>=0.71.0",
"pytest>=9.1.1",
"rich>=15.0.0",
"ruff>=0.16.0",
"ty>=0.0.64",
"types-pyyaml>=6.0.12.20260724",
]

[build-system]
Expand All @@ -44,7 +44,8 @@ build-backend = "uv_build"

[tool.codespell]
skip = [
".agents",
".agents/*",

]

[tool.pylint.messages_control]
Expand Down
2 changes: 1 addition & 1 deletion src/ort/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

__all__ = [
"AnalyzerResult",
"OrtResult",
"OrtYamlLoader",
"RepositoryConfiguration",
"OrtResult",
"ort_yaml_load",
]
6 changes: 3 additions & 3 deletions src/ort/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@
"DependencyGraphEdge",
"DependencyGraphNode",
"DependencyReference",
"Excludes",
"Hash",
"Identifier",
"Includes",
"Excludes",
"Issue",
"LicenseClassifications",
"OrtResult",
Expand All @@ -59,10 +59,10 @@
"PackageCurationData",
"PackageLinkage",
"PackageReference",
"PathExcludeReason",
"PathIncludeReason",
"PathExclude",
"PathExcludeReason",
"PathInclude",
"PathIncludeReason",
"Project",
"RemoteArtifact",
"Repository",
Expand Down
2 changes: 1 addition & 1 deletion src/ort/models/config/scan_storage_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class ScanStorageConfiguration(BaseModel):
@classmethod
def validate_provenance(cls, v):
if not isinstance(v, dict):
raise ValueError("Config must be a dictionary.")
raise TypeError("Config must be a dictionary.")
# Return the dict as-is; ScanStorageConfiguration with extra="allow"
# will store all fields without needing to instantiate subclasses.
return v
Expand Down
2 changes: 1 addition & 1 deletion src/ort/models/identifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def parse_string_or_dict(cls, value: Any):
raise TypeError("Identifier must be a dict or a string in the correct format")

def __str__(self) -> str:
return ":".join([self.orttype, self.namespace, self.name, self.version])
return f"{self.orttype}:{self.namespace}:{self.name}:{self.version}"

@model_serializer(mode="plain")
def serialize(self) -> str:
Expand Down
6 changes: 0 additions & 6 deletions src/ort/models/provenance.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,18 @@ class UnknownProvenance(Provenance):
Provenance information about the origin of source code.
"""

pass


class KnownProvenance(Provenance):
"""
Provenance information about the origin of source code.
"""

pass


class RemoteProvenance(KnownProvenance):
"""
Provenance information about the origin of source code.
"""

pass


class ArtifactProvenance(RemoteProvenance):
"""
Expand Down
6 changes: 6 additions & 0 deletions src/ort/models/vulnerabilities/vulnerability.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,9 @@ class Vulnerability(BaseModel):
...,
description="A list with detailed information for this vulnerability obtained from different sources.",
)

first_fixed_versions: set[str] = Field(
default_factory=set,
description="The first package versions that contain a fix for this [Vulnerability]. There could be multiple"
"first versions in case vulnerability fixes are back-ported to distinct release branches.",
)
10 changes: 8 additions & 2 deletions src/tools/ort_validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import click
from pydantic import BaseModel, ValidationError

from ort import RepositoryConfiguration, ort_yaml_load
from ort import OrtResult, RepositoryConfiguration, ort_yaml_load
from ort.models import LicenseClassifications

logger = logging.getLogger()
Expand Down Expand Up @@ -40,7 +40,6 @@ def main(debug: bool = False) -> None:
logging.basicConfig(level=logging.DEBUG)
if debug:
logging.basicConfig(level=logging.DEBUG)
pass


@click.command()
Expand All @@ -55,8 +54,15 @@ def repository_configuration(datafile):
load_and_validate(RepositoryConfiguration, datafile)


@click.command()
@click.argument("datafile")
def ort_result(datafile):
load_and_validate(OrtResult, datafile)


main.add_command(repository_configuration)
main.add_command(license_classifications)
main.add_command(ort_result)

if __name__ == "__main__":
main()
4 changes: 2 additions & 2 deletions tests/test_evaluator_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,15 @@ def test_evaluator_run_invalid_violation_entry():
start_time=datetime(2026, 3, 12, 15, 8, 5, tzinfo=timezone.utc),
end_time=datetime(2026, 3, 12, 15, 8, 8, tzinfo=timezone.utc),
environment=_make_environment(),
violations=[{"rule": "MISSING_REQUIRED_FIELDS"}], # ty: ignore[invalid-argument-type]
violations=[{"rule": "MISSING_REQUIRED_FIELDS"}],
)


def test_evaluator_run_invalid_start_time_type():
"""Test that an invalid start_time type raises a ValidationError."""
with pytest.raises(ValidationError):
EvaluatorRun(
start_time="not-a-date", # ty: ignore[invalid-argument-type]
start_time="not-a-date",
end_time=datetime(2026, 3, 12, 15, 8, 8, tzinfo=timezone.utc),
environment=_make_environment(),
)
Expand Down
3 changes: 2 additions & 1 deletion tests/test_repository_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@


import pytest
from pydantic.v1 import ValidationError

from ort.models import Includes, PathInclude, PathIncludeReason
from ort.models.config.repository_configuration import RepositoryConfiguration
Expand Down Expand Up @@ -40,7 +41,7 @@ def test_only_include_valid():
]
)
repo_config = RepositoryConfiguration(includes=includes_model)
except Exception as e:
except ValidationError as e:
pytest.fail(f"Failed to instantiate RepositoryConfiguration: {e}")

if not repo_config.includes or not getattr(repo_config.includes, "paths", None):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_scan_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ def test_scan_summary_invalid_start_time():
"""Test that an invalid start_time type raises ValidationError."""
with pytest.raises(ValidationError):
ScanSummary(
start_time="not-a-date", # ty: ignore[invalid-argument-type]
start_time="not-a-date",
end_time=datetime(2026, 3, 4, 17, 47, 23, tzinfo=timezone.utc),
)

Expand Down
28 changes: 14 additions & 14 deletions tests/test_validated_int_enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class SampleModel(BaseModel):

class TestValidatedIntEnumFromString:
def test_valid_string_name(self):
result = SampleModel(level="HIGH") # ty: ignore[invalid-argument-type]
result = SampleModel(level="HIGH")
if result.level != SampleEnum.HIGH:
pytest.fail(f"Expected SampleEnum.HIGH, got {result.level}")
if result.level.value != 3:
Expand All @@ -34,20 +34,20 @@ def test_all_members_by_name(self, member):

def test_case_sensitive_name(self):
with pytest.raises(ValidationError):
SampleModel(level="high") # ty: ignore[invalid-argument-type]
SampleModel(level="high")

def test_invalid_string_name(self):
with pytest.raises(ValidationError):
SampleModel(level="CRITICAL") # ty: ignore[invalid-argument-type]
SampleModel(level="CRITICAL")

def test_empty_string(self):
with pytest.raises(ValidationError):
SampleModel(level="") # ty: ignore[invalid-argument-type]
SampleModel(level="")


class TestValidatedIntEnumFromInt:
def test_valid_int_value(self):
result = SampleModel(level=1) # ty: ignore[invalid-argument-type]
result = SampleModel(level=1)
if result.level != SampleEnum.LOW:
pytest.fail(f"Expected SampleEnum.LOW, got {result.level}")

Expand All @@ -59,15 +59,15 @@ def test_all_members_by_int(self, member):

def test_invalid_int_value(self):
with pytest.raises(ValidationError):
SampleModel(level=99) # ty: ignore[invalid-argument-type]
SampleModel(level=99)

def test_zero_not_a_member(self):
with pytest.raises(ValidationError):
SampleModel(level=0) # ty: ignore[invalid-argument-type]
SampleModel(level=0)

def test_negative_int(self):
with pytest.raises(ValidationError):
SampleModel(level=-1) # ty: ignore[invalid-argument-type]
SampleModel(level=-1)


class TestValidatedIntEnumFromInstance:
Expand All @@ -90,30 +90,30 @@ class SeverityModel(BaseModel):
class TestValidatedIntEnumInvalidTypes:
def test_float_value(self):
with pytest.raises(ValidationError):
SampleModel(level=1.5) # ty: ignore[invalid-argument-type]
SampleModel(level=1.5)

def test_none_value(self):
with pytest.raises(ValidationError):
SampleModel(level=None) # ty: ignore[invalid-argument-type]
SampleModel(level=None)

def test_list_value(self):
with pytest.raises(ValidationError):
SampleModel(level=[1]) # ty: ignore[invalid-argument-type]
SampleModel(level=[1])

def test_dict_value(self):
with pytest.raises(ValidationError):
SampleModel(level={"name": "HIGH"}) # ty: ignore[invalid-argument-type]
SampleModel(level={"name": "HIGH"})


class TestValidatedIntEnumSerialization:
def test_serialize_to_name(self):
result = SampleModel(level="HIGH") # ty: ignore[invalid-argument-type]
result = SampleModel(level="HIGH")
data = result.model_dump()
if data["level"] != "HIGH":
pytest.fail(f"Expected 'HIGH', got {data['level']}")

def test_json_round_trip(self):
original = SampleModel(level="MEDIUM") # ty: ignore[invalid-argument-type]
original = SampleModel(level="MEDIUM")
json_str = original.model_dump_json()
restored = SampleModel.model_validate_json(json_str)
if restored.level != SampleEnum.MEDIUM:
Expand Down
4 changes: 2 additions & 2 deletions tests/test_vulnerability_reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,9 @@ def test_vulnerability_minimal(self):
def test_vulnerability_missing_id(self):
"""Test that missing id raises ValidationError."""
with pytest.raises(ValidationError):
Vulnerability(references=[VulnerabilityReference(url="https://example.com")])
Vulnerability(references=[VulnerabilityReference(url="https://example.com")]) # ty: ignore[missing-argument]

def test_vulnerability_missing_references(self):
"""Test that missing references raises ValidationError."""
with pytest.raises(ValidationError):
Vulnerability(id="CVE-2024-1234")
Vulnerability(id="CVE-2024-1234") # ty: ignore[missing-argument]
Loading
Loading