Skip to content

Commit

Permalink
feat(sw360_objects): add Project class plus refactoring
Browse files Browse the repository at this point in the history
Refactor the from_json() methods to one common version.
  • Loading branch information
gernot-h committed Apr 5, 2022
1 parent 58f90ee commit 2fafc62
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 69 deletions.
5 changes: 3 additions & 2 deletions sw360/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from .sw360_api import SW360 # noqa: F401
from .sw360error import SW360Error # noqa: F401
from .sw360oauth2 import SW360OAuth2 # noqa: F401
from .sw360_objects import Component, Release, Attachment
from .sw360_objects import Component, Release, Attachment, Project

__all__ = ["SW360", "SW360Error", "SW360OAuth2", "Component", "Release", "Attachment"]
__all__ = ["SW360", "SW360Error", "SW360OAuth2", "Component", "Release",
"Attachment", "Project"]
190 changes: 123 additions & 67 deletions sw360/sw360_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,54 @@ def __init__(self, json=None, resource_id=None, **kwargs):
if json is not None:
self.from_json(json)

def from_json(self, json):
pass
def parse_release_list(self, json_list, component_id=None):
"""Parse a JSON list of releases, create according objects and add
them to `container`."""
releases = {}
for release_json in json_list:
release = Release(component_id=component_id)
release.from_json(release_json)
releases[release.id] = release
return releases

def parse_attachment_list(self, json_list, resources=[]):
"""Parse a JSON list of releases, create according objects and add
them to `container`."""
attachments = {}
for attachment_json in json_list:
attachment = Attachment(resources=resources)
attachment.from_json(attachment_json)
attachments[attachment.id] = attachment
return attachments

def from_json(self, json, copy_attributes=list(), rename_attributes={}):
"""`copy_attributes` will be copied as-is between this instance's
attributes and JSON members. `rename_attributes` may contain a
dictionary to map JSON attributes to instance attributes."""
for key, value in json.items():
if key in copy_attributes:
self.__setattr__(key, value)
elif key in rename_attributes:
self.__setattr__(rename_attributes[key], value)
elif key in ("_links", "_embedded"):
for links_key, links_value in value.items():
if links_key == "sw360:component":
self.component_id = links_value["href"].split("/")[-1]
elif links_key == "sw360:attachments":
self.attachments = self.parse_attachment_list(
links_value,
resources=[self])
elif links_key == "sw360:releases":
self.releases = self.parse_release_list(
links_value,
component_id=self.id)
elif links_key == "self":
self.id = links_value["href"].split("/")[-1]
else:
self.details.setdefault(key, {})
self.details[key][links_key] = links_value
else:
self.details[key] = value


class Release(SW360Resource):
Expand Down Expand Up @@ -82,28 +128,9 @@ def from_json(self, json):
external ids which will be stored as-is in `details['externalIds'].
Please note that this might change in future if better abstractions
will be added in this Python library."""
attachments = []
for key, value in json.items():
if key in ("name", "version", "downloadurl"):
self.__setattr__(key, value)
elif key in ("_links", "_embedded"):
for links_key, links_value in value.items():
if links_key == "sw360:component":
self.component_id = links_value["href"].split("/")[-1]
elif links_key == "sw360:attachments":
attachments = links_value
elif links_key == "self":
self.id = links_value["href"].split("/")[-1]
else:
self.details.setdefault(key, {})
self.details[key][links_key] = links_value
else:
self.details[key] = value

for attachment_json in attachments:
attachment = Attachment(resources=[self])
attachment.from_json(attachment_json)
self.attachments[attachment.id] = attachment
super().from_json(
json,
copy_attributes=("name", "version", "downloadurl"))

def __repr__(self):
"""Representation string."""
Expand Down Expand Up @@ -158,20 +185,10 @@ def from_json(self, json):
in the `details` instance attribute.
Please note that this might change in future if better abstractions
will be added in this Python library."""
for key, value in json.items():
if key in ("filename", "sha1"):
self.__setattr__(key, value)
elif key == "attachmentType":
self.attachment_type = value
elif key == "_links":
for links_key, links_value in value.items():
if links_key == "self":
self.id = links_value["href"].split("/")[-1]
else:
self.details.setdefault(key, {})
self.details[key][links_key] = links_value
else:
self.details[key] = value
super().from_json(
json,
copy_attributes=("filename", "sha1"),
rename_attributes={"attachmentType": "attachment_type"})

def __repr__(self):
"""Representation string."""
Expand Down Expand Up @@ -228,37 +245,76 @@ def from_json(self, json):
as-is in `details['_embedded']['sw360:vendors']` and
`details['externalIds']. Please note that this might change in future
if better abstractions will be added in this Python library."""
releases = []
attachments = []
for key, value in json.items():
if key in ("name", "description", "homepage"):
self.__setattr__(key, value)
elif key == "componentType":
self.component_type = value
elif key in ("_links", "_embedded"):
for links_key, links_value in value.items():
if key == "_links" and links_key == "self":
self.id = links_value["href"].split("/")[-1]
elif links_key == "sw360:releases":
releases = links_value
elif links_key == "sw360:attachments":
attachments = links_value
else:
self.details.setdefault(key, {})
self.details[key][links_key] = links_value
else:
self.details[key] = value
super().from_json(
json,
copy_attributes=("name", "description", "homepage"),
rename_attributes={"componentType": "component_type"})

for release_json in releases:
release = Release(component_id=self.id)
release.from_json(release_json)
self.releases[release.id] = release
def __repr__(self):
"""Representation string."""
return "<Component %s id:%s>" % (self.name, self.id)

for attachment_json in attachments:
attachment = Attachment(resources=[self])
attachment.from_json(attachment_json)
self.attachments[attachment.id] = attachment

class Project(SW360Resource):
"""A project is SW360 abstraction for a collection of software components
used in a project/product. It can contain links to other `Project`s or
`Release`s.
You can either create it from a SW360 `json` object or by specifying the
details via the constructor parameters, see list below. Only the most
important attributes are supported, rest hast be provided via `kwargs` and
is stored in the `details` attribute of instances.
For JSON parsing, please read documentation of from_json() method.
:param json: create component from SW360 JSON object by calling from_json()
:param project_id: id of the project (if exists in SW360 already)
:param name: name of the project
:param version: version of the project
:param description: short description for project
:param visibility: project visibility in SW360, one of "PRIVATE",
"ME_AND_MODERATORS", "BUISNESSUNIT_AND_MODERATORS",
"EVERYONE"
:param project_type: one of "CUSTOMER", "INTERNAL", "PRODUCT", "SERVICE",
"INNER_SOURCE"
:param kwargs: additional project details as specified in the SW360 REST API
:type json: SW360 JSON object
:type project_id: string
:type name: string
:type version: string
:type description: string
:type visibility: string
:type project_type: string
:type kwargs: dictionary
"""
def __init__(self, json=None, project_id=None, name=None, version=None,
description=None, visibility=None, project_type=None,
**kwargs):
self.releases = {}

self.name = name
self.version = version
self.description = description
self.visibility = visibility
self.project_type = project_type
super().__init__(json, project_id, **kwargs)

def from_json(self, json):
"""Parse project JSON object from SW360 REST API. Information for
its releases will be extracted, Release() objects created for them
and stored in the `releases` instance attribue. Please note that
the REST API will only provide basic information for the releases.
All details not directly supported by this class will be
stored as-is in the `details` instance attribute. For now, this also
includes linked projects and external ids. Please note that this might
change in future if better abstractions will be added in this Python
library."""
super().from_json(
json,
copy_attributes=("name", "description", "version", "visibility"),
rename_attributes={"projectType": "project_type"})

def __repr__(self):
"""Representation string."""
return "<Component %s id:%s>" % (self.name, self.id)
return "<Project %s id:%s>" % (self.name, self.id)

0 comments on commit 2fafc62

Please sign in to comment.