From 0dd1f526d8f98dd8dafc25ab20e695a7b155af0b Mon Sep 17 00:00:00 2001 From: Daniel Mach Date: Mon, 12 Feb 2024 15:13:02 +0100 Subject: [PATCH] Add XML models for Project and Package --- osc/obs_api/__init__.py | 2 + osc/obs_api/enums.py | 79 ++++++++++++ osc/obs_api/flag.py | 24 ++++ osc/obs_api/group_role.py | 15 +++ osc/obs_api/package.py | 127 +++++++++++++++++++ osc/obs_api/package_devel.py | 13 ++ osc/obs_api/person_role.py | 15 +++ osc/obs_api/project.py | 114 +++++++++++++++++ osc/obs_api/project_devel.py | 9 ++ osc/obs_api/project_link.py | 17 +++ osc/obs_api/project_maintenance_maintains.py | 9 ++ osc/obs_api/repository.py | 50 ++++++++ osc/obs_api/repository_download.py | 36 ++++++ osc/obs_api/repository_download_master.py | 13 ++ osc/obs_api/repository_hostsystem.py | 13 ++ osc/obs_api/repository_path.py | 13 ++ osc/obs_api/repository_releasetarget.py | 19 +++ osc/obs_api/simple_flag.py | 24 ++++ osc/obs_api/status.py | 42 ++++++ osc/obs_api/status_data.py | 31 +++++ 20 files changed, 665 insertions(+) create mode 100644 osc/obs_api/__init__.py create mode 100644 osc/obs_api/enums.py create mode 100644 osc/obs_api/flag.py create mode 100644 osc/obs_api/group_role.py create mode 100644 osc/obs_api/package.py create mode 100644 osc/obs_api/package_devel.py create mode 100644 osc/obs_api/person_role.py create mode 100644 osc/obs_api/project.py create mode 100644 osc/obs_api/project_devel.py create mode 100644 osc/obs_api/project_link.py create mode 100644 osc/obs_api/project_maintenance_maintains.py create mode 100644 osc/obs_api/repository.py create mode 100644 osc/obs_api/repository_download.py create mode 100644 osc/obs_api/repository_download_master.py create mode 100644 osc/obs_api/repository_hostsystem.py create mode 100644 osc/obs_api/repository_path.py create mode 100644 osc/obs_api/repository_releasetarget.py create mode 100644 osc/obs_api/simple_flag.py create mode 100644 osc/obs_api/status.py create mode 100644 osc/obs_api/status_data.py diff --git a/osc/obs_api/__init__.py b/osc/obs_api/__init__.py new file mode 100644 index 00000000..7216b78b --- /dev/null +++ b/osc/obs_api/__init__.py @@ -0,0 +1,2 @@ +from .package import Package +from .project import Project diff --git a/osc/obs_api/enums.py b/osc/obs_api/enums.py new file mode 100644 index 00000000..a5c143cb --- /dev/null +++ b/osc/obs_api/enums.py @@ -0,0 +1,79 @@ +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import + + +class BlockModes(str, Enum): + ALL = "all" + LOCAL = "local" + NEVER = "never" + + +class BuildArch(str, Enum): + NOARCH = "noarch" + AARCH64 = "aarch64" + AARCH64_ILP32 = "aarch64_ilp32" + ARMV4L = "armv4l" + ARMV5L = "armv5l" + ARMV6L = "armv6l" + ARMV7L = "armv7l" + ARMV5EL = "armv5el" + ARMV6EL = "armv6el" + ARMV7EL = "armv7el" + ARMV7HL = "armv7hl" + ARMV8EL = "armv8el" + HPPA = "hppa" + M68K = "m68k" + I386 = "i386" + I486 = "i486" + I586 = "i586" + I686 = "i686" + ATHLON = "athlon" + IA64 = "ia64" + K1OM = "k1om" + MIPS = "mips" + MIPSEL = "mipsel" + MIPS32 = "mips32" + MIPS64 = "mips64" + MIPS64EL = "mips64el" + PPC = "ppc" + PPC64 = "ppc64" + PPC64P7 = "ppc64p7" + PPC64LE = "ppc64le" + RISCV64 = "riscv64" + S390 = "s390" + S390X = "s390x" + SH4 = "sh4" + SPARC = "sparc" + SPARC64 = "sparc64" + SPARC64V = "sparc64v" + SPARCV8 = "sparcv8" + SPARCV9 = "sparcv9" + SPARCV9V = "sparcv9v" + X86_64 = "x86_64" + LOCAL = "local" + + +class LinkedbuildModes(str, Enum): + OFF = "off" + LOCALDEP = "localdep" + ALLDIRECT = "alldirect" + ALL = "all" + + +class LocalRole(str, Enum): + MAINTAINER = "maintainer" + BUGOWNER = "bugowner" + REVIEWER = "reviewer" + DOWNLOADER = "downloader" + READER = "reader" + + +class RebuildModes(str, Enum): + TRANSITIVE = "transitive" + DIRECT = "direct" + LOCAL = "local" + + +class ReleaseTriggers(str, Enum): + MANUAL = "manual" + MAINTENANCE = "maintenance" + OBSGENDIFF = "obsgendiff" diff --git a/osc/obs_api/flag.py b/osc/obs_api/flag.py new file mode 100644 index 00000000..5fa415cf --- /dev/null +++ b/osc/obs_api/flag.py @@ -0,0 +1,24 @@ +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import + + +class Flag(XmlModel): + XML_TAG = None + + def __init__(self, flag, **kwargs): + super().__init__(flag=flag, **kwargs) + + class FlagChoices(Enum): + ENABLE = "enable" + DISABLE = "disable" + + flag: FlagChoices = Field( + xml_set_tag=True, + ) + + arch: Optional[str] = Field( + xml_attribute=True, + ) + + repository: Optional[str] = Field( + xml_attribute=True, + ) diff --git a/osc/obs_api/group_role.py b/osc/obs_api/group_role.py new file mode 100644 index 00000000..c513fb36 --- /dev/null +++ b/osc/obs_api/group_role.py @@ -0,0 +1,15 @@ +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import + +from .enums import LocalRole + + +class GroupRole(XmlModel): + XML_TAG = "group" + + groupid: str = Field( + xml_attribute=True, + ) + + role: LocalRole = Field( + xml_attribute=True, + ) diff --git a/osc/obs_api/package.py b/osc/obs_api/package.py new file mode 100644 index 00000000..83783e9e --- /dev/null +++ b/osc/obs_api/package.py @@ -0,0 +1,127 @@ +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import + +from .flag import Flag +from .group_role import GroupRole +from .package_devel import PackageDevel +from .person_role import PersonRole +from .simple_flag import SimpleFlag +from .status import Status + + +class Package(XmlModel): + XML_TAG = "package" + + name: str = Field( + xml_attribute=True, + ) + + project: str = Field( + xml_attribute=True, + ) + + title: str = Field() + + description: str = Field() + + devel: Optional[PackageDevel] = Field() + + releasename: Optional[str] = Field() + + person_list: Optional[List[PersonRole]] = Field( + xml_name="person", + ) + + group_list: Optional[List[GroupRole]] = Field( + xml_name="group", + ) + + lock: Optional[SimpleFlag] = Field() + + build_list: Optional[List[Flag]] = Field( + xml_name="build", + xml_wrapped=True, + ) + + publish_list: Optional[List[Flag]] = Field( + xml_name="publish", + xml_wrapped=True, + ) + + useforbuild_list: Optional[List[Flag]] = Field( + xml_name="useforbuild", + xml_wrapped=True, + ) + + debuginfo_list: Optional[List[Flag]] = Field( + xml_name="debuginfo", + xml_wrapped=True, + ) + + binarydownload: Optional[SimpleFlag] = Field() + + sourceaccess: Optional[SimpleFlag] = Field() + + url: Optional[str] = Field() + + scmsync: Optional[str] = Field() + + bcntsynctag: Optional[str] = Field() + + @classmethod + def from_api(cls, apiurl, project, package, *, rev=None): + url_path = ["source", project, package, "_meta"] + url_query = { + "rev": rev, + } + response = cls.xml_request("GET", apiurl, url_path, url_query) + return cls.from_file(response) + + def to_api(self, apiurl, *, project=None, package=None): + project = project or self.project + package = package or self.name + url_path = ["source", project, package, "_meta"] + url_query = {} + response = self.xml_request("PUT", apiurl, url_path, url_query, data=self.to_string()) + return Status.from_file(response) + + @classmethod + def cmd_release( + cls, + apiurl: str, + project: str, + package: str, + *, + repository: Optional[str] = None, + arch: Optional[str] = None, + target_project: Optional[str] = None, + target_repository: Optional[str] = None, + setrelease: Optional[str] = None, + nodelay: Optional[bool] = None, + ): + """ + POST /source/{project}/{package}?cmd=release + Release sources and binaries of a specified package. + + :param apiurl: Full apiurl or its alias. + :param project: Project name. + :param package: Package name. + :param repository: Limit the release to the given repository. + :param arch: Limit the release to the given architecture. + :param target_project: The name of the release target project. + :param target_repository: The name of the release target repository. + :param setrelease: Tag the release with the given value. + :param nodelay: Do not delay the relase. If not set, the release will be delayed to be done later. + """ + + url_path = ["source", project, package] + url_query = { + "cmd": "release", + "repository": repository, + "arch": arch, + "target_project": target_project, + "target_repository": target_repository, + "setrelease": setrelease, + "nodelay": nodelay, + } + response = cls.xml_request("POST", apiurl, url_path, url_query) + return Status.from_string(response.read()) diff --git a/osc/obs_api/package_devel.py b/osc/obs_api/package_devel.py new file mode 100644 index 00000000..adfa7725 --- /dev/null +++ b/osc/obs_api/package_devel.py @@ -0,0 +1,13 @@ +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import + + +class PackageDevel(XmlModel): + XML_TAG = "devel" + + project: str = Field( + xml_attribute=True, + ) + + package: Optional[str] = Field( + xml_attribute=True, + ) diff --git a/osc/obs_api/person_role.py b/osc/obs_api/person_role.py new file mode 100644 index 00000000..759a29a4 --- /dev/null +++ b/osc/obs_api/person_role.py @@ -0,0 +1,15 @@ +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import + +from .enums import LocalRole + + +class PersonRole(XmlModel): + XML_TAG = "person" + + userid: str = Field( + xml_attribute=True, + ) + + role: LocalRole = Field( + xml_attribute=True, + ) diff --git a/osc/obs_api/project.py b/osc/obs_api/project.py new file mode 100644 index 00000000..9c6cf501 --- /dev/null +++ b/osc/obs_api/project.py @@ -0,0 +1,114 @@ +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import + +from .flag import Flag +from .group_role import GroupRole +from .person_role import PersonRole +from .project_devel import ProjectDevel +from .project_link import ProjectLink +from .project_maintenance_maintains import ProjectMaintenanceMaintains +from .repository import Repository +from .simple_flag import SimpleFlag + + +class Project(XmlModel): + XML_TAG = "project" + + name: str = Field( + xml_attribute=True, + ) + + class KindEnum(str, Enum): + STANDARD = "standard" + MAINTENANCE = "maintenance" + MAINTENANCE_INCIDENT = "maintenance_incident" + MAINTENANCE_RELEASE = "maintenance_release" + + kind: Optional[KindEnum] = Field( + xml_attribute=True, + ) + + title: str = Field( + ) + + description: str = Field( + ) + + url: Optional[str] = Field( + ) + + link_list: Optional[List[ProjectLink]] = Field( + xml_name="link", + ) + + mountproject: Optional[str] = Field( + ) + + remoteurl: Optional[str] = Field( + ) + + scmsync: Optional[str] = Field( + ) + + devel: Optional[ProjectDevel] = Field( + ) + + person_list: Optional[List[PersonRole]] = Field( + xml_name="person", + ) + + group_list: Optional[List[GroupRole]] = Field( + xml_name="group", + ) + + lock: Optional[SimpleFlag] = Field( + xml_wrapped=True, + ) + + build_list: Optional[List[Flag]] = Field( + xml_name="build", + xml_wrapped=True, + ) + + publish_list: Optional[List[Flag]] = Field( + xml_name="publish", + xml_wrapped=True, + ) + + useforbuild_list: Optional[List[Flag]] = Field( + xml_name="useforbuild", + xml_wrapped=True, + ) + + debuginfo_list: Optional[List[Flag]] = Field( + xml_name="debuginfo", + xml_wrapped=True, + ) + + binarydownload_list: Optional[List[Flag]] = Field( + xml_name="binarydownload", + xml_wrapped=True, + ) + + sourceaccess: Optional[SimpleFlag] = Field( + xml_wrapped=True, + ) + + access: Optional[SimpleFlag] = Field( + xml_wrapped=True, + ) + + maintenance_list: Optional[List[ProjectMaintenanceMaintains]] = Field( + xml_name="maintenance", + xml_wrapped=True, + ) + + repository_list: Optional[List[Repository]] = Field( + xml_name="repository", + ) + + @classmethod + def from_api(cls, apiurl, project): + url_path = ["source", project, "_meta"] + url_query = {} + response = cls.xml_request("GET", apiurl, url_path, url_query) + return cls.from_file(response) diff --git a/osc/obs_api/project_devel.py b/osc/obs_api/project_devel.py new file mode 100644 index 00000000..e3f5ef6a --- /dev/null +++ b/osc/obs_api/project_devel.py @@ -0,0 +1,9 @@ +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import + + +class ProjectDevel(XmlModel): + XML_TAG = "devel" + + project: str = Field( + xml_attribute=True, + ) diff --git a/osc/obs_api/project_link.py b/osc/obs_api/project_link.py new file mode 100644 index 00000000..ad3efb27 --- /dev/null +++ b/osc/obs_api/project_link.py @@ -0,0 +1,17 @@ +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import + + +class ProjectLink(XmlModel): + XML_TAG = "link" + + project: str = Field( + xml_attribute=True, + ) + + class VrevmodeEnum(str, Enum): + UNEXTEND = "unextend" + EXTEND = "extend" + + vrevmode: Optional[VrevmodeEnum] = Field( + xml_attribute=True, + ) diff --git a/osc/obs_api/project_maintenance_maintains.py b/osc/obs_api/project_maintenance_maintains.py new file mode 100644 index 00000000..9253154c --- /dev/null +++ b/osc/obs_api/project_maintenance_maintains.py @@ -0,0 +1,9 @@ +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import + + +class ProjectMaintenanceMaintains(XmlModel): + XML_TAG = "maintains" + + project: str = Field( + xml_attribute=True, + ) diff --git a/osc/obs_api/repository.py b/osc/obs_api/repository.py new file mode 100644 index 00000000..baaa9da4 --- /dev/null +++ b/osc/obs_api/repository.py @@ -0,0 +1,50 @@ +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import + +from .enums import BlockModes +from .enums import BuildArch +from .enums import LinkedbuildModes +from .enums import RebuildModes +from .repository_download import RepositoryDownload +from .repository_hostsystem import RepositoryHostsystem +from .repository_path import RepositoryPath +from .repository_releasetarget import RepositoryReleasetarget + + +class Repository(XmlModel): + XML_TAG = "repository" + + name: str = Field( + xml_attribute=True, + ) + + rebuild: Optional[RebuildModes] = Field( + xml_attribute=True, + ) + + block: Optional[BlockModes] = Field( + xml_attribute=True, + ) + + linkedbuild: Optional[LinkedbuildModes] = Field( + xml_attribute=True, + ) + + download_list: Optional[List[RepositoryDownload]] = Field( + xml_name="download", + ) + + releasetarget_list: Optional[List[RepositoryReleasetarget]] = Field( + xml_name="releasetarget", + ) + + hostsystem_list: Optional[List[RepositoryHostsystem]] = Field( + xml_name="hostsystem", + ) + + path_list: Optional[List[RepositoryPath]] = Field( + xml_name="path", + ) + + arch_list: Optional[List[BuildArch]] = Field( + xml_name="arch", + ) diff --git a/osc/obs_api/repository_download.py b/osc/obs_api/repository_download.py new file mode 100644 index 00000000..b85706d0 --- /dev/null +++ b/osc/obs_api/repository_download.py @@ -0,0 +1,36 @@ +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import + +from .repository_download_master import RepositoryDownloadMaster + + +class RepositoryDownload(XmlModel): + XML_TAG = "download" + + arch: str = Field( + xml_attribute=True, + ) + + url: str = Field( + xml_attribute=True, + ) + + class RepotypeEnum(str, Enum): + RPMMD = "rpmmd" + SUSETAGS = "susetags" + DEB = "deb" + ARCH = "arch" + MDK = "mdk" + REGISTRY = "registry" + + repotype: RepotypeEnum = Field( + xml_attribute=True, + ) + + archfilter: Optional[str] = Field( + ) + + master: Optional[RepositoryDownloadMaster] = Field( + ) + + pubkey: Optional[str] = Field( + ) diff --git a/osc/obs_api/repository_download_master.py b/osc/obs_api/repository_download_master.py new file mode 100644 index 00000000..07b11a73 --- /dev/null +++ b/osc/obs_api/repository_download_master.py @@ -0,0 +1,13 @@ +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import + + +class RepositoryDownloadMaster(XmlModel): + XML_TAG = "master" + + url: str = Field( + xml_attribute=True, + ) + + sslfingerprint: Optional[str] = Field( + xml_attribute=True, + ) diff --git a/osc/obs_api/repository_hostsystem.py b/osc/obs_api/repository_hostsystem.py new file mode 100644 index 00000000..8dc70f06 --- /dev/null +++ b/osc/obs_api/repository_hostsystem.py @@ -0,0 +1,13 @@ +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import + + +class RepositoryHostsystem(XmlModel): + XML_TAG = "hostsystem" + + repository: str = Field( + xml_attribute=True, + ) + + project: str = Field( + xml_attribute=True, + ) diff --git a/osc/obs_api/repository_path.py b/osc/obs_api/repository_path.py new file mode 100644 index 00000000..4323ccc5 --- /dev/null +++ b/osc/obs_api/repository_path.py @@ -0,0 +1,13 @@ +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import + + +class RepositoryPath(XmlModel): + XML_TAG = "path" + + project: str = Field( + xml_attribute=True, + ) + + repository: str = Field( + xml_attribute=True, + ) diff --git a/osc/obs_api/repository_releasetarget.py b/osc/obs_api/repository_releasetarget.py new file mode 100644 index 00000000..6070800b --- /dev/null +++ b/osc/obs_api/repository_releasetarget.py @@ -0,0 +1,19 @@ +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import + +from .enums import ReleaseTriggers + + +class RepositoryReleasetarget(XmlModel): + XML_TAG = "releasetarget" + + project: str = Field( + xml_attribute=True, + ) + + repository: str = Field( + xml_attribute=True, + ) + + trigger: Optional[ReleaseTriggers] = Field( + xml_attribute=True, + ) diff --git a/osc/obs_api/simple_flag.py b/osc/obs_api/simple_flag.py new file mode 100644 index 00000000..e778ce9a --- /dev/null +++ b/osc/obs_api/simple_flag.py @@ -0,0 +1,24 @@ +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import + + +class SimpleFlag(XmlModel): + XML_TAG = None + XML_TAG_FIELD = "flag" + + def __init__(self, flag): + super().__init__(flag=flag) + + class SimpleFlagChoices(Enum): + ENABLE = "enable" + DISABLE = "disable" + + flag: SimpleFlagChoices = Field( + xml_wrapped=True, + xml_set_tag=True, + ) + + def __eq__(self, other): + if hasattr(other, "flag"): + return self.flag == other.flag + # allow comparing with a string + return self.flag == other diff --git a/osc/obs_api/status.py b/osc/obs_api/status.py new file mode 100644 index 00000000..458f4cb6 --- /dev/null +++ b/osc/obs_api/status.py @@ -0,0 +1,42 @@ +import textwrap + +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import +from .status_data import StatusData + + +class Status(XmlModel): + XML_TAG = "status" + + code: str = Field( + xml_attribute=True, + description=textwrap.dedent( + """ + Status code returned by the server. + """ + ), + ) + + summary: Optional[str] = Field( + description=textwrap.dedent( + """ + Human readable summary. + """ + ), + ) + + details: Optional[str] = Field( + description=textwrap.dedent( + """ + Detailed, human readable information. + """ + ), + ) + + data_list: Optional[List[StatusData]] = Field( + xml_name="data", + description=textwrap.dedent( + """ + Additional machine readable data. + """ + ), + ) diff --git a/osc/obs_api/status_data.py b/osc/obs_api/status_data.py new file mode 100644 index 00000000..234e91b6 --- /dev/null +++ b/osc/obs_api/status_data.py @@ -0,0 +1,31 @@ +import textwrap + +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import + + +class StatusData(XmlModel): + XML_TAG = "data" + + class NameEnum(str, Enum): + SOURCEPROJECT = "sourceproject" + SOURCEPACKAGE = "sourcepackage" + TARGETPROJECT = "targetproject" + TARGETPACKAGE = "targetpackage" + + name: NameEnum = Field( + xml_attribute=True, + description=textwrap.dedent( + """ + Key. + """ + ), + ) + + value: str = Field( + xml_set_text=True, + description=textwrap.dedent( + """ + Value. + """ + ), + )