mirror of
https://github.com/openSUSE/osc.git
synced 2025-01-30 16:26:17 +01:00
Add obs_api.Request class for handling requests
This commit is contained in:
parent
e5370b9c0b
commit
9078bc257c
@ -1,3 +1,4 @@
|
|||||||
from .package import Package
|
from .package import Package
|
||||||
from .package_sources import PackageSources
|
from .package_sources import PackageSources
|
||||||
from .project import Project
|
from .project import Project
|
||||||
|
from .request import Request
|
||||||
|
@ -67,6 +67,13 @@ class LocalRole(str, Enum):
|
|||||||
READER = "reader"
|
READER = "reader"
|
||||||
|
|
||||||
|
|
||||||
|
class ObsRatings(str, Enum):
|
||||||
|
LOW = "low"
|
||||||
|
MODERATE = "moderate"
|
||||||
|
IMPORTANT = "important"
|
||||||
|
CRITICAL = "critical"
|
||||||
|
|
||||||
|
|
||||||
class RebuildModes(str, Enum):
|
class RebuildModes(str, Enum):
|
||||||
TRANSITIVE = "transitive"
|
TRANSITIVE = "transitive"
|
||||||
DIRECT = "direct"
|
DIRECT = "direct"
|
||||||
@ -77,3 +84,13 @@ class ReleaseTriggers(str, Enum):
|
|||||||
MANUAL = "manual"
|
MANUAL = "manual"
|
||||||
MAINTENANCE = "maintenance"
|
MAINTENANCE = "maintenance"
|
||||||
OBSGENDIFF = "obsgendiff"
|
OBSGENDIFF = "obsgendiff"
|
||||||
|
|
||||||
|
|
||||||
|
class RequestStates(str, Enum):
|
||||||
|
REVIEW = "review"
|
||||||
|
NEW = "new"
|
||||||
|
ACCEPTED = "accepted"
|
||||||
|
DECLINED = "declined"
|
||||||
|
REVOKED = "revoked"
|
||||||
|
SUPERSEDED = "superseded"
|
||||||
|
DELETED = "deleted"
|
||||||
|
118
osc/obs_api/request.py
Normal file
118
osc/obs_api/request.py
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
from .enums import ObsRatings
|
||||||
|
from .request_action import RequestAction
|
||||||
|
from .request_history import RequestHistory
|
||||||
|
from .request_review import RequestReview
|
||||||
|
from .request_state import RequestState
|
||||||
|
|
||||||
|
|
||||||
|
class Request(XmlModel):
|
||||||
|
XML_TAG = "request"
|
||||||
|
|
||||||
|
id: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
actions: Optional[int] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
creator: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
action_list: List[RequestAction] = Field(
|
||||||
|
xml_name="action",
|
||||||
|
)
|
||||||
|
|
||||||
|
state: Optional[RequestState] = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
description: Optional[str] = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
priority: Optional[ObsRatings] = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
review_list: Optional[List[RequestReview]] = Field(
|
||||||
|
xml_name="review",
|
||||||
|
)
|
||||||
|
|
||||||
|
history_list: Optional[List[RequestHistory]] = Field(
|
||||||
|
xml_name="history",
|
||||||
|
)
|
||||||
|
|
||||||
|
title: Optional[str] = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
accept_at: Optional[str] = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_api(
|
||||||
|
cls,
|
||||||
|
apiurl: str,
|
||||||
|
request_id: int,
|
||||||
|
*,
|
||||||
|
with_history: Optional[bool] = None,
|
||||||
|
with_full_history: Optional[bool] = None
|
||||||
|
) -> "Request":
|
||||||
|
"""
|
||||||
|
Return the specified request.
|
||||||
|
|
||||||
|
:param request_id: Id of the request.
|
||||||
|
:param withhistory: Include the request history in the results.
|
||||||
|
:param withfullhistory: Includes both, request and review history in the results.
|
||||||
|
"""
|
||||||
|
url_path = ["request", request_id]
|
||||||
|
url_query = {
|
||||||
|
"withhistory": with_history,
|
||||||
|
"withfullhistory": with_full_history,
|
||||||
|
}
|
||||||
|
response = cls.xml_request("GET", apiurl, url_path, url_query)
|
||||||
|
return cls.from_file(response, apiurl=apiurl)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def cmd_diff(
|
||||||
|
cls,
|
||||||
|
apiurl: str,
|
||||||
|
request_id: int,
|
||||||
|
*,
|
||||||
|
with_issues: Optional[bool] = None,
|
||||||
|
with_description_issues: Optional[bool] = None,
|
||||||
|
diff_to_superseded: Optional[int] = None
|
||||||
|
) -> "Request":
|
||||||
|
"""
|
||||||
|
Return the specified request including a diff of all packages in the request.
|
||||||
|
|
||||||
|
:param request_id: Id of the request.
|
||||||
|
:param with_issues: Include parsed issues from referenced sources in the change files.
|
||||||
|
:param with_description_issues: Include parsed issues from request description.
|
||||||
|
:param diff_to_superseded: Diff relatively to the given superseded request.
|
||||||
|
"""
|
||||||
|
url_path = ["request", str(request_id)]
|
||||||
|
url_query = {
|
||||||
|
"cmd": "diff",
|
||||||
|
"view": "xml",
|
||||||
|
"withissues": with_issues,
|
||||||
|
"withdescriptionissues": with_description_issues,
|
||||||
|
"diff_to_superseded": diff_to_superseded,
|
||||||
|
}
|
||||||
|
response = cls.xml_request("POST", apiurl, url_path, url_query)
|
||||||
|
return cls.from_file(response, apiurl=apiurl)
|
||||||
|
|
||||||
|
def get_issues(self):
|
||||||
|
"""
|
||||||
|
Aggregate issues from action/sourcediff into a single list.
|
||||||
|
The list may contain duplicates.
|
||||||
|
|
||||||
|
To get any issues returned, it is crucial to load the request with the issues
|
||||||
|
by calling ``cmd_diff()`` with appropriate arguments first.
|
||||||
|
"""
|
||||||
|
result = []
|
||||||
|
for action in self.action_list or []:
|
||||||
|
if action.sourcediff is None:
|
||||||
|
continue
|
||||||
|
for issue in action.sourcediff.issue_list or []:
|
||||||
|
result.append(issue)
|
||||||
|
return result
|
236
osc/obs_api/request_action.py
Normal file
236
osc/obs_api/request_action.py
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
import urllib.error
|
||||||
|
|
||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
from .package import Package
|
||||||
|
from .package_sources import PackageSources
|
||||||
|
from .request_action_acceptinfo import RequestActionAcceptinfo
|
||||||
|
from .request_action_group import RequestActionGroup
|
||||||
|
from .request_action_grouped import RequestActionGrouped
|
||||||
|
from .request_action_options import RequestActionOptions
|
||||||
|
from .request_action_person import RequestActionPerson
|
||||||
|
from .request_action_source import RequestActionSource
|
||||||
|
from .request_action_target import RequestActionTarget
|
||||||
|
from .request_sourcediff import RequestSourcediff
|
||||||
|
|
||||||
|
|
||||||
|
class RequestAction(XmlModel):
|
||||||
|
XML_TAG = "action"
|
||||||
|
|
||||||
|
class TypeEnum(str, Enum):
|
||||||
|
SUBMIT = "submit"
|
||||||
|
DELETE = "delete"
|
||||||
|
CHANGE_DEVEL = "change_devel"
|
||||||
|
ADD_ROLE = "add_role"
|
||||||
|
SET_BUGOWNER = "set_bugowner"
|
||||||
|
MAINTENANCE_INCIDENT = "maintenance_incident"
|
||||||
|
MAINTENANCE_RELEASE = "maintenance_release"
|
||||||
|
RELEASE = "release"
|
||||||
|
GROUP = "group"
|
||||||
|
|
||||||
|
type: TypeEnum = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
source: Optional[RequestActionSource] = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
target: Optional[RequestActionTarget] = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
person: Optional[RequestActionPerson] = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
group: Optional[RequestActionGroup] = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
grouped_list: Optional[List[RequestActionGrouped]] = Field(
|
||||||
|
xml_name="grouped",
|
||||||
|
)
|
||||||
|
|
||||||
|
options: Optional[RequestActionOptions] = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
sourcediff: Optional[RequestSourcediff] = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
acceptinfo: Optional[RequestActionAcceptinfo] = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self._allow_new_attributes = True
|
||||||
|
# source and target always come from ``self._apiurl`` while devel and factory projects may live elsewhere
|
||||||
|
self._devel_apiurl = self._apiurl
|
||||||
|
self._factory_apiurl = self._apiurl
|
||||||
|
self._factory_project = "openSUSE:Factory"
|
||||||
|
self._props = {}
|
||||||
|
self._allow_new_attributes = False
|
||||||
|
|
||||||
|
def _get_package(self, package_type):
|
||||||
|
key = f"{package_type}_package"
|
||||||
|
if key not in self._props:
|
||||||
|
func = getattr(self, f"_get_{package_type}_apiurl_project_package")
|
||||||
|
apiurl, project, package = func()
|
||||||
|
if apiurl is None:
|
||||||
|
self._props[key] = None
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
self._props[key] = Package.from_api(apiurl, project, package)
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if e.code != 404:
|
||||||
|
raise
|
||||||
|
self._props[key] = None
|
||||||
|
return self._props[key]
|
||||||
|
|
||||||
|
def _get_package_sources(self, package_type, *, rev=None):
|
||||||
|
key = f"{package_type}_package_sources"
|
||||||
|
if key not in self._props:
|
||||||
|
func = getattr(self, f"_get_{package_type}_apiurl_project_package")
|
||||||
|
apiurl, project, package = func()
|
||||||
|
if apiurl is None:
|
||||||
|
self._props[key] = None
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
self._props[key] = PackageSources.from_api(apiurl, project, package, rev=rev)
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
if e.code != 404:
|
||||||
|
raise
|
||||||
|
self._props[key] = None
|
||||||
|
return self._props[key]
|
||||||
|
|
||||||
|
def _get_source_apiurl_project_package(self):
|
||||||
|
return self._apiurl, self.source.project, self.source.package
|
||||||
|
|
||||||
|
@property
|
||||||
|
def source_package(self) -> Optional[Package]:
|
||||||
|
"""
|
||||||
|
Return a ``Package`` object that encapsulates metadata of the source package.
|
||||||
|
"""
|
||||||
|
return self._get_package("source")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def source_package_sources(self) -> Optional[PackageSources]:
|
||||||
|
"""
|
||||||
|
Return a ``PackageSources`` object that contains information about the ``source.rev`` revision of the source package sources in OBS SCM.
|
||||||
|
"""
|
||||||
|
if self.source is None:
|
||||||
|
return None
|
||||||
|
return self._get_package_sources("source", rev=self.source.rev)
|
||||||
|
|
||||||
|
def _get_target_apiurl_project_package(self):
|
||||||
|
if self.target is None:
|
||||||
|
return None, None, None
|
||||||
|
target_project, target_package = self.get_actual_target_project_package()
|
||||||
|
return self._apiurl, target_project, target_package
|
||||||
|
|
||||||
|
@property
|
||||||
|
def target_package(self) -> Optional[Package]:
|
||||||
|
"""
|
||||||
|
Return a ``Package`` object that encapsulates metadata of the target package.
|
||||||
|
"""
|
||||||
|
return self._get_package("target")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def target_package_sources(self) -> Optional[PackageSources]:
|
||||||
|
"""
|
||||||
|
Return a ``PackageSources`` object that contains information about the current revision of the target package sources in OBS SCM.
|
||||||
|
"""
|
||||||
|
return self._get_package_sources("target")
|
||||||
|
|
||||||
|
def _get_factory_apiurl_project_package(self):
|
||||||
|
if self.target is None:
|
||||||
|
# a new package was submitted, it doesn't exist on target; let's read the package name from the source
|
||||||
|
target_project, target_package = None, self.source.package
|
||||||
|
else:
|
||||||
|
target_project, target_package = self.get_actual_target_project_package()
|
||||||
|
|
||||||
|
if (self._apiurl, target_project) == (self._factory_apiurl, self._factory_project):
|
||||||
|
# factory package equals the target package
|
||||||
|
return None, None, None
|
||||||
|
|
||||||
|
return self._factory_apiurl, self._factory_project, target_package
|
||||||
|
|
||||||
|
@property
|
||||||
|
def factory_package(self) -> Optional[Package]:
|
||||||
|
"""
|
||||||
|
Return a ``Package`` object that encapsulates metadata of the package in the factory project.
|
||||||
|
The name of the package equals the target package name.
|
||||||
|
"""
|
||||||
|
return self._get_package("factory")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def factory_package_sources(self) -> Optional[PackageSources]:
|
||||||
|
"""
|
||||||
|
Return a ``PackageSources`` object that contains information about the current revision of the factory package sources in OBS SCM.
|
||||||
|
"""
|
||||||
|
return self._get_package_sources("factory")
|
||||||
|
|
||||||
|
def _get_devel_apiurl_project_package(self):
|
||||||
|
if self.factory_package is None:
|
||||||
|
return None, None, None
|
||||||
|
|
||||||
|
devel = self.factory_package.devel
|
||||||
|
if devel is None:
|
||||||
|
return None, None, None
|
||||||
|
|
||||||
|
return (
|
||||||
|
self._devel_apiurl,
|
||||||
|
devel.project,
|
||||||
|
devel.package or self.factory_package.name,
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def devel_package(self) -> Optional[Package]:
|
||||||
|
"""
|
||||||
|
Return a ``Package`` object that encapsulates metadata of the package in the devel project.
|
||||||
|
The devel project name and package name come from ``self.factory_package.devel``.
|
||||||
|
If the devel package name is not set, target package name is used.
|
||||||
|
"""
|
||||||
|
return self._get_package("devel")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def devel_package_sources(self) -> Optional[PackageSources]:
|
||||||
|
"""
|
||||||
|
Return a ``PackageSources`` object that contains information about the current revision of the devel package sources in OBS SCM.
|
||||||
|
"""
|
||||||
|
return self._get_package_sources("devel")
|
||||||
|
|
||||||
|
def get_actual_target_project_package(self) -> Tuple[str, str]:
|
||||||
|
"""
|
||||||
|
Return the target project and package names because maintenance incidents require special handling.
|
||||||
|
|
||||||
|
The target project for maintenance incidents is virtual and cannot be queried.
|
||||||
|
The actual target project is specified in target's ``releaseproject`` field.
|
||||||
|
|
||||||
|
Also the target package for maintenance incidents is not set explicitly.
|
||||||
|
It is extracted from ``releasename`` field from the source metadata.
|
||||||
|
If ``releasename`` is not defined, source package name is used.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.type == "maintenance_incident":
|
||||||
|
# dmach's note on security:
|
||||||
|
# The ``releaseproject`` is baked into the target information in the request and that's perfectly ok.
|
||||||
|
# The ``releasename`` is part of the source package metadata and *may change* after the request is created.
|
||||||
|
# After consulting this with OBS developers, I believe this doesn't represent any security issue
|
||||||
|
# because the project is fixed and tampering with ``releasename`` might only lead to inconsistent naming,
|
||||||
|
# the package would still end up it the same project.
|
||||||
|
|
||||||
|
# target.releaseproject is always set for a maintenance_incident
|
||||||
|
assert self.target
|
||||||
|
assert self.target.releaseproject
|
||||||
|
project = self.target.releaseproject
|
||||||
|
|
||||||
|
# the target package is not specified
|
||||||
|
# we need to extract it from source package's metadata or use source package name as a fallback
|
||||||
|
assert self.source_package
|
||||||
|
if self.source_package.releasename:
|
||||||
|
package = self.source_package.releasename.split(".")[0]
|
||||||
|
else:
|
||||||
|
package = self.source_package.name
|
||||||
|
|
||||||
|
return project, package
|
||||||
|
|
||||||
|
assert self.target
|
||||||
|
assert self.target.project
|
||||||
|
assert self.target.package
|
||||||
|
return self.target.project, self.target.package
|
33
osc/obs_api/request_action_acceptinfo.py
Normal file
33
osc/obs_api/request_action_acceptinfo.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
|
||||||
|
|
||||||
|
class RequestActionAcceptinfo(XmlModel):
|
||||||
|
XML_TAG = "acceptinfo"
|
||||||
|
|
||||||
|
rev: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
srcmd5: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
osrcmd5: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
oproject: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
opackage: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
xsrcmd5: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
oxsrcmd5: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
13
osc/obs_api/request_action_group.py
Normal file
13
osc/obs_api/request_action_group.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
|
||||||
|
|
||||||
|
class RequestActionGroup(XmlModel):
|
||||||
|
XML_TAG = "group"
|
||||||
|
|
||||||
|
name: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
role: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
9
osc/obs_api/request_action_grouped.py
Normal file
9
osc/obs_api/request_action_grouped.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
|
||||||
|
|
||||||
|
class RequestActionGrouped(XmlModel):
|
||||||
|
XML_TAG = "grouped"
|
||||||
|
|
||||||
|
id: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
27
osc/obs_api/request_action_options.py
Normal file
27
osc/obs_api/request_action_options.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
|
||||||
|
|
||||||
|
class RequestActionOptions(XmlModel):
|
||||||
|
XML_TAG = "options"
|
||||||
|
|
||||||
|
class SourceupdateEnum(str, Enum):
|
||||||
|
UPDATE = "update"
|
||||||
|
NOUPDATE = "noupdate"
|
||||||
|
CLEANUP = "cleanup"
|
||||||
|
|
||||||
|
sourceupdate: Optional[SourceupdateEnum] = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
class UpdatelinkEnum(str, Enum):
|
||||||
|
TRUE = "true"
|
||||||
|
FALSE = "false"
|
||||||
|
|
||||||
|
updatelink: Optional[UpdatelinkEnum] = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
class MakeoriginolderEnum(str, Enum):
|
||||||
|
TRUE = "true"
|
||||||
|
FALSE = "false"
|
||||||
|
|
||||||
|
makeoriginolder: Optional[MakeoriginolderEnum] = Field(
|
||||||
|
)
|
13
osc/obs_api/request_action_person.py
Normal file
13
osc/obs_api/request_action_person.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
|
||||||
|
|
||||||
|
class RequestActionPerson(XmlModel):
|
||||||
|
XML_TAG = "person"
|
||||||
|
|
||||||
|
name: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
role: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
17
osc/obs_api/request_action_source.py
Normal file
17
osc/obs_api/request_action_source.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
|
||||||
|
|
||||||
|
class RequestActionSource(XmlModel):
|
||||||
|
XML_TAG = "source"
|
||||||
|
|
||||||
|
project: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
package: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
rev: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
21
osc/obs_api/request_action_target.py
Normal file
21
osc/obs_api/request_action_target.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
|
||||||
|
|
||||||
|
class RequestActionTarget(XmlModel):
|
||||||
|
XML_TAG = "target"
|
||||||
|
|
||||||
|
project: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
package: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
releaseproject: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
repository: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
19
osc/obs_api/request_history.py
Normal file
19
osc/obs_api/request_history.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
|
||||||
|
|
||||||
|
class RequestHistory(XmlModel):
|
||||||
|
XML_TAG = "history"
|
||||||
|
|
||||||
|
who: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
when: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
description: str = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
comment: Optional[str] = Field(
|
||||||
|
)
|
57
osc/obs_api/request_review.py
Normal file
57
osc/obs_api/request_review.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
from .enums import RequestStates
|
||||||
|
from .request_review_history import RequestReviewHistory
|
||||||
|
|
||||||
|
|
||||||
|
class RequestReview(XmlModel):
|
||||||
|
XML_TAG = "review"
|
||||||
|
|
||||||
|
state: RequestStates = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
created: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
by_user: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
by_group: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
by_project: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
by_package: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
who: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
when: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
comment: Optional[str] = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
history_list: Optional[List[RequestReviewHistory]] = Field(
|
||||||
|
xml_name="history",
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_user_and_type(self):
|
||||||
|
if self.by_user:
|
||||||
|
return (self.by_user, "user")
|
||||||
|
if self.by_group:
|
||||||
|
return (self.by_group, "group")
|
||||||
|
if self.by_package:
|
||||||
|
return (f"{self.by_project}/{self.by_package}", "package")
|
||||||
|
if self.by_project:
|
||||||
|
return (self.by_project, "project")
|
||||||
|
raise RuntimeError("Unable to determine user and its type")
|
19
osc/obs_api/request_review_history.py
Normal file
19
osc/obs_api/request_review_history.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
|
||||||
|
|
||||||
|
class RequestReviewHistory(XmlModel):
|
||||||
|
XML_TAG = "history"
|
||||||
|
|
||||||
|
who: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
when: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
description: str = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
comment: Optional[str] = Field(
|
||||||
|
)
|
30
osc/obs_api/request_sourcediff.py
Normal file
30
osc/obs_api/request_sourcediff.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
from .request_sourcediff_files_file import RequestSourcediffFilesFile
|
||||||
|
from .request_sourcediff_issue import RequestSourcediffIssue
|
||||||
|
from .request_sourcediff_new import RequestSourcediffNew
|
||||||
|
from .request_sourcediff_old import RequestSourcediffOld
|
||||||
|
|
||||||
|
|
||||||
|
class RequestSourcediff(XmlModel):
|
||||||
|
XML_TAG = "sourcediff"
|
||||||
|
|
||||||
|
key: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
old: Optional[RequestSourcediffOld] = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
new: Optional[RequestSourcediffNew] = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
files_list: List[RequestSourcediffFilesFile] = Field(
|
||||||
|
xml_name="files",
|
||||||
|
xml_wrapped=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
issue_list: Optional[List[RequestSourcediffIssue]] = Field(
|
||||||
|
xml_name="issues",
|
||||||
|
xml_wrapped=True,
|
||||||
|
xml_item_name="issue",
|
||||||
|
)
|
13
osc/obs_api/request_sourcediff_file_diff.py
Normal file
13
osc/obs_api/request_sourcediff_file_diff.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
|
||||||
|
|
||||||
|
class RequestSourcediffFileDiff(XmlModel):
|
||||||
|
XML_TAG = "diff"
|
||||||
|
|
||||||
|
lines: int = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
text: str = Field(
|
||||||
|
xml_set_text=True,
|
||||||
|
)
|
17
osc/obs_api/request_sourcediff_file_new.py
Normal file
17
osc/obs_api/request_sourcediff_file_new.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
|
||||||
|
|
||||||
|
class RequestSourcediffFileNew(XmlModel):
|
||||||
|
XML_TAG = "new"
|
||||||
|
|
||||||
|
name: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
md5: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
size: int = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
17
osc/obs_api/request_sourcediff_file_old.py
Normal file
17
osc/obs_api/request_sourcediff_file_old.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
|
||||||
|
|
||||||
|
class RequestSourcediffFileOld(XmlModel):
|
||||||
|
XML_TAG = "old"
|
||||||
|
|
||||||
|
name: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
md5: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
size: int = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
21
osc/obs_api/request_sourcediff_files_file.py
Normal file
21
osc/obs_api/request_sourcediff_files_file.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
from .request_sourcediff_file_diff import RequestSourcediffFileDiff
|
||||||
|
from .request_sourcediff_file_new import RequestSourcediffFileNew
|
||||||
|
from .request_sourcediff_file_old import RequestSourcediffFileOld
|
||||||
|
|
||||||
|
|
||||||
|
class RequestSourcediffFilesFile(XmlModel):
|
||||||
|
XML_TAG = "file"
|
||||||
|
|
||||||
|
state: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
old: Optional[RequestSourcediffFileOld] = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
new: Optional[RequestSourcediffFileNew] = Field(
|
||||||
|
)
|
||||||
|
|
||||||
|
diff: RequestSourcediffFileDiff = Field(
|
||||||
|
)
|
25
osc/obs_api/request_sourcediff_issue.py
Normal file
25
osc/obs_api/request_sourcediff_issue.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
|
||||||
|
|
||||||
|
class RequestSourcediffIssue(XmlModel):
|
||||||
|
XML_TAG = "issue"
|
||||||
|
|
||||||
|
state: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
tracker: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
name: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
label: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
url: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
21
osc/obs_api/request_sourcediff_new.py
Normal file
21
osc/obs_api/request_sourcediff_new.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
|
||||||
|
|
||||||
|
class RequestSourcediffNew(XmlModel):
|
||||||
|
XML_TAG = "new"
|
||||||
|
|
||||||
|
project: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
package: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
rev: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
srcmd5: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
21
osc/obs_api/request_sourcediff_old.py
Normal file
21
osc/obs_api/request_sourcediff_old.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
|
||||||
|
|
||||||
|
class RequestSourcediffOld(XmlModel):
|
||||||
|
XML_TAG = "old"
|
||||||
|
|
||||||
|
project: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
package: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
rev: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
srcmd5: str = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
33
osc/obs_api/request_state.py
Normal file
33
osc/obs_api/request_state.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import
|
||||||
|
from .enums import RequestStates
|
||||||
|
|
||||||
|
|
||||||
|
class RequestState(XmlModel):
|
||||||
|
XML_TAG = "state"
|
||||||
|
|
||||||
|
name: RequestStates = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
who: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
when: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
created: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
superseded_by: Optional[int] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
approver: Optional[str] = Field(
|
||||||
|
xml_attribute=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
comment: Optional[str] = Field(
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user