Skip to content

Commit

Permalink
[issue-290] Add new document class
Browse files Browse the repository at this point in the history
Signed-off-by: Nicolaus Weidner <[email protected]>
  • Loading branch information
nicoweidner committed Nov 16, 2022
1 parent d206edf commit e26db6f
Show file tree
Hide file tree
Showing 5 changed files with 234 additions and 0 deletions.
81 changes: 81 additions & 0 deletions src/model/document.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Copyright (c) 2022 spdx contributors
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


from datetime import datetime
from typing import List, Optional

from src.model.actor import Actor
from src.model.annotation import Annotation
from src.model.external_document_ref import ExternalDocumentRef
from src.model.extracted_licensing_info import ExtractedLicensingInfo
from src.model.file import File
from src.model.package import Package
from src.model.relationship import Relationship
from src.model.snippet import Snippet
from src.model.version import Version


class CreationInfo:
creators: List[Actor] # min. 1 element
created: datetime
comment: Optional[str]

def __init__(self, creators: List[Actor], created: datetime, comment: Optional[str] = None):
self.creators = creators
self.created = created
self.comment = comment


class Document:
data_license = "CC0-1.0"

# Mandatory properties

spdx_version: str
spdx_id: str
name: str
document_namespace: str
creation_info: CreationInfo

# Optional properties

external_document_references: List[ExternalDocumentRef]
license_list_version: Optional[Version]
comment: Optional[str]

packages: List[Package]
files: List[File]
snippets: List[Snippet]
annotations: List[Annotation]
relationships: List[Relationship]
extracted_licensing_info: List[ExtractedLicensingInfo]

def __init__(self, spdx_version: str, spdx_id: str, name: str, document_namespace: str,
creation_info: CreationInfo, external_document_references: List[ExternalDocumentRef] = None,
license_list_version: Optional[Version] = None, comment: Optional[str] = None,
packages: List[Package] = None, files: List[File] = None, snippets: List[Snippet] = None,
annotations: List[Annotation] = None, relationships: List[Relationship] = None,
extracted_licensing_info: List[ExtractedLicensingInfo] = None):
self.spdx_version = spdx_version
self.spdx_id = spdx_id
self.name = name
self.document_namespace = document_namespace
self.creation_info = creation_info
self.external_document_references = [] if external_document_references is None else external_document_references
self.license_list_version = license_list_version
self.comment = comment
self.packages = [] if packages is None else packages
self.files = [] if files is None else files
self.snippets = [] if snippets is None else snippets
self.annotations = [] if annotations is None else annotations
self.relationships = [] if relationships is None else relationships
self.extracted_licensing_info = [] if extracted_licensing_info is None else extracted_licensing_info
24 changes: 24 additions & 0 deletions src/model/external_document_ref.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright (c) 2022 spdx contributors
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


from src.model.checksum import Checksum


class ExternalDocumentRef:
namespace: str
spdx_id: str
checksum: Checksum

def __init__(self, namespace: str, spdx_id: str, checksum: Checksum):
self.namespace = namespace
self.spdx_id = spdx_id
self.checksum = checksum
52 changes: 52 additions & 0 deletions src/model/extracted_licensing_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright (c) 2022 spdx contributors
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


from datetime import datetime
from typing import Optional, List


class CrossReference:
url: str
is_live: Optional[bool]
is_valid: Optional[bool]
is_way_back_link: Optional[bool]
match: Optional[str]
order: Optional[int]
timestamp: Optional[datetime]

def __init__(self, url: str, is_live: Optional[bool] = None, is_valid: Optional[bool] = None,
is_way_back_link: Optional[bool] = None, match: Optional[str] = None, order: Optional[int] = None,
timestamp: Optional[datetime] = None):
self.url = url
self.is_live = is_live
self.is_valid = is_valid
self.is_way_back_link = is_way_back_link
self.match = match
self.order = order
self.timestamp = timestamp


class ExtractedLicensingInfo:
license_id: Optional[str]
extracted_text: Optional[str]
license_name: Optional[str]
comment: Optional[str]
cross_references: List[CrossReference]

def __init__(self, license_id: Optional[str] = None, extracted_text: Optional[str] = None,
license_name: Optional[str] = None, comment: Optional[str] = None,
cross_references: List[CrossReference] = None):
self.license_id = license_id
self.extracted_text = extracted_text
self.license_name = license_name
self.comment = comment
self.cross_references = [] if cross_references is None else cross_references
47 changes: 47 additions & 0 deletions src/model/version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Copyright (c) 2022 spdx contributors
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


import re
from re import Pattern


class Version:
VERSION_REGEX: Pattern = re.compile(r"^(\d+)\.(\d+)$")

major: int
minor: int

@classmethod
def is_valid_version_string(cls, value: str) -> bool:
return cls.VERSION_REGEX.match(value) is not None

# No type hint for Python reasons.
# See https://stackoverflow.com/questions/33533148/how-do-i-type-hint-a-method-with-the-type-of-the-enclosing-class
@classmethod
def from_string(cls, value: str):
m = cls.VERSION_REGEX.match(value)
if m is not None:
return cls(int(m.group(1)), int(m.group(2)))
else:
raise ValueError(f"{value} is not a valid version string")

def __init__(self, major: int, minor: int):
self.major = major
self.minor = minor

def __str__(self):
return f"{self.major}.{self.minor}"

def __eq__(self, other):
if not isinstance(other, Version):
return False
return self.major == other.major and self.minor == other.minor
30 changes: 30 additions & 0 deletions tests/model/test_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright (c) 2022 spdx contributors
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


import pytest

from src.model.version import Version


@pytest.mark.parametrize("input_string,expected", [("1.2", Version(1, 2)), ("12.345", Version(12, 345))])
def test_version_from_string(input_string, expected):
assert Version.is_valid_version_string(input_string)
version: Version = Version.from_string(input_string)
assert version == expected


@pytest.mark.parametrize("input_string", ["1", "1-2", "1.a", "a", "a.b", "a.1", "v1.2", "1.2v"])
def test_invalid_version_string(input_string):
assert not Version.is_valid_version_string(input_string)
with pytest.raises(ValueError) as error:
Version.from_string(input_string)
assert str(error.value) == f"{input_string} is not a valid version string"

0 comments on commit e26db6f

Please sign in to comment.