From e83eb0de546f0a6e49cf930d98e590761bc312d4 Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: May 13 2024 07:47:01 +0000 Subject: [PATCH 1/13] Python typing stubs baseline Related: https://pagure.io/koji/issue/3708 --- diff --git a/koji/__init__.pyi b/koji/__init__.pyi new file mode 100644 index 0000000..e188937 --- /dev/null +++ b/koji/__init__.pyi @@ -0,0 +1,2843 @@ +# This library is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this library; if not, see . + + +""" +Koji - type stubs + +Typing annotations stub for the parts of koji used by koji smoky +dingo. In particular there are annotations for the virtual XMLRPC +methods on the ClientSession class which should help check that the +calls are being used correctly. + +:author: Christopher O'Brien +:license: GPL v3 +""" + +import io +from types import ModuleType +import requests +import xml.sax.handler +from configparser import ConfigParser, RawConfigParser +from optparse import Values +from datetime import datetime +from typing import ( + Any, Dict, List, Optional, Tuple, TypeAlias, TypedDict, Union, Set, + Callable, Self, Collection, Sequence, IO, Generator, Iterable +) +from xmlrpc.client import DateTime + + +__version__: str +__version_info__: Tuple[int] + +_StrDict: TypeAlias = Dict[str, Any] +_Options: TypeAlias = Optional[_StrDict] + +# simple aliases +_ArchesType: TypeAlias = Union[str, Iterable[str]] +_Timestamp: TypeAlias = Union[str, float] + + +# types + +class _ArchiveInfo(TypedDict): + """ + Data representing a koji archive. These are typically obtained via + the ``getArchive`` or ``listArchives`` XMLRPC calls + """ + + btype: str + """ Name of this archive's koji BType. eg. 'maven' or 'image' """ + + btype_id: int + """ ID of this archive's koji BType """ + + build_id: int + """ ID of koji build owning this archive """ + + buildroot_id: int + """ ID of the koji buildroot used to produce this archive """ + + checksum: str + """ hex representation of the checksum for this archive """ + + checksum_type: int + """ type of cryptographic checksum used in the `checksum` field """ + + extra: dict + """ additional metadata provided by content generators """ + + filename: str + """ base filename for this archive """ + + id: int + """ internal ID """ + + metadata_only: bool + + size: int + """ filesize in bytes """ + + type_description: str + """ this archive's type description """ + + type_extensions: str + """ space-delimited extensions shared by this archive's type """ + + type_id: int + """ ID of the archive's type """ + + type_name: str + """ name of the archive's type. eg. 'zip' or 'pom' """ + + artifact_id: str + """ Only present on maven archives. The maven artifact's name """ + + group_id: str + """ Only present on maven archives. The maven artifact's group """ + + version: str + """ Only present on maven archives. The maven artifact's version """ + + platforms: List[str] + """ Only present on Windows archives """ + + relpath: str + """ Only present on Windows archives """ + + flags: str + """ Only present on Windows archives """ + + arch: str + """ Only present on Image archives """ + + +_ArchiveInfos = Collection[_ArchiveInfo] +""" An Collection of _ArchiveInfo dicts """ + + +class _ArchiveTypeInfo(TypedDict): + + description: str + """ short title of the type """ + + extensions: str + """ space separated extensions for this type """ + + id: int + """ the internal ID of the archive type """ + + name: str + """ the name of the archive type """ + + +class _BTypeInfo(TypedDict): + id: int + """ the internal ID of the btype """ + + name: str + """ the name of the btype """ + + +class _BuildInfo(TypedDict): + """ + Data representing a koji build. These are typically obtained via + the ``getBuild`` XMLRPC call. + """ + + build_id: int + """ The internal ID for the build record """ + + cg_id: int + """ The ID of the content generator which has reserved or produced + this build """ + + cg_name: str + """ The name of the content generator which has reserved or produced + this build """ + + completion_time: str + """ ISO-8601 formatted UTC datetime stamp indicating when this build + was completed """ + + completion_ts: float + """ UTC timestamp indicating when this build was completed """ + + creation_event_id: int + """ koji event ID at the creation of this build record """ + + creation_time: str + """ ISO-8601 formatted UTC datetime stamp indicating when this build + record was created """ + + creation_ts: float + """ UTC timestamp indicating when this build record was created """ + + epoch: str + """ epoch of this build, or None if unspecified. This field is + typically only used for RPM builds which have specified an epoch + in their spec. """ + + extra: dict + """ flexible additional information for this build, used by content + generators """ + + id: int + """ Same as build_id """ + + name: str + """ The name component of the NVR of this build. Should match the + package_name field. """ + + nvr: str + """ The unique NVR of the build, comprised of the name, version, and + release separated by hyphens """ + + owner_id: int + """ ID of the koji user that owns this build """ + + owner_name: str + """ name of the koji user that owns this build """ + + package_id: int + """ The corresponding package ID for this build. """ + + package_name: str + """ The corresponding package name for this build. Should match the + name field. """ + + release: str + source: str + start_time: str + start_ts: float + + state: int + """ state of the build, see `BuildState` """ + + task_id: int + + version: str + """ version portion of the NVR for the build """ + + volume_id: int + """ ID of the storage volume that the archives for this build will be + stored on """ + + volume_name: str + """ name of the storage that the archives for this build will be + stored on """ + + maven_group_id: Optional[str] + """ only present on Maven builds which have been loaded with type + information """ + + maven_artifact_id: Optional[str] + """ only present on Maven builds which have been loaded with type + information """ + + maven_version: Optional[str] + """ only present on Maven builds which have been loaded with type + information """ + + platform: Optional[str] + """ only present on Windows builds which have been loaded with type + information """ + + tag_name: Optional[str] + """ only present in listTagged output""" + + create_event: Optional[int] + """ only present in listTagged output""" + + +_BuildInfos: TypeAlias = Collection[_BuildInfo] +""" +An Collection of _BuildInfo dicts +""" + + +class _BuildrootInfo(TypedDict): + arch: str + br_type: int + + cg_id: Optional[int] + cg_name: Optional[str] + cg_version: Optional[str] + + container_arch: str + container_type: str + + create_event_id: int + create_event_time: str + create_ts: float + + extra: Optional[dict] + + host_arch: Optional[str] + host_id: int + host_name: str + host_os: Optional[str] + + id: int + + repo_create_event_id: int + repo_create_event_time: str + + repo_id: int + repo_state: int + + retire_event_id: int + retire_event_time: str + retire_ts: float + + state: int + + tag_id: int + tag_name: str + + task_id: int + + workdir: str + + +_BuildRootInfos: TypeAlias = Collection[_BuildrootInfo] + + +class _BuildTarget(TypedDict): + id: int + build_tag: int + dest_tag: int + name: str + build_tag_name: str + dest_tag_name: str + + +class _ChannelInfo(TypedDict): + id: int + """ internal channel ID """ + + name: str + """ channel name """ + + +_ChannelInfos: TypeAlias = Collection[_ChannelInfo] + + +class _CGInfo(TypedDict): + """ + Data representing a koji Content Generator. A dict of these are + typically obtained via the ``listCGs`` XMLRPC call, mapping their + friendly names to the _CGInfo structure + """ + + id: int + """ internal identifier """ + + users: List[str] + """ list of account names with access to perform CGImports using + this content generator """ + + +class _Event(TypedDict): + id: int + ts: float + + +class _ExternalRepo(TypedDict): + id: int + name: str + url: str + + +_ExternalRepos: TypeAlias = Collection[_ExternalRepo] + + +class _HostInfo(TypedDict): + """ + Data representing a koji host. These are typically obtained via the + ``getHost`` XMLRPC call + """ + + arches: str + """ space-separated list of architectures this host can handle """ + + capacity: float + """ maximum capacity for tasks, using the sum of the task weight + values """ + + comment: str + """ text describing the current status or usage """ + + description: str + """ text describing this host """ + + enabled: bool + """ whether this host is configured by the hub to take tasks """ + + id: int + """ internal identifier """ + + name: str + """ user name of this host's account, normally FQDN. """ + + ready: bool + """ whether this host is reporting itself as active and prepared to + accept tasks """ + + task_load: float + """ the load of currently running tasks on the host. Compared with the + capacity and a given task's weight, this can determine whether a + task will 'fit' on the host """ + + user_id: int + """ the user ID of this host's account. Hosts have a user account of + type HOST, which is how they authenticate with the hub """ + + +class _ListTaskOpts(TypedDict, total=False): + """Specific filter dictionary for listTasks API call""" + arch: Iterable[str] + not_arch: Iterable[str] + state: Iterable[int] + not_state: Iterable[int] + owner: Union[int, Iterable[int]] + not_owner: Union[int, Iterable[int]] + host_id: Union[int, Iterable[int]] + not_host_id: Union[int, Iterable[int]] + channel_id: Union[int, Iterable[int]] + not_channel_id: Union[int, Iterable[int]] + parent: Union[int, Iterable[int]] + not_parent: Union[int, Iterable[int]] + decode: bool + method: str + createdBefore: Union[float, str] + createdAfter: Union[float, str] + startedBefore: Union[float, str] + startedAfter: Union[float, str] + completeBeforer: Union[float, str] + completeAfter: Union[float, str] + + +class _PackageInfo(TypedDict): + """ + ``getPackage`` XMLRPC call. + """ + + id: int + """ + the internal ID for this package + """ + + name: str + """ + the package name + """ + + +class _PermInfo(TypedDict): + id: int + name: str + + +class _QueryOptsType(TypedDict, total=False): + """Various API calls use queryOpts dictionary for altering output format""" + countOnly: bool + order: str + offset: int + limit: int + group: str + asList: bool + + +class _RepoInfo(TypedDict): + """ + Data representing a koji build tag's repository. These are + typically obtained via the ``getRepo`` or ``repoInfo`` XMLRPC + calls. + """ + + create_event: int + """ koji event ID representing the point that the repo's tag + configuration was snapshot from. Note that this doesn't always + correlate to the creation time of the repo -- koji has the ability to + generate a repository based on older events """ + + create_ts: float + """ UTC timestamp indicating when this repo was created """ + + creation_time: str + """ ISO-8601 formatted UTC datetime stamp indicating when this repo + was created """ + + dist: bool + """ whether this is a dist-repo or not """ + + id: int + """ internal ID for this repository """ + + state: int + """ the current state of this repository """ + + tag_id: int + """ ID of the tag from which this repo was generated. This value is not + present in the output of the ``getRepo`` XMLRPC call as it is presumed + that the caller already knows the tag's identity """ + + tag_name: str + """ name of the tag from which this repo was generated. This value is + not present in the output of the ``getRepo`` XMLRPC call as it is + presumed that the caller already knows the tag's identity """ + + task_id: int + """ ID of the task which generated this repository """ + + +class _RPMInfo(TypedDict): + """ + Data representing a koji RPM. These are typically obtained via the + ``listRPMs`` XMLRPC call, or from the `kojismokydingo.as_rpminfo` + function + """ + + arch: str + """ The RPM's architecture, eg. 'src' or 'x86_64' """ + + build_id: int + """ The ID of the build owning this RPM """ + + buildroot_id: int + """ The buildroot used by the task which produced this RPM """ + + buildtime: int + """ UTC timestamp of the time that this RPM was produced """ + + epoch: str + """ The RPM's epoch field, or None if not defined """ + + external_repo_id: int + """ The external repo ID for this RPM record, or 0 if the RPM was + built in this koji instance rather than being a reference to an + external repository """ + + external_repo_name: str + """ name identifying the repo that this RPM came from, or 'INTERNAL' + if built in this koji instance """ + + extra: dict + """ Optional extra data """ + + id: int + """ The internal ID for this RPM """ + + metadata_only: bool + + name: str + """ The RPM's name field """ + + nvr: str + """ The NVR (Name Version and Release) of the RPM """ + + payloadhash: str + """ The MD5 in hex of the RPM's payload (the content past the + headers) """ + + release: str + """ The RPM's release field """ + + size: int + """ The file size of the unsigned copy of the RPM """ + + version: str + """ The RPM's version field """ + + +_RPMInfos = Collection[_RPMInfo] + + +class _RPMSignature(TypedDict): + """ + Data representing an RPM signature in koji. Obtained via the + ``queryRPMSigs`` XMLRPC API. + """ + + rpm_id: int + sigkey: str + sighash: str + + +class _SearchResult(TypedDict): + """ as returned by the ``search`` XMLRPC call """ + + id: int + """ result ID """ + + name: str + """ result name """ + +_SearchResults: TypeAlias = Collection[_SearchResult] + + +class _TagGroupPackage(TypedDict): + basearchonly: str + blocked: bool + group_id: int + package: str + requires: str + tag_id: int + type: str + + +class _TagGroupReq(TypedDict): + blocked: bool + group_id: int + is_metapkg: bool + name: str + req_id: int + tag_id: int + type: str + + +class _TagInfo(TypedDict): + """ + Data representing a koji tag. Typically obtained via the + ``getTag`` XMLRPC call, or the `kojismokydingo.as_taginfo` and + `kojismokydingo.bulk_load_tags` functions. + """ + + arches: str + """ space-separated list of architectures, or None """ + + extra: Dict[str, str] + """ inheritable additional configuration data """ + + id: int + """ internal ID of this tag """ + + locked: bool + """ when locked, a tag will protest against having addtional builds + associated with it """ + + maven_include_all: bool + """ whether this tag should use the alternative maven-latest logic + (including multiple builds of the same package name) when inherited + by the build tag of a maven-enabled target """ + + maven_support: bool + """ whether this tag should generate a maven repository when it is + the build tag for a target """ + + name: str + + perm: str + """ name of the required permission to associate builds with this tag, + or None """ + + perm_id: int + """ ID of the required permission to associate builds with this tag, + or None """ + + +_TagInfos = Collection[_TagInfo] + + +class _TagInheritanceEntry(TypedDict): + """ + Data representing a single inheritance element. A list of these + represents the inheritance data for a tag. Typically obtained via + the ``getFullInheritance`` XMLRPC call. + """ + + child_id: int + """ the ID of the child tag in the inheritance link. The child tag + inherits from the parent tag """ + + currdepth: int + """ only present from the ``getFullInheritance`` call. The inheritance + depth this link occurs at. A depth of 1 indicates that the child + tag would be the one originally queried for its inheritance tree + """ + + filter: list + """ only present from the ``getFullInheritance`` call. """ + + intransitive: bool + """ if true then this inheritance link would not be inherited. ie. + this link only appears at a depth of 1, and is otherwise omitted. """ + + maxdepth: int + """ additional parents in the inheritance tree from this link are only + considered up to this depth, relative from the link's current + depth. A maxdepth of 1 indicates that only the immediate parents + will be inherited. A maxdepth of 0 indicates that the tag and none + of its parents will be inherited. A value of None indicates no + restriction. """ + + name: str + """ the parent tag's name """ + + nextdepth: int + """ only present from the ``getFullInheritance`` call. """ + + noconfig: bool + """ if True then this inheritance link does not include tag + configuration data, such as extras and groups """ + + parent_id: int + """ the parent tag's internal ID """ + + pkg_filter: str + """ a regex indicating which package entries may be inherited. If empty, + all packages are inherited """ + + priority: int + """ the inheritance link priority, which provides an ordering for + links at the same depth with the same child tag (ie. what order + the parent links for a given tag are processed in). Lower + priorities are processed first. """ + + +_TagInheritance: TypeAlias = Collection[_TagInheritanceEntry] +""" +As returned by the ``getInheritanceData`` and +``getFullInheritance`` XMLRPC calls. A list of inheritance elements +for a tag. +""" + + +class _TagPackageInfo(TypedDict): + """ + ``listPackages`` XMLRPC call. + """ + + blocked: bool + """ if True this entry represents a block """ + + extra_arches: str + """ additional architectures, separated by spaces """ + + owner_id: int + """ ID of the user who is the owner of the package for this tag """ + + owner_name: str + """ name of the user who is the owner of the package for this tag """ + + package_id: int + """ ID of the package """ + + package_name: str + """ name of the package """ + + tag_id: int + """ ID of the package listing's tag """ + + tag_name: str + """ name of the package listing's tag """ + + +class _TargetInfo(TypedDict): + """ + Data representing a koji build target. Typically obtained via the + ``getBuildTarget`` or ``getBuildTargets`` XMLRPC calls, or the + `kojismokydingo.as_targetinfo` function. + """ + + build_tag: int + """ internal ID of the target's build tag """ + + build_tag_name: str + """ name of the target's build tag """ + + dest_tag: int + """ internal ID of the target's destination tag """ + + dest_tag_name: str + """ name of the target's destination tag """ + + id: int + """ internal ID of this build target """ + + name: str + """ name of this build target """ + + +_TargetInfos = Collection[_TargetInfo] + + +class _TaskInfo(TypedDict): + """ + ``getTaskInfo`` XMLRPC call or `kojismokydingo.as_taskinfo` function + """ + + arch: str + """ task architecture, or 'noarch' """ + + awaited: Union[bool, None] + """ True if this task is currently being waiting-for by its parent + task. False if this task is no longer being waited-for. None if + the task was never waited-for. """ + + channel_id: int + """ internal ID of the channel from which a host will be selected to + take this task """ + + completion_time: str + """ ISO-8601 formatted UTC datetime stamp indicating when this task + was completed, or None if not completed """ + + completion_ts: float + """ UTC timestamp indicating when this task was completed, or None if + not completed """ + + create_time: str + """ ISO-8601 formatted UTC datetime stamp indicating when this task + was created """ + + create_ts: float + """ UTC timestamp indicating when this task was created """ + + host_id: int + """ host which has taken this task, or None """ + + id: int + """ internal task ID """ + + label: str + """ task label, or None """ + + method: str + """ task method, indicates the type of work to be done """ + + owner: int + """ ID of the user that initiated this task """ + + parent: int + """ ID of the parent task, or None """ + + priority: int + + start_time: str + """ ISO-8601 formatted UTC datetime stamp indicating when this task + was started by a host, or None if not yet started """ + + start_ts: float + """ UTC timestamp indicating when this task was started by a host, or + None if not yet started """ + + state: int + """ the current state of this task """ + + waiting: Union[bool, None] + """ True if this task is currently waiting for any of its subtasks to + complete. False if this task is not waiting, or None if the task + never needed to wait. """ + + weight: float + """ value which ascribes the general resources needed to perform this + task. hosts have a limit to the number of resources which can be used + to run tasks in parallel """ + + request: List[Any] + """ The task request info. Only present when the request parameter to + the ``getTaskInfo`` call is `True`. Note that the `as_taskinfo` + function does set that parameter to True. """ + + +_TaskInfos: TypeAlias = Collection[_TaskInfo] + + +class _UserInfo(TypedDict): + """ + Data representing a koji user account. These are typically + obtained via the ``getUser`` or ``getLoggedInUser`` XMLRPC calls, + or the ``kojismokydingo.as_userinfo`` function. + """ + + authtype: int + """ Only present from the ``getLoggedInUser`` call """ + + id: int + """ internal identifer """ + + krb_principal: str + """ kerberos principal associated with the user. Only used in koji + before 1.19 or when using the ``getLoggedInUser`` call. """ + + krb_principals: List[str] + """ list of kerberos principals associated with the user. Used in koji + from 1.19 onwards. """ + + name: str + """ the username """ + + status: int + """ status of the account. not present for members from the + ``getGroupMembers`` call. """ + + usertype: int + """ type of the account """ + + +_UserInfos: TypeAlias = Collection[_UserInfo] + + +class _Volume(TypedDict): + id: int + name: str + + +_Volumes: TypeAlias = Collection[_Volume] + + +class _BuildReferences(TypedDict, total=False): + tags: _TagInfos + rpms: _RPMInfos + component_of: List[int] + archives: List[int] + last_used: Optional[int] + + +class _TagGroup(TypedDict): + """ + ``getTagGroups`` XMLRPC call + """ + + biarchonly: bool + blocked: bool + description: str + display_name: str + exported: bool + group_id: int + grouplist: List[_TagGroupReq] + is_default: bool + langonly: str + name: str + packagelist: List[_TagGroupPackage] + tag_id: int + uservisible: bool + + +_TagGroups: TypeAlias = Collection[_TagGroup] + + +# specs +_ArchiveSpec = Union[int, str, _ArchiveInfo] +_BuildSpec: TypeAlias = Union[int, str, _BuildInfo] +_CGSpec: TypeAlias = Union[int, str] +_ChannelSpec = Union[int, str, _ChannelInfo] +_GroupSpec = Union[int, str] +_HostSpec = Union[int, str, _HostInfo] +_PackageSpec = Union[int, str, _PackageInfo] +_RepoSpec = Union[int, _RepoInfo, str, _TagInfo] +_RPMSpec = Union[int, str, _RPMInfo] +_TagSpec = Union[int, str, _TagInfo] +_TargetSpec = Union[int, str, _TargetInfo] +_UserSpec = Union[int, str, _UserInfo] + +# koji/__init__.py part + +class Enum(dict): + def get( + self, + key: Union[str, int], + default: Optional[Union[str, int]] = None): + ... + + def getnum( + self, + key: str, + default: Optional[int] = None) -> int: + ... + + +AUTHTYPE_NORMAL: int +AUTHTYPE_KERB: int +AUTHTYPE_SSL: int +AUTHTYPE_GSSAPI: int + + +REPO_INIT: int +REPO_READY: int +REPO_EXPIRED: int +REPO_DELETED: int +REPO_PROBLEM: int +REPO_MERGE_MODES: Set[str] + +RPM_SIGTAG_GPG: int +RPM_SIGTAG_PGP: int +RPM_SIGTAG_RSA: int +RPM_SIGTAG_MD5: int + +RPM_TAG_HEADERSIGNATURES: int +RPM_TAG_FILEDIGESTALGO: int + +PRIO_DEFAULT: int + +BASEDIR: str + + +AUTHTYPES: Enum +BR_STATES: Enum +BR_TYPES: Enum +BUILD_STATES: Enum +CHECKSUM_TYPES: Enum +REPO_STATES: Enum +TAG_UPDATE_TYPES: Enum +TASK_STATES: Enum +USERTYPES: Enum +USER_STATUS: Enum + + +class Fault: + def __init__( + self, + faultCode: int, + faultString: str, + **extra: Any): + ... + + +class FaultInfo(TypedDict): + faultCode: int + faultString: str + + +class GenericError(Exception): + faultCode: int + fromFault: bool + + +class ActionNotAllowed(GenericError): + ... + + +class AuthError(GenericError): + ... + + +class BuildError(GenericError): + ... + + +class BuildrootError(BuildError): + ... + + +class ParameterError(GenericError): + ... + + +class ConfigurationError(GenericError): + ... + + +class LockError(GenericError): + ... + + +class AuthExpired(AuthError): + ... + + +class AuthLockError(AuthError): + ... + + +class RetryError(AuthError): + ... + + +class TagError(GenericError): + ... + + +class LiveMediaError(GenericError): + ... + + +class ApplianceError(GenericError): + ... + + +class LiveCDError(GenericError): + ... + + +class PathInfo: + topdir: str + + def __init__( + self, + topdir: Optional[str] = None): + ... + + def build( + self, + build: _BuildInfo) -> str: + ... + + def build_logs( + self, + build: _BuildInfo) -> str: + ... + + def distrepo( + self, + repo_id: int, + tag: _TagInfo, + volume: Optional[str]) -> str: + ... + + def imagebuild( + self, + build: _BuildInfo) -> str: + ... + + def mavenbuild( + self, + build: _BuildInfo) -> str: + ... + + def mavenfile( + self, + maveninfo: _ArchiveInfo) -> str: + ... + + def mavenrepo( + self, + maveninfo: _ArchiveInfo) -> str: + ... + + def repo( + self, + repo_id: int, + tag_str: str) -> str: + ... + + def repocache( + self, + tag_str: str) -> str: + ... + + def rpm( + self, + rpminfo: _RPMInfo) -> str: + ... + + def scratch(self) -> str: + ... + + def sighdr( + self, + rinfo: _RPMInfo, + sigkey: str) -> str: + ... + + def signed( + self, + rpminfo: _RPMInfo, + sigkey: str) -> str: + ... + + def task( + self, + task_id: int, + volume: Optional[str] = None) -> str: + ... + + def taskrelpath( + self, + task_id: int) -> str: + ... + + def tmpdir( + self, + volume: Optional[str] = None) -> str: + ... + + def typedir( + self, + build: _BuildInfo, + btype: str) -> str: + ... + + def volumedir( + self, + volume: Optional[str] = None) -> str: + ... + + def winbuild( + self, + build: _BuildInfo) -> str: + ... + + def winfile( + self, + wininfo: _ArchiveInfo) -> str: + ... + + def work( + self, + volume: Optional[str] = None) -> str: + ... + + +pathinfo: PathInfo +PathSpec = Union[str, PathInfo] + + +class MultiCallSession: + def __enter__(self) -> Self: + ... + + def __exit__(self, _type, value, traceback) -> bool: + ... + + def __getattr__(self, name) -> Any: + ... + + ... + + +class ClientSession: + + baseurl: str + opts: Dict[str, Any] + krb_principal: str + logged_in: bool + + def multicall( + self, + strict: bool = False, + batch: Optional[int] = None) -> MultiCallSession: + ... + + def __init__( + self, + baseurl: str, + opts: _Options = None, + sinfo: _Options = None, + auth_method: _Options = None): + ... + + def fastUpload( + self, + localfile: str, + path: str, + name: Optional[str] = None, + callback: Optional[Callable] = None, + blocksize: Optional[int] = None, + overwrite: bool = False, + volume: Optional[str] = None): + ... + + def new_session(self): + ... + + def setSession(self, sinfo: dict): + ... + + def subsession(self) -> Self: + ... + + def uploadWrapper( + self, + localfile: str, + path: str, + name: Optional[str] = None, + callback: Optional[Callable] = None, + blocksize: Optional[int] = None, + overwrite: bool = True, + volume: Optional[str] = None) -> None: + ... + + # API + def _listapi(self) -> List[_StrDict]: + ... + + def CGImport( + self, + metadata: Union[str, _StrDict], + directory: str, + token: Optional[str] = None) -> _BuildInfo: + ... + + def addChannel( + self, + channel_name: str, + description: Optional[str] = None) -> int: + ... + + def addExternalRepoToTag( + self, + tag_info: _TagSpec, + repo_info: _RepoSpec, + priority: int, + merge_mode: str = 'koji', + arches: Optional[str] = None) -> None: + ... + + def addHost( + self, + hostname: str, + arches: List[str], + krb_principal: Optional[str] = None, + force: bool = False) -> int: + ... + + def addHostToChannel( + self, + hostname: _HostSpec, + channel_name: str, + create: bool = False, + force: bool = False) -> None: + ... + + def addRPMSig( + self, + an_rpm: _RPMSpec, + data: str) -> None: + ... + + def addVolume( + self, + name: str, + strict: bool = True) -> _Volume: + ... + + def applyVolumePolicy( + self, + build: _BuildInfo, + strict: bool = False) -> None: + ... + + def assignTask( + self, + task_id: int, + hostname: str, + force: bool = False) -> bool: + ... + + def build( + self, + src: str, + target: _TargetSpec, + opts: Optional[Dict] = None, + priority: Optional[int] = None, + channel: Optional[str] = None) -> int: + ... + + def buildImage( + self, + name: str, + version: str, + arch: _ArchesType, + target: str, + ksfile: str, + img_type: str, + opts: _StrDict, + priority: Optional[int] = None) -> int: + ... + + def buildImageOz( + self, + name: str, + version: str, + arches: _ArchesType, + target: str, + inst_tree: str, + opts: _StrDict, + priority: Optional[int] = None) -> int: + ... + + def buildImageIndirection( + self, + opts: _Options = None, + priority: Optional[int] = None) -> int: + ... + + def buildReferences( + self, + build: _BuildInfo, + limit: Optional[int] = None, + lazy: bool = False) -> _BuildReferences: + ... + + def chainBuild( + self, + srcs: List[List[str]], + target: str, + opts: _Options = None, + priority: Optional[int] = None, + channel: Optional[str] = None) -> int: + ... + + def chainMaven( + self, + builds: _BuildInfos, + target: str, + opts: _Options = None, + priority: Optional[int] = None, + channel: str = 'maven') -> int: + ... + + def changeBuildVolume( + self, + build: _BuildSpec, + volume: str, + strict: bool = True) -> None: + ... + + def count( + self, + methodName: str, + *args: Any, + **kw: Any) -> int: + ... + + def createBuildTarget( + self, + name: str, + build_tag: _TagSpec, + dest_tag: _TagSpec) -> None: + ... + + def createEmptyBuild( + self, + name: str, + version: str, + release: str, + epoch: str, + owner: Optional[_UserSpec] = None) -> int: + ... + + def createImageBuild( + self, + build_info: Union[str, _StrDict]) -> None: + ... + + def createMavenBuild( + self, + build_info: Union[str, _StrDict], + maven_info: _StrDict) -> None: + ... + + def createNotification( + self, + user_id: int, + package_id: Optional[int], + tag_id: Optional[int], + success_only: bool) -> None: + ... + + def createNotificationBlock( + self, + user_id: int, + package_id: Optional[int] = None, + tag_id: Optional[int] = None) -> None: + ... + + def createTag( + self, + name: str, + parent: Optional[Union[int, str]] = None, + arches: Optional[str] = None, + perm: Optional[str] = None, + locked: bool = False, + maven_support: bool = False, + maven_include_all: bool = False, + extra: Optional[Dict[str, str]] = None) -> int: + ... + + def createUser( + self, + username: str, + status: Optional[int] = None, + krb_principal: Optional[str] = None) -> int: + ... + + def createWinBuild( + self, + build_info: Union[str, _StrDict], + win_info: _StrDict) -> None: + ... + + def deleteBuild( + self, + build: _BuildInfo, + strict: bool = False, + min_ref_age: int = 604800) -> bool: + ... + + def deleteBuildTarget( + self, + buildTargetInfo: _TargetSpec) -> None: + ... + + def deleteExternalRepo( + self, + info: _RepoSpec) -> None: + ... + + def deleteNotification( + self, + id: int) -> None: + ... + + def deleteNotificationBlock(self, id: int) -> None: + ... + + def deleteRPMSig( + self, + rpminfo: _RPMSpec, + sigkey: Optional[str] = None, + all_sigs: bool = False) -> None: + ... + + def deleteTag(self, tagInfo: _TagSpec) -> None: + ... + + def disableHost(self, hostname: str) -> None: + ... + + def disableUser(self, username: str) -> None: + ... + + def distRepo( + self, + tag: _TagSpec, + keys: List[str], + **task_opts) -> int: + ... + + def downloadTaskOutput( + self, + taskID: int, + fileName: str, + offset: int = 0, + size: int = -1, + volume: Optional[str] = None) -> bytes: + ... + + def echo(self, *args) -> list: + ... + + def editBuildTarget( + self, + buildTargetInfo: _TargetSpec, + name: str, + build_tag: _TagSpec, + dest_tag: _TagSpec) -> None: + ... + + def editChannel( + self, + channelInfo: _ChannelSpec, + name: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None) -> bool: + ... + + def editExternalRepo( + self, + name: str, + url: Optional[str] = None) -> None: + ... + + def editHost( + self, + hostInfo: _HostSpec, + arches: Optional[List[str]] = None, + capacity: Optional[float] = None, + description: Optional[str] = None, + comment: Optional[str] = None) -> bool: + ... + + def editPermission( + self, + perm: str, + description: str) -> None: + ... + + def editTag2( + self, + taginfo: Union[int, str], + **kwargs) -> None: + ... + + def editTagExternalRepo( + self, + tag_info: _TagSpec, + repo_info: _RepoSpec, + priority: Optional[int] = None, + merge_mode: Optional[str] = None, + arches: Optional[_ArchesType] = None) -> bool: + ... + + def editUser( + self, + userInfo: _UserSpec, + name: Optional[str] = None, + krb_principal_mappings: Optional[List[_StrDict]] = None) -> None: + ... + + def enableHost(self, hostname: str) -> None: + ... + + def enableUser(self, username: str) -> None: + ... + + def exclusiveSession(self, *args, **kwargs) -> None: + ... + + def freeTask(self, task_id: int) -> None: + ... + + def getAllPerms(self) -> List[_PermInfo]: + ... + + def getArchive( + self, + archive_id: _ArchiveSpec, + strict: bool = False) -> _ArchiveInfo: + ... + + def getArchiveType( + self, + filename: Optional[str] = None, + type_name: Optional[str] = None, + type_id: Optional[int] = None, + strict: bool = False) -> _ArchiveTypeInfo: + ... + + def getArchiveTypes(self) -> List[_ArchiveTypeInfo]: + ... + + def getBuild( + self, + buildInfo: Union[int, str], + strict: bool = False) -> _BuildInfo: + ... + + def getBuildConfig( + self, + tag: _TagSpec, + event: Optional[int] = None) -> _TagInfo: + ... + + def getBuildNotification( + self, + id: int, + strict: bool = False) -> Collection[_StrDict]: + ... + + def getBuildNotifications( + self, + userID: Optional[int] = None) -> Collection[_StrDict]: + ... + + def getBuildNotificationBlocks( + self, + userID: Optional[int] = None) -> Collection[_StrDict]: + ... + + def getBuildTarget( + self, + info: Union[int, str], + event: Optional[int] = None, + strict: bool = False) -> _TargetInfo: + ... + + def getBuildTargets( + self, + info: Optional[Union[int, str]] = None, + event: Optional[int] = None, + buildTagID: Optional[int] = None, + destTagID: Optional[int] = None, + queryOpts: Optional[_QueryOptsType] = None) -> _TargetInfos: + ... + + def getBuildType( + self, + buildInfo: Union[int, str], + strict: bool = False) -> Dict[str, dict]: + ... + + def getBuildroot( + self, + buildrootID: int, + strict: bool = False) -> _BuildrootInfo: + ... + + def getChangelogEntries( + self, + buildID: Optional[int] = None, + taskID: Optional[int] = None, + filepath: Optional[str] = None, + author: Optional[str] = None, + before: Optional[_Timestamp] = None, + after: Optional[_Timestamp] = None, + queryOpts: Optional[_QueryOptsType] = None, + strict: bool = False) -> Sequence[_StrDict]: + ... + + def getChannel( + self, + channelInfo: Union[int, str], + strict: bool = False) -> _ChannelInfo: + ... + + def getFullInheritance( + self, + tag: Union[int, str], + event: Optional[int] = None, + reverse: bool = False) -> _TagInheritance: + ... + + def getInheritanceData( + self, + tag: Union[int, str], + event: Optional[int] = None) -> _TagInheritance: + ... + + def getGroupMembers( + self, + group: Union[int, str]) -> _UserInfos: + ... + + def getHost( + self, + hostInfo: Union[int, str], + strict: bool = False, + event: Optional[int] = None) -> _HostInfo: + ... + + def getKojiVersion(self) -> str: + ... + + def getLastHostUpdate( + self, + hostID: int, + ts: bool = False) -> Union[str, float, None]: + ... + + def getLastEvent( + self, + before: Optional[float] = None) -> _Event: + ... + + def getLatestBuilds( + self, + tag: Union[int, str], + event: Optional[int] = None, + package: Optional[Union[int, str]] = None, + type: Optional[str] = None) -> List[_BuildInfo]: + ... + + def getLatestMavenArchives( + self, + tag: Union[int, str], + event: Optional[int] = None, + inherit: bool = True) -> List[_ArchiveInfo]: + ... + + def getLatestRPMS( + self, + tag: Union[int, str], + package: Optional[Union[int, str]] = None, + arch: Optional[str] = None, + event: Optional[int] = None, + rpmsigs: bool = False, + type: Optional[str] = None) -> Tuple[List[_RPMInfo], + List[_BuildInfo]]: + ... + + def getLoggedInUser(self) -> _UserInfo: + ... + + def getMavenBuild( + self, + buildInfo: _BuildSpec, + strict: bool = False) -> _StrDict: + ... + + def getPackage( + self, + info: Union[int, str], + strict: bool = False, + create: bool = False) -> _PackageInfo: + ... + + def getPackageID( + self, + name: str, + strict: bool = False) -> int: + ... + + def getPerms(self) -> List[str]: + ... + + def getRepo( + self, + tag: Union[int, str], + state: Optional[_RepoState] = None, + event: Optional[int] = None, + dist: bool = False) -> _RepoInfo: + ... + + def getRPM( + self, + rpminfo: _RPMSpec, + strict: bool = False, + multi: bool = False) -> Union[_RPMInfo, List[_RPMInfo]]: + ... + + def getTag( + self, + taginfo: Union[int, str], + strict: bool = False, + event: Optional[int] = None, + blocked: bool = False) -> _TagInfo: + ... + + def getTagID( + self, + info: _TagSpec, + strict: bool = False, + create: bool = False) -> int: + ... + + def getTagExternalRepos( + self, + tag_info: Optional[_TagSpec] = None, + repo_info: Optional[_RepoSpec] = None, + event: Optional[int] = None) -> _ExternalRepos: + ... + + def getTagGroups( + self, + tag: Union[int, str], + event: Optional[int] = None, + inherit: bool = True, + incl_pkgs: bool = True, + incl_reqs: bool = True, + incl_blocked: bool = False) -> _TagGroups: + ... + + def getTaskInfo( + self, + task_id: Union[int, List[int]], + request: bool = False, + strict: bool = False) -> Union[_TaskInfo, _TaskInfos]: + ... + + def getTaskChildren( + self, + task_id: int, + request: bool = False, + strict: bool = False) -> _TaskInfos: + ... + + def getTaskResult( + self, + taskId: int, + raise_fault: bool = True) -> dict: + ... + + def getUser( + self, + userInfo: Optional[_UserSpec] = None, + strict: bool = False, + krb_princs: bool = True) -> _UserInfo: + ... + + def getUserPerms( + self, + userID: Optional[_UserSpec] = None) -> List[str]: + ... + + def getVolume( + self, + volume: str, + strict: bool = False) -> _Volume: + ... + + def getWinBuild( + self, + buildInfo: _BuildSpec, + strict: bool = False) -> _StrDict: + ... + + def grantCGAccess( + self, + user: _UserSpec, + cg: _CGSpec, + create: bool = False) -> None: + ... + + def grantPermission( + self, + userinfo: _UserSpec, + permission: str, + create: bool = False, + description: Optional[str] = None) -> None: + ... + + def groupListAdd( + self, + taginfo: _TagSpec, + grpinfo: _GroupSpec, + block: bool = False, + force: bool = False, + **opts) -> None: + ... + + def groupListBlock( + self, + taginfo: _TagSpec, + grpinfo: _GroupSpec) -> None: + ... + + def groupListRemove( + self, + taginfo: _TagSpec, + grpinfo: _GroupSpec) -> None: + ... + + def groupPackageListAdd( + self, + taginfo: _TagSpec, + grpinfo: _GroupSpec, + pkg_name: str, + block: bool = False, + force: bool = False, + **opts) -> None: + ... + + def groupPackageListBlock( + self, + taginfo: _TagSpec, + grpinfo: _GroupSpec, + pkg_name: str) -> None: + ... + + def groupPackageListUnblock( + self, + taginfo: _TagSpec, + grpinfo: _GroupSpec, + pkg_name: str) -> None: + ... + + def groupReqListAdd( + self, + taginfo: _TagSpec, + grpinfo: _GroupSpec, + reqinfo: _GroupSpec, + force: bool = False, + **opts) -> None: + ... + + def groupReqListBlock( + self, + taginfo: _TagSpec, + grpinfo: _GroupSpec, + reqinfo: _GroupSpec) -> None: + ... + + def groupReqListUnblock( + self, + taginfo: _TagSpec, + grpinfo: _GroupSpec, + reqinfo: _GroupSpec) -> None: + ... + + def gssapi_login( + self, + principal: Optional[str] = None, + keytab: Optional[str] = None, + ccache: Optional[str] = None, + proxyuser: Optional[str] = None) -> bool: + ... + + def hasPerm( + self, + perm: str, + strict: bool = False) -> bool: + ... + + def importArchive( + self, + filepath: str, + buildinfo: Union[_StrDict, _BuildInfo], + type: str, + typeInfo: _StrDict) -> None: + ... + + def importRPM( + self, + path: str, + basename: str) -> None: + ... + + def listArchives( + self, + buildID: Optional[int] = None, + buildrootID: Optional[int] = None, + componentBuildrootID: Optional[int] = None, + hostID: Optional[int] = None, + type: Optional[str] = None, + filename: Optional[str] = None, + size: Optional[int] = None, + checksum: Optional[str] = None, + typeInfo: Optional[dict] = None, + queryOpts: Optional[_QueryOptsType] = None, + imageID: Optional[int] = None, + archiveID: Optional[int] = None, + strict: bool = False) -> List[_ArchiveInfo]: + ... + + def listBTypes( + self, + query: Optional[Dict[str, str]] = None, + queryOpts: Optional[_QueryOptsType] = None) -> List[_BTypeInfo]: + ... + + def listBuildroots( + self, + hostID: Optional[int] = None, + tagID: Optional[int] = None, + state: Optional[int] = None, + rpmID: Optional[int] = None, + archiveID: Optional[int] = None, + taskID: Optional[int] = None, + buildrootID: Optional[int] = None, + queryOpts: Optional[_QueryOptsType] = None) -> BuildRootInfos: + ... + + def listBuilds( + self, + packageID: Optional[_PackageSpec] = None, + userID: Optional[_UserSpec] = None, + taskID: Optional[int] = None, + prefix: Optional[str] = None, + state: Optional[int] = None, + volumeID: Optional[int] = None, + source: Optional[str] = None, + createdBefore: Optional[_Timestamp] = None, + createdAfter: Optional[_Timestamp] = None, + completeBefore: Optional[_Timestamp] = None, + completeAfter: Optional[_Timestamp] = None, + type: Optional[str] = None, + typeInfo: Optional[dict[str, Any]] = None, + queryOpts: Optional[_QueryOptsType] = None, + pattern: Optional[str] = None, + cgID: Optional[int] = None) -> _BuildInfos: + ... + + def listCGs(self) -> Dict[str, _CGInfo]: + ... + + def listChannels( + self, + hostID: Optional[_HostSpec] = None, + event: Optional[int] = None, + enabled: Optional[bool] = None) -> _ChannelInfos: + ... + + def listExternalRepos( + self, + info: Optional[Union[str, int]] = None, + url: Optional[str] = None, + event: Optional[int] = None, + queryOpts: Optional[_QueryOptsType] = None) -> _ExternalRepos: + ... + + def listHosts( + self, + arches: Optional[_ArchesType] = None, + channelID: Optional[int] = None, + ready: Optional[bool] = None, + enabled: Optional[bool] = None, + userID: Optional[int] = None, + queryOpts: Optional[_QueryOptsType] = None) -> List[_HostInfo]: + ... + + def listPackages( + self, + tagID: Optional[int] = None, + userID: Optional[int] = None, + pkgID: Optional[int] = None, + prefix: Optional[str] = None, + inherited: bool = False, + with_dups: bool = False, + event: Optional[int] = None, + queryOpts: Optional[_QueryOptsType] = None, + with_owners: bool = True) -> List[_TagPackageInfo]: + ... + + def listRPMs( + self, + buildID: Optional[int] = None, + buildrootID: Optional[int] = None, + imageID: Optional[int] = None, + componentBuildrootID: Optional[int] = None, + hostID: Optional[int] = None, + arches: Optional[str] = None, + queryOpts: Optional[_QueryOptsType] = None) -> List[_RPMInfo]: + ... + + def listTagged( + self, + tag: Union[int, str], + event: Optional[int] = None, + inherit: bool = False, + prefix: Optional[str] = None, + latest: bool = False, + package: Optional[_PackageSpec] = None, + owner: Optional[_UserSpec] = None, + type: Optional[str] = None) -> List[_BuildInfo]: + ... + + def listTaggedArchives( + self, + tag: Union[int, str], + event: Optional[int] = None, + inherit: bool = False, + latest: bool = False, + package: Optional[Union[int, str]] = None, + type: Optional[str] = None) -> Tuple[List[_ArchiveInfo], + List[_BuildInfo]]: + ... + + def listTaggedRPMS( + self, + tag: _TagSpec, + event: Optional[int] = None, + inherit: bool = False, + latest: Union[bool, int] = False, + package: Optional[_PackageSpec] = None, + arch: Optional[str] = None, + rpmsigs: bool = False, + owner: Optional[str] = None, + type: Optional[str] = None, + strict: bool = True, + extra: bool = True) -> _RPMInfos: + ... + + def listTags( + self, + build: Optional[Union[int, str]] = None, + package: Optional[Union[int, str]] = None, + perms: bool = True, + queryOpts: Optional[_QueryOptsType] = None, + pattern: Optional[str] = None) -> List[_TagInfo]: + ... + + def listTasks( + self, + opts: Optional[_ListTaskOpts] = None, + queryOpts: Optional[_QueryOptsType] = None) -> _TaskInfos: + ... + + def listVolumes(self) -> _Volumes: + ... + + def login( + self, + opts: Optional[Dict[str, Any]] = None) -> bool: + ... + + def logout(self, session_id: Optional[int] = None) -> None: + ... + + def makeTask(self, *args, **kwargs) -> int: + ... + + def massTag( + self, + tag: Union[int, str], + builds: List[str]) -> None: + ... + + def mavenBuild( + self, + url: str, + target: str, + opts: _Options = None, + priority: Optional[int] = None, + channel: str = 'maven') -> int: + ... + + def mavenEnabled(self) -> bool: + ... + + def moveBuild( + self, + tag1: _TagSpec, + tag2: _TagSpec, + build: _BuildSpec, + force: bool = False) -> None: + ... + + def moveAllBuilds( + self, + tag1: _TagSpec, + tag2: _TagSpec, + package: _PackageSpec, + force: bool = False) -> List[int]: + ... + + def multiCall( + self, + strict: bool = False, + batch: Optional[int] = None) -> List[Union[FaultInfo, List[Any]]]: + ... + + def newRepo( + self, + tag: _TagSpec, + event: Optional[_Event] = None, + src: bool = False, + debuginfo: bool = False, + separate_src: bool = False) -> int: + ... + + def packageListAdd( + self, + taginfo: Union[int, str], + pkginfo: str, + owner: Optional[Union[int, str]] = None, + block: Optional[bool] = None, + exta_arches: Optional[str] = None, + force: bool = False, + update: bool = False): + ... + + def packageListBlock( + self, + taginfo: _TagSpec, + pkginfo: _PackageSpec, + force: bool = False) -> None: + ... + + def packageListRemove( + self, + taginfo: _TagSpec, + pkginfo: _PackageSpec, + force: bool = False) -> None: + ... + + def packageListSetOwner( + self, + taginfo: _TagSpec, + pkginfo: _PackageSpec, + owner: str, + force: bool = False) -> None: + ... + + def queryHistory( + self, + tables: Optional[List[str]] = None, + **kwargs: Any) -> Dict[str, List[Dict[str, Any]]]: + ... + + def queryRPMSigs( + self, + rpm_id: Optional[int] = None, + sigkey: Optional[str] = None, + queryOpts: Optional[_QueryOptsType] = None) -> List[_RPMSignature]: + ... + + def removeExternalRepoFromTag( + self, + tag_info: _TagSpec, + repo_info: _RepoSpec) -> None: + ... + + def removeHostFromChannel( + self, + hostname: _HostSpec, + channel_name: str) -> None: + ... + + def repoInfo( + self, + repo_id: int, + strict: bool = False) -> _RepoInfo: + ... + + def restartHosts( + self, + priority: int = 5, + options: _Options = None) -> int: + ... + + def resubmitTask( + self, + taskID: int) -> int: + ... + + def revokeCGAccess( + self, + user: _UserSpec, + cg: _CGSpec) -> None: + ... + + def revokePermission( + self, + userinfo: _UserSpec, + permission: str) -> None: + ... + + def search( + self, + terms: str, + type: str, + matchType: str, + queryOpts: Optional[_QueryOptsType] = None) -> _SearchResults: + ... + + def setInheritanceData( + self, + tag: Union[int, str], + data: _TagInheritance, + clear: bool = False) -> None: + ... + + def setTaskPriority( + self, + task_id: int, + priority: int, + recurse: bool = True) -> None: + ... + + def snapshotTag( + self, + src: _TagSpec, + dst: _TagSpec, + config: bool = True, + pkgs: bool = True, + builds: bool = True, + groups: bool = True, + latest_only: bool = True, + inherit_builds: bool = True, + event: Optional[int] = None, + force: bool = False) -> None: + ... + + def snapshotTagModify( + self, + src: _TagSpec, + dst: _TagSpec, + config: bool = True, + pkgs: bool = True, + builds: bool = True, + groups: bool = True, + latest_only: bool = True, + inherit_builds: bool = True, + event: Optional[int] = None, + force: bool = False, + remove: bool = False) -> None: + ... + + def ssl_login( + self, + cert: Optional[str] = None, + ca: Optional[str] = None, + serverca: Optional[str] = None, + proxyuser: Optional[str] = None) -> bool: + ... + + def tagBuild( + self, + tag: _TagSpec, + build: _BuildSpec, + force: bool = False, + fromtag: Optional[_TagSpec] = None) -> int: + ... + + def tagBuildBypass( + self, + tag: Union[int, str], + build: Union[int, str], + force: bool = False, + notify: bool = False) -> None: + ... + + def tagChangedSinceEvent( + self, + event: int, + taglist: List[int]) -> bool: + ... + + def untagBuildBypass( + self, + tag: Union[int, str], + build: Union[int, str], + strict: bool = True, + force: bool = False, + notify: bool = False) -> None: + ... + + def untaggedBuilds( + self, + name: Optional[str] = None, + queryOpts: Optional[_QueryOptsType] = None) -> _BuildInfos: + ... + + def updateNotification( + self, + id: int, + package_id: Optional[int], + tag_id: Optional[int], + success_only: Optional[bool]) -> None: + ... + + def winBuild( + self, + vm: str, + url: str, + target: str, + opts: _StrDict, + priority: Optional[int] = None, + channel: str = 'vm') -> int: + ... + + def wrapperRPM( + self, + build: _BuildSpec, + url: str, + target: str, + priority: Optional[int] = None, + channel: str = 'maven', + opts: Optional[Dict] = None) -> int: + ... + + def writeSignedRPM( + self, + an_rpm: _RPMSpec, + sigkey: str, + force: bool = False) -> None: + ... + + def getExternalRepo( + self, + info: Union[str, int], + strict: bool = False, + event: Optional[int] = None) -> Optional[_RepoInfo]: + ... + + def getExternalRepoList( + self, + tag_info: _TagSpec, + event: Optional[int] = None) -> Collection[Dict]: + ... + + def createExternalRepo( + self, + name: str, + url: str) -> _ExternalRepo: + ... + + +def convertFault(fault: Fault) -> GenericError: + ... + + +def read_config( + profile_name: str, + user_config: Optional[str] = None) -> _StrDict: + ... + + +def read_config_files( + config_files: List[Union[str, Tuple[str, bool]]], + raw: bool = False) -> Union[ConfigParser, RawConfigParser]: + ... + + +def hex_string(s: str) -> str: + ... + + +def load_json(filepath: str): + ... + + +def dump_json( + filepath: str, + data: Any, + indent: int = 4, + sort_keys: bool = False) -> None: + ... + + +class RawHeader: + def __init__(self, data: bytes): + ... + + def get(self, key: int, default: Any = None): + ... + + def version(self) -> int: + ... + + def dump(self) -> None: + ... + + +def check_NVR( + nvr: Union[str, Dict[str, Union[str, int]]], + strict: bool = False) -> bool: + ... + + +def check_NVRA( + nvra: Union[str, Dict[str, Union[str, int]]], + strict: bool = False) -> bool: + ... + + +def parse_NVR(nvr: str) -> Dict[str, Union[str, int]]: + ... + + +def parse_NVRA(nvra: str) -> Dict[str, Union[str, int]]: + ... + + +def grab_session_options(options) -> Dict[str, Any]: + ... + + +def parse_arches( + arches: str, + to_list: bool = False, + strict: bool = False, + allow_none: bool = False) -> Union[List[str], str]: + ... + + +def canonArch(arch: str) -> str: + ... + + +def is_debuginfo(name: str) -> bool: + ... + + +def _fix_print(value: Union[str, bytes]) -> str: + ... + + +def _open_text_file(path: str, mode: str = 'rt'): + ... + + +def formatTime( + value: Union[int, float, datetime, DateTime]) -> str: + ... + + +def formatTimeLong(value: Any) -> str: + ... + + +def openRemoteFile( + relpath: str, + topurl: Optional[str], + topdir: Optional[str], + tempdir: Optional[str]): + ... + + +def get_rpm_headers( + f: Any, + ts: Optional[int] = None) -> bytes: + ... + + +def get_header_field( + hdr: bytes, + name: str, + src_arch: bool = False) -> Union[str, List[str]]: + ... + + +def get_header_fields( + X: Union[bytes, str], + fields: Optional[Sequence[str]], + src_arch: bool = False) -> Dict[str, Union[str, List[str]]]: + ... + + +def get_rpm_header( + f: Union[bytes, str], + ts: Optional[int] = None) -> bytes: + ... + + +def maven_info_to_nvr(maveinfo: Dict[str, Any]) -> Dict[str, Any]: + ... + + +def genMockConfig( + name: str, + arch: str, + managed: bool = True, + repoid: Optional[int] = None, + tag_name: Optional[str] = None, + **opts) -> str: + ... + + +def buildLabel( + buildInfo: _BuildInfo, + showEpoch: bool = False) -> str: + ... + + +def fixEncoding( + value: Any, + fallback: str = 'iso8859-15', + remove_nonprintable: bool = False) -> str: + ... + + +def fix_encoding( + value: str, + fallback: str = 'iso8859-15', + remove_nonprintable: bool = False) -> str: + ... + + +def add_file_logger( + logger: Any, + fn: str) -> None: + ... + + +def add_mail_logger( + logger: Any, + addr: str) -> None: + ... + + +def add_sys_logger(logger: Any): + ... + + +def remove_log_handler(logger: str, handler: Any): + ... + + +def add_stderr_logger(Any) -> None: + ... + + +def daemonize() -> None: + ... + + +def parse_pom( + path: Optional[str] = None, + contents: Optional[str] = None) -> dict: + ... + + +def pom_to_maven_info(pominfo: _StrDict) -> _StrDict: + ... + + +def taskLabel(taskInfo: _StrDict) -> str: + ... + + +def encode_args(*args, **opts) -> list: + ... + + +def decode_args(*args) -> Tuple[list, dict]: + ... + + +def decode_args2(args, names, strict: bool = True) -> dict: + ... + + +def decode_int(n: Any) -> int: + ... + + +def safe_xmlrpc_loads(s: str) -> dict: + ... + + +def ensuredir(directory: str) -> str: + ... + + +def multibyte(data: bytes) -> int: + ... + + +def find_rpm_sighdr(path: str) -> Tuple[int, int]: + ... + + +def rpm_hdr_size( + f: Union[str, IO], + ofs: Optional[int] = None) -> int: + ... + + +def rip_rpm_sighdr(src: str) -> bytes: + ... + + +def rip_rpm_hdr(src: str) -> bytes: + ... + + +def get_sigpacket_key_id(sigpacket: bytes) -> str: + ... + + +def get_sighdr_key(sighdr: bytes) -> Union[str, None]: + ... + + +class SplicedSigStreamReader(io.RawIOBase): + def __init__( + self, + path: str, + sighdr: bytes, + bufsize: int) -> None: + ... + + def generator(self) -> Generator[bytes, bytes, None]: + ... + + def readable(self) -> bool: + ... + + def readinto( + self, + b: bytes) -> int: + ... + + +def spliced_sig_reader( + path: str, + sighdr: bytes, + bufsize: Optional[int] = 8192) -> io.BufferedReader: + ... + + +def splice_rpm_sighdr( + sighdr: bytes, + src: str, + dst: Optional[str] = None, + bufsize: Optional[int] = 8192, + callback: Optional[Callable] = None) -> str: + ... + + +class POMHandler(xml.sax.handler.ContentHandler): + def __init__(self, values: list, fields: dict) -> None: + ... + + def startElement(self, name: str, attrs: dict) -> None: + ... + + def characters(self, content: str) -> None: + ... + + def endElement(self, name: str) -> None: + ... + + def reset(self) -> None: + ... + + +def mavenLabel(dict) -> str: + ... + + +def make_groups_spec( + grplist: List[_StrDict], + name: str = 'buildsys-build', + buildgroup: Optional[str] = None) -> str: + ... + + +def generate_comps( + groups: List[_StrDict], + expand_groups: bool = False) -> str: + ... + + +def format_exc_plus() -> str: + ... + + +def request_with_retry( + retries: int = 3, + backoff_factor: float = 0.3, + status_forcelist: Sequence[int] = (500, 502, 504, 408, 429), + session: Optional[requests.Session] = None) -> requests.Session: + ... + + +def downloadFile( + url: str, + path: Optional[str] = None, + fo: Optional[IO] = None): + ... + + +def check_rpm_file(rpmfile: Union[IO, str]): + ... + + +def config_directory_contents( + dir_name: str, + strict: bool = False) -> List[str]: + ... + + +def get_profile_module( + profile_name: str, + config: Optional[Values] = None) -> ModuleType: + ... + + +def is_requests_cert_error(e: Exception) -> bool: + ... + + +def is_conn_error(e: Exception) -> bool: + ... + + +def removeNonprintable(value: str) -> str: + ... + + +def fixEncodingRecurse( + value: str, + fallback: Optional[str] = 'iso8859-15', + remove_nonprintable: bool = False): + ... +# +# The end. diff --git a/koji/_version.pyi b/koji/_version.pyi new file mode 100644 index 0000000..2723565 --- /dev/null +++ b/koji/_version.pyi @@ -0,0 +1,4 @@ +from typing import Tuple + +__version_info__: Tuple[int, int, int] +__version__: str diff --git a/koji/policy.pyi b/koji/policy.pyi new file mode 100644 index 0000000..cc3f0a2 --- /dev/null +++ b/koji/policy.pyi @@ -0,0 +1,91 @@ +from typing import ( + Optional, Dict, Callable, List, Iterable, Tuple +) + + +class BaseSimpleTest: + name: Optional[str] = None + + def __init__(self, str: str) -> None: + ... + + def run(self, data: dict) -> None: + ... + + +class TrueTest(BaseSimpleTest): + name: str + + def run(self, data: dict) -> bool: + ... + + +class FalseTest(BaseSimpleTest): + ... + + +class AllTest(TrueTest): + ... + + +class NoneTest(FalseTest): + ... + + +class HasTest(BaseSimpleTest): + field: Optional[str] + ... + + +class BoolTest(BaseSimpleTest): + field: Optional[str] + ... + + +class MatchTest(BaseSimpleTest): + field: Optional[str] + ... + + +class TargetTest(MatchTest): + ... + + +class CompareTest(BaseSimpleTest): + allow_float: bool = True + operators: Dict[str, Callable] + + +class SimpleRuleSet: + + def __init__( + self, + rules: Iterable[str], + tests: Dict[str, Callable]) -> None: + ... + + def parse_rules( + self, + lines: Iterable[str]) -> None: + ... + + def parse_line( + self, + line: str) -> Tuple[List[Callable], bool, str]: + ... + + def get_test_handler(self, str: str): + ... + + def all_actions(self) -> List[str]: + ... + + def apply(self, data: dict) -> str: + ... + + def last_rule(self) -> str: + ... + + +def findSimpleTests(namespace: str) -> Dict[str, BaseSimpleTest]: + ... diff --git a/koji/tasks.pyi b/koji/tasks.pyi new file mode 100644 index 0000000..2cd1c4d --- /dev/null +++ b/koji/tasks.pyi @@ -0,0 +1,268 @@ +from kojismokydingo.types import TaskInfo +from typing import Any, Optional, List, Union, Dict, TypedDict + + +class _HostInfo(TypedDict): + arches: str + capacity: float + comment: str + description: str + enabled: bool + id: int + name: str + ready: bool + task_load: float + user_id: int + + +class _RepoInfo(TypedDict): + create_event: int + create_ts: float + creation_time: str + dist: bool + id: int + state: int + tag_id: int + tag_name: str + task_id: int + + +class _TagInfo(TypedDict): + arches: str + extra: Dict[str, str] + id: int + locked: bool + maven_include_all: bool + maven_support: bool + name: str + perm: str + perm_id: int + + +def scan_mounts(topdir: str) -> List[str]: + ... + + +def umount_all(topdir: str) -> None: + ... + + +def safe_rmtree( + path: str, + unmount: bool = False, + strict: bool = True) -> int: + ... + + +class ServerExit(Exception): + ... + + +class ServerRestart(Exception): + ... + + +def parse_task_params( + method: str, + params: Union[dict, str]) -> dict[str, Any]: + ... + + +LEGACY_SIGNATURES: Dict[str, list] + + +class BaseTaskHandler: + Methods: List[str] + Foreground: bool = ... + id: Any = ... + method: Any = ... + session: Any = ... + options: Any = ... + workdir: Any = ... + logger: Any = ... + manager: Any = ... + + def __init__( + self, + id: int, + method: str, + params: list, + session: Any, + options: dict, + workdir: Optional[str] = ...) -> None: + ... + + def setManager(self, manager: Any) -> None: + ... + + def handler(self) -> None: + ... + + def run(self) -> None: + ... + + def weight(self) -> float: + ... + + def createWorkdir(self) -> None: + ... + + def removeWorkdir(self) -> None: + ... + + def wait( + self, + subtasks: Optional[List[int]] = None, + all: bool = False, + failany: bool = False, + canfail: Optional[bool] = None, + timeout: Optional[int] = None) -> dict: + ... + + def getUploadDir(self) -> str: + ... + + def uploadFile( + self, + filename: str, + relPath: Optional[str] = None, + remoteName: Optional[str] = None, + volume: Optional[str] = None) -> None: + ... + + def uploadTree( + self, + dirpath: str, + flatten: bool = False, + volume: Optional[str] = None) -> None: + ... + + def chownTree( + self, + dirpath: str, + uid: int, + gid: int) -> None: + ... + + def localPath( + self, + relpath: str) -> str: + ... + + def subtask( + self, + method: str, + arglist: list, + **opts: Any) -> int: + ... + + def subtask2( + self, + __taskopts: list, + __method: str, + *args: list, + **kwargs: dict) -> int: + ... + + def find_arch( + self, + arch: str, + host: _HostInfo, + tag: _TagInfo, + preferred_arch: Optional[str] = None) -> str: + ... + + def getRepo( + self, + tag: Any, + builds: Optional[Any] = None, + wait: bool = False) -> _RepoInfo: + ... + + def run_callbacks( + self, + plugin: str, + *args: list, + **kwargs: dict) -> None: + ... + + @property + def taskinfo(self) -> TaskInfo: + ... + + @taskinfo.setter + def taskinfo(self, taskinfo: TaskInfo) -> None: + ... + + +class FakeTask(BaseTaskHandler): + Methods: List[str] + Foreground: bool = ... + + def handler(self, *args: list): + ... + + +class SleepTask(BaseTaskHandler): + def handler(self, n: int) -> None: + ... + + +class ForkTask(BaseTaskHandler): + def handler(self, n: int = 5, m: int = 37) -> None: + ... + + +class WaitTestTask(BaseTaskHandler): + def handler(self, count: int, seconds: int = ...) -> None: + ... + + +class SubtaskTask(BaseTaskHandler): + def handler(self, n: int = ...) -> None: + ... + + +class DefaultTask(BaseTaskHandler): + def handler(self, *args: list, **opts: dict) -> None: + ... + + +class ShutdownTask(BaseTaskHandler): + def handler(self) -> None: + ... + + +class RestartTask(BaseTaskHandler): + def handler(self, host: _HostInfo) -> str: + ... + + +class RestartVerifyTask(BaseTaskHandler): + def handler(self, task_id: int, host: _HostInfo) -> None: + ... + + +class RestartHostsTask(BaseTaskHandler): + def handler(self, options: Optional[Dict[str, Any]] = ...) -> None: + ... + + +class DependantTask(BaseTaskHandler): + def handler( + self, + wait_list: List[int], + task_list: List[int]) -> None: + ... + + +class MultiPlatformTask(BaseTaskHandler): + def buildWrapperRPM( + self, + spec_url: str, + build_task_id: int, + build_target: int, + build: int, + repo_id: int, + **opts: Dict[str, Any]): + ... diff --git a/koji/util.pyi b/koji/util.pyi new file mode 100644 index 0000000..34bf609 --- /dev/null +++ b/koji/util.pyi @@ -0,0 +1,363 @@ +import base64 +import koji + +from typing import ( + Any, + Callable, + Dict, + Iterable, + List, + Optional, + Self, + TypedDict, + Tuple, + Union, +) + + +class _Event(TypedDict): + id: int + ts: float + + +class _TagInfo(TypedDict): + arches: str + extra: Dict[str, str] + id: int + locked: bool + maven_include_all: bool + maven_support: bool + name: str + perm: str + perm_id: int + +# koji/util.py follows + + +DATE_RE: Any +TIME_RE: Any + + +def md5_constructor(*args: Any, **kwargs: Any): + ... + + +def deprecated(message: str) -> None: + ... + + +def formatChangelog(entries: List[str]) -> str: + ... + + +def parseTime(val: str) -> Optional[int]: + ... + + +def checkForBuilds( + session: koji.ClientSession, + tag, + builds, + event, + latest: bool = False) -> bool: + ... + + +def duration(start: float) -> str: + ... + + +def printList(lst: List[str]) -> str: + ... + + +def base64encode( + s: Union[str, bytes], + as_bytes: bool = False): + ... + + +base64decode = base64.b64decode + + +def decode_bytes( + data: bytes, + fallback: str = 'iso8859-15') -> str: + ... + + +def multi_fnmatch( + s: str, + patterns: Union[List[str], str]) -> bool: + ... + + +def dslice( + dict_: Dict[str, Any], + keys: Iterable[str], + strict: bool = True) -> Dict[str, Any]: + ... + + +def dslice_ex( + dict_: Dict[str, Any], + keys: Iterable[str], + strict: bool = True) -> Dict[str, Any]: + ... + + +class DataWalker: + def __init__( + self, + data: Any, + callback: Callable, + kwargs: Optional[dict] = None) -> None: + ... + + def walk(self): + ... + + +def encode_datetime(value: Any) -> str: + ... + + +def encode_datetime_recurse(value: Any): + ... + + +def call_with_argcheck( + func: Callable, + args: list, + kwargs: Optional[dict] = None): + ... + + +def apply_argspec( + argspec: Iterable, + args: Iterable, + kwargs: Optional[dict] = None) -> dict: + ... + + +class HiddenValue: + def __init__(self, value: Any) -> None: + ... + + +class LazyValue: + def __init__( + self, + func: Callable, + args: list, + kwargs: Optional[dict] = None, + cache: bool = False) -> None: + ... + + def get(self): + ... + + +class LazyString(LazyValue): + ... + + +def lazy_eval(value: Any): + ... + + +class LazyDict(dict): + def lazyset( + self, + key: Any, + func: Any, + args: list, + kwargs: Optional[dict] = None, + cache: bool = False) -> None: + ... + + def get(self, *args: Any, **kwargs: Any): + ... + + def copy(self) -> Self: + ... + + def values(self) -> Iterable: + ... + + def items(self) -> Iterable: + ... + + def itervalues(self) -> None: + ... + + def iteritems(self) -> None: + ... + + def pop(self, key: Any, *args: Any, **kwargs: Any): + ... + + def popitem(self) -> Tuple: + ... + + +class LazyRecord: + def __init__(self, base: Optional[Any] = None) -> None: + ... + + def __getattribute__(self, name: Any): + ... + + +def lazysetattr( + object: Any, + name: str, + func: Callable, + args: list, + kwargs: Optional[dict] = None, + cache: bool = False) -> None: + ... + + +class _RetryRmtree(Exception): + ... + + +def rmtree( + path: str, + logger: Optional[Any] = None) -> None: + ... + + +def safer_move(src: str, dst: str) -> None: + ... + + +def move_and_symlink( + src: str, + dst: str, + relative: bool = True, + create_dir: bool = False) -> None: + ... + + +def joinpath( + path: str, + *paths: List[str]) -> str: + ... + + +def eventFromOpts( + session: koji.ClientSession, + opts: Any) -> Optional[_Event]: + ... + + +def filedigestAlgo(hdr: bytes) -> str: + ... + + +def check_sigmd5(filename: str) -> bool: + ... + + +def parseStatus(rv: int, prefix: Union[str, Iterable[str]]) -> str: + ... + + +def isSuccess(rv: int) -> bool: + ... + + +def setup_rlimits( + opts: Any, + logger: Optional[Any] = None) -> None: + ... + + +class adler32_constructor: + def __init__( + self, + arg: str = '') -> None: + ... + + def update(self, arg: Union[str, bytes]) -> None: + ... + + def digest(self) -> bytes: + ... + + def hexdigest(self) -> str: + ... + + def copy(self) -> Self: + ... + + digest_size: int = 4 + block_size: int = 1 + + +def tsort(parts: Iterable) -> list: + ... + + +class MavenConfigOptAdapter: + def __init__( + self, + conf: Any, + section: str) -> None: + ... + + +def maven_opts( + values: dict, + chain: bool = False, + scratch: bool = False) -> dict: + ... + + +def maven_params( + config: Any, + package: str, + chain: bool = False, + scratch: bool = False) -> dict: + ... + + +def wrapper_params( + config: Any, + package: str, + chain: bool = False, + scratch: bool = False) -> dict: + ... + + +def parse_maven_params( + confs: Any, + chain: bool = False, + scratch: bool = False) -> dict: + ... + + +def parse_maven_param( + confs: Any, + chain: bool = False, + scratch: bool = False, + section: Optional[str] = None) -> dict: + ... + + +def parse_maven_chain( + confs: Any, + scratch: bool = False) -> dict: + ... + + +def to_list(lst: Iterable) -> list: + ... + + +def format_shell_cmd( + cmd: List[str], + text_width: int = 80) -> str: + ... From e0c8aac7c846f2d2797adc61d3361b1154e5180d Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: May 13 2024 07:47:01 +0000 Subject: [PATCH 2/13] overload getTaskInfo --- diff --git a/koji/__init__.pyi b/koji/__init__.pyi index e188937..537706a 100644 --- a/koji/__init__.pyi +++ b/koji/__init__.pyi @@ -32,8 +32,9 @@ from configparser import ConfigParser, RawConfigParser from optparse import Values from datetime import datetime from typing import ( - Any, Dict, List, Optional, Tuple, TypeAlias, TypedDict, Union, Set, - Callable, Self, Collection, Sequence, IO, Generator, Iterable + Any, Callable, Collection, Dict, Generator, IO, Iterable, List, + Optional, Self, Sequence, Set, Tuple, TypeAlias, TypedDict, + Union, overload ) from xmlrpc.client import DateTime @@ -1834,13 +1835,23 @@ class ClientSession: incl_blocked: bool = False) -> _TagGroups: ... + @overload def getTaskInfo( self, - task_id: Union[int, List[int]], + task_id: int, + request: bool = False, + strict: bool = False) -> _TaskInfo: + ... + + @overload + def getTaskInfo( + self, + task_id: List[int], request: bool = False, - strict: bool = False) -> Union[_TaskInfo, _TaskInfos]: + strict: bool = False) -> _TaskInfos: ... + def getTaskChildren( self, task_id: int, From c84c6897b5c589622cfeddf0c1505de46c60a787 Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: May 13 2024 07:47:01 +0000 Subject: [PATCH 3/13] additional pyi --- diff --git a/koji/arch.pyi b/koji/arch.pyi new file mode 100644 index 0000000..606c771 --- /dev/null +++ b/koji/arch.pyi @@ -0,0 +1,41 @@ +from _typeshed import Incomplete + +multilibArches: dict[str, tuple[str]] +arches: dict[str, str] + +def legitMultiArchesInSameLib(arch: Incomplete | None = ...): ... +def canCoinstall(arch1, arch2): ... +def archDifference(myarch, targetarch): ... +def score(arch): ... +def isMultiLibArch(arch: Incomplete | None = ...): ... +def getBestArchFromList(archlist, myarch: Incomplete | None = ...): ... +def getArchList(thisarch: Incomplete | None = ...): ... +def getCanonX86Arch(arch): ... +def getCanonARMArch(arch): ... +def getCanonPPCArch(arch): ... +def getCanonSPARCArch(arch): ... +def getCanonX86_64Arch(arch): ... + +def getCanonArch( + skipRpmPlatform: int = ...) -> str: + ... + +canonArch: str + +def getMultiArchInfo(arch=...): ... +def getBestArch(myarch: Incomplete | None = ...): ... +def getBaseArch(myarch: Incomplete | None = ...): ... + +class ArchStorage: + canonarch: Incomplete + basearch: Incomplete + bestarch: Incomplete + compatarches: Incomplete + archlist: Incomplete + multilib: bool + def __init__(self) -> None: ... + legit_multi_arches: Incomplete + def setup_arch(self, arch: Incomplete | None = ..., archlist_includes_compat_arch: bool = ...) -> None: ... + def get_best_arch_from_list(self, archlist, fromarch: Incomplete | None = ...): ... + def score(self, arch): ... + def get_arch_list(self, arch): ... diff --git a/koji/context.pyi b/koji/context.pyi new file mode 100644 index 0000000..17e6bf6 --- /dev/null +++ b/koji/context.pyi @@ -0,0 +1,22 @@ +from _typeshed import Incomplete + + +class _data: + ... + + +class ThreadLocal: + def __init__(self) -> None: + ... + + def __getattr__(self, key: str): + ... + + def __setattr__(self, key: str, value): + ... + + def __delattr__(self, key: str): + ... + + +context: ThreadLocal diff --git a/koji/daemon.pyi b/koji/daemon.pyi new file mode 100644 index 0000000..0f2bdd4 --- /dev/null +++ b/koji/daemon.pyi @@ -0,0 +1,216 @@ +from _typeshed import Incomplete +import io +import logging +from build.lib.koji import ClientSession +import koji +from koji.tasks import safe_rmtree, BaseTaskHandler +from koji.util import ( + adler32_constructor, + base64encode, + dslice, + joinpath, + parseStatus, + to_list, +) +from typing import Any, Optional, Collection, Callable + + +def incremental_upload( + session: koji.ClientSession, + fname: str, + fd: io.IOBase, + path: str, + retries: int = ..., + logger: Optional[logging.Logger] = ...) -> None: + ... + + +def fast_incremental_upload( + session: koji.ClientSession, + fname: str, + fd: io.IOBase, + path: str, + retries: int, + logger: logging.Logger) -> None: + ... + + +def log_output( + session: koji.ClientSession, + path: str, + args: Collection[str], + outfile: str, + uploadpath: str, + cwd: Optional[str] = None, + logerror: bool | int = ..., + append: bool | int = ..., + chroot: Optional[str] = ..., + env: Optional[dict[str, Any]] = ...): + ... + + +class SCM: + types: dict[str, tuple[str]] + + @classmethod + def is_scm_url( + cls, + url: str, + strict: bool = ...): + ... + + logger: logging.Logger + url: str + scheme: str + user: str + host: str + repository: str + module: str + revision: str + use_common: bool + source_cmd: list[str] + scmtype: str + + def __init__( + self, + url: str, + allow_password: bool = ...) -> None: + ... + + def get_info( + self, + keys: list[str] = ...): + ... + + def assert_allowed( + self, + allowed: str = ..., + session: Optional[koji.ClientSession] = ..., + by_config: bool = ..., + by_policy: bool = ..., + policy_data: dict[str, Any] = ...) -> None: + ... + + def assert_allowed_by_config( + self, + allowed: str) -> None: + ... + + def assert_allowed_by_policy( + self, + session: koji.ClientSession, + **extra_data) -> None: + ... + + sourcedir: str + + def checkout( + self, + scmdir: str, + session: Optional[koji.ClientSession] = ..., + uploadpath: Optional[str] = ..., + logfile: Optional[str] = ...): + ... + + def get_source(self): + ... + + +class TaskManager: + options: Incomplete + session: koji.ClientSession + tasks: dict[int, dict] + skipped_tasks: dict[int, float] + pids: dict[int, int] + subsessions: dict[int, int] + handlers: dict[str, BaseTaskHandler] + status: str + restart_pending: bool + ready: bool + hostdata: dict + task_load: float + host_id: int + start_ts: float + logger: logging.Logger + + def __init__( + self, + options, + session: koji.ClientSession) -> None: + ... + + def findHandlers( + self, + vars: dict) -> None: + ... + + def registerHandler( + self, + entry: BaseTaskHandler) -> None: + ... + + def registerCallback( + self, + entry: BaseTaskHandler) -> None: + ... + + def registerEntries( + self, + vars: dict) -> None: + ... + + def scanPlugin( + self, + plugin) -> None: + ... + + def shutdown(self) -> None: + ... + + def updateBuildroots( + self, + nolocal: bool = ...) -> None: + ... + + def updateTasks(self) -> None: + ... + + def getNextTask(self): + ... + + def checkAvailDelay( + self, + task: dict[str, Any], + bin_avail: list, + our_avail: float): + ... + + def cleanDelayTimes(self) -> None: + ... + + def cleanupTask( + self, + task_id: int, + wait: bool = ...): + ... + + def checkSpace(self): + ... + + def readyForTask(self): + ... + + def takeTask( + self, + task: dict): + ... + + def forkTask( + self, + handler: BaseTaskHandler): + ... + + def runTask( + self, + handler: BaseTaskHandler) -> None: + ... diff --git a/koji/plugin.pyi b/koji/plugin.pyi new file mode 100644 index 0000000..5dcb9a3 --- /dev/null +++ b/koji/plugin.pyi @@ -0,0 +1,78 @@ +from _typeshed import Incomplete +from koji.util import encode_datetime_recurse as encode_datetime_recurse +from typing import Callable, Optional + +callbacks: dict[str, list[Callable]] + + +class PluginTracker: + searchpath: Optional[str] + prefix: str + plugins: dict + + def __init__( + self, + path: Optional[str] = ..., + prefix: str = ...) -> None: + ... + + def load( + self, + name: str, + path: Optional[str] = ..., + reload: bool = ...) -> Callable + ... + + def get( + self, + name: str) -> Callable: + ... + + def pathlist(self, path: str) -> str: + ... + + def pathlist(self, path: list[str]) -> list[str]: + ... + + +def export(f: Callable) -> Callable: + ... + + +def export_cli(f: Callable) -> Callable: + ... + + +def export_as(alias: str) -> Callable: + ... + + +def export_in( + module, + alias: Optional[str] = ...) -> Callable: + ... + + +def callback(*cbtypes) -> Callable: + ... + + +def ignore_error(f: Callable) -> Callable: + ... + + +def convert_datetime(f: Callable) -> Callable: + ... + + +def register_callback( + cbtype: str, + func: Callable) -> None: + ... + + +def run_callbacks( + cbtype: str, + *args, + **kws) -> None: + ... diff --git a/koji/rpmdiff.pyi b/koji/rpmdiff.pyi new file mode 100644 index 0000000..b0c9a29 --- /dev/null +++ b/koji/rpmdiff.pyi @@ -0,0 +1,44 @@ +import json +from typing import Any, Optional + + +class BytesJSONEncoder(json.JSONEncoder): + + def default(self, o): + ... + + +class Rpmdiff: + TAGS: tuple[int] + PRCO: tuple[str] + PREREQ_FLAG: int + DEPFORMAT: str + FORMAT: str + ADDED: str + REMOVED: str + result: list[tuple] + old_data: dict[str, Any] + new_data: dict[str, Any] + + def __init__( + self, + old: str, + new: str, + ignore: Optional[str] = ...) -> None: + ... + + def textdiff(self) -> str: + ... + + def differs(self) -> bool: + ... + + def sense2str( + self, + sense: int) -> str: + ... + + def kojihash( + self, + new: bool = ...) -> str: + ... diff --git a/koji/server.pyi b/koji/server.pyi new file mode 100644 index 0000000..6fddfd0 --- /dev/null +++ b/koji/server.pyi @@ -0,0 +1,14 @@ +class ServerError(Exception): + ... + + +class ServerRedirect(ServerError): + ... + + +class BadRequest(ServerError): + ... + + +class RequestTimeout(ServerError): + ... diff --git a/koji/xmlrpcplus.pyi b/koji/xmlrpcplus.pyi new file mode 100644 index 0000000..7b83615 --- /dev/null +++ b/koji/xmlrpcplus.pyi @@ -0,0 +1,44 @@ +import types +import six.moves.xmlrpc_client as xmlrpc_client +from _typeshed import Incomplete +from typing import Callable, Optional, Union + +getparser: Incomplete +loads: Incomplete +Fault: Incomplete +DateTime: Incomplete + + +class ExtendedMarshaller(xmlrpc_client.Marshaller): + dispatch: Incomplete + + def dump_generator( + self, + value: types.GeneratorType, + write: Callable) -> None: + ... + + MAXI8: int + MINI8: int + + def dump_int( + self, + value: int, + write: Callable): + ... + + def dump_re( + self, + value, + write: Callable): + ... + + +def dumps( + params, + methodname: Optional[str] = ..., + methodresponse: Optional[Union[bool, int]] = ..., + encoding: Optional[str] = ..., + allow_none: Union[bool, int] = ..., + marshaller: Optional[xmlrpc_client.Marshaller] = ...) -> str: + ... From 504d8e52d00d1a58f6c0b232cda01ca24148f314 Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: May 13 2024 07:47:01 +0000 Subject: [PATCH 4/13] add py.typed --- diff --git a/koji/Makefile b/koji/Makefile index 2e6a206..0aab67d 100644 --- a/koji/Makefile +++ b/koji/Makefile @@ -5,10 +5,12 @@ PYSCRIPTS = SUBDIRS = PKGDIR = $(shell $(PYTHON) ../devtools/get_site_packages.py )/$(PACKAGE) -ifeq ($(PYVER_MAJOR),2) - PYFILES=$(filter-out db.py,$(PYFILES_ALL)) +ifeq ($(PYVER_MAJOR), 2) + PYFILES=$(filter-out db.py, $(PYFILES_ALL)) + PYIFILES= else PYFILES=$(PYFILES_ALL) + PYIFILES=$(wildcard *.pyi) endif _default: @@ -23,6 +25,9 @@ install: for p in $(PYFILES) ; do \ install -p -m 644 $$p $(DESTDIR)/$(PKGDIR)/$$p; \ done + for p in $(PYIFILES) ; do \ + install -p -m 644 $$p $(DESTDIR)/$(PKGDIR)/$$p; \ + done for p in $(PYSCRIPTS) ; do \ chmod 0755 $(DESTDIR)/$(PKGDIR)/$$p; \ done diff --git a/py.typed b/py.typed new file mode 100644 index 0000000..b258964 --- /dev/null +++ b/py.typed @@ -0,0 +1,2 @@ +partial + diff --git a/setup.py b/setup.py index 91f7d76..0ca1397 100755 --- a/setup.py +++ b/setup.py @@ -69,7 +69,8 @@ setup( 'koji_cli_plugins': 'plugins/cli', }, package_data={ - '': ['README.md'], + '': ['README.md', 'py.typed'], + 'koji': ["*.pyi"], }, # doesn't make sense, as we have only example config # data_files=[ From ce4ea8da806f2a72bbe6def56edab6776253b4cb Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: May 13 2024 07:47:01 +0000 Subject: [PATCH 5/13] replace Collections with Lists --- diff --git a/koji/__init__.pyi b/koji/__init__.pyi index 537706a..267f64d 100644 --- a/koji/__init__.pyi +++ b/koji/__init__.pyi @@ -32,7 +32,7 @@ from configparser import ConfigParser, RawConfigParser from optparse import Values from datetime import datetime from typing import ( - Any, Callable, Collection, Dict, Generator, IO, Iterable, List, + Any, Callable, Dict, Generator, IO, Iterable, List, Optional, Self, Sequence, Set, Tuple, TypeAlias, TypedDict, Union, overload ) @@ -124,8 +124,8 @@ class _ArchiveInfo(TypedDict): """ Only present on Image archives """ -_ArchiveInfos = Collection[_ArchiveInfo] -""" An Collection of _ArchiveInfo dicts """ +_ArchiveInfos = List[_ArchiveInfo] +""" An List of _ArchiveInfo dicts """ class _ArchiveTypeInfo(TypedDict): @@ -262,9 +262,9 @@ class _BuildInfo(TypedDict): """ only present in listTagged output""" -_BuildInfos: TypeAlias = Collection[_BuildInfo] +_BuildInfos: TypeAlias = List[_BuildInfo] """ -An Collection of _BuildInfo dicts +An List of _BuildInfo dicts """ @@ -312,7 +312,7 @@ class _BuildrootInfo(TypedDict): workdir: str -_BuildRootInfos: TypeAlias = Collection[_BuildrootInfo] +_BuildRootInfos: TypeAlias = List[_BuildrootInfo] class _BuildTarget(TypedDict): @@ -332,7 +332,7 @@ class _ChannelInfo(TypedDict): """ channel name """ -_ChannelInfos: TypeAlias = Collection[_ChannelInfo] +_ChannelInfos: TypeAlias = List[_ChannelInfo] class _CGInfo(TypedDict): @@ -361,7 +361,7 @@ class _ExternalRepo(TypedDict): url: str -_ExternalRepos: TypeAlias = Collection[_ExternalRepo] +_ExternalRepos: TypeAlias = List[_ExternalRepo] class _HostInfo(TypedDict): @@ -563,7 +563,7 @@ class _RPMInfo(TypedDict): """ The RPM's version field """ -_RPMInfos = Collection[_RPMInfo] +_RPMInfos = List[_RPMInfo] class _RPMSignature(TypedDict): @@ -586,7 +586,7 @@ class _SearchResult(TypedDict): name: str """ result name """ -_SearchResults: TypeAlias = Collection[_SearchResult] +_SearchResults: TypeAlias = List[_SearchResult] class _TagGroupPackage(TypedDict): @@ -649,7 +649,7 @@ class _TagInfo(TypedDict): or None """ -_TagInfos = Collection[_TagInfo] +_TagInfos = List[_TagInfo] class _TagInheritanceEntry(TypedDict): @@ -708,7 +708,7 @@ class _TagInheritanceEntry(TypedDict): priorities are processed first. """ -_TagInheritance: TypeAlias = Collection[_TagInheritanceEntry] +_TagInheritance: TypeAlias = List[_TagInheritanceEntry] """ As returned by the ``getInheritanceData`` and ``getFullInheritance`` XMLRPC calls. A list of inheritance elements @@ -772,7 +772,7 @@ class _TargetInfo(TypedDict): """ name of this build target """ -_TargetInfos = Collection[_TargetInfo] +_TargetInfos = List[_TargetInfo] class _TaskInfo(TypedDict): @@ -854,7 +854,7 @@ class _TaskInfo(TypedDict): function does set that parameter to True. """ -_TaskInfos: TypeAlias = Collection[_TaskInfo] +_TaskInfos: TypeAlias = List[_TaskInfo] class _UserInfo(TypedDict): @@ -889,7 +889,7 @@ class _UserInfo(TypedDict): """ type of the account """ -_UserInfos: TypeAlias = Collection[_UserInfo] +_UserInfos: TypeAlias = List[_UserInfo] class _Volume(TypedDict): @@ -897,7 +897,7 @@ class _Volume(TypedDict): name: str -_Volumes: TypeAlias = Collection[_Volume] +_Volumes: TypeAlias = List[_Volume] class _BuildReferences(TypedDict, total=False): @@ -928,7 +928,7 @@ class _TagGroup(TypedDict): uservisible: bool -_TagGroups: TypeAlias = Collection[_TagGroup] +_TagGroups: TypeAlias = List[_TagGroup] # specs @@ -1639,17 +1639,17 @@ class ClientSession: def getBuildNotification( self, id: int, - strict: bool = False) -> Collection[_StrDict]: + strict: bool = False) -> List[_StrDict]: ... def getBuildNotifications( self, - userID: Optional[int] = None) -> Collection[_StrDict]: + userID: Optional[int] = None) -> List[_StrDict]: ... def getBuildNotificationBlocks( self, - userID: Optional[int] = None) -> Collection[_StrDict]: + userID: Optional[int] = None) -> List[_StrDict]: ... def getBuildTarget( @@ -2451,7 +2451,7 @@ class ClientSession: def getExternalRepoList( self, tag_info: _TagSpec, - event: Optional[int] = None) -> Collection[Dict]: + event: Optional[int] = None) -> List[Dict]: ... def createExternalRepo( From 02de926078fe69f2fd30afa9f117cc521a4a1a49 Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: May 13 2024 07:47:01 +0000 Subject: [PATCH 6/13] be less strict on buildinfos --- diff --git a/koji/__init__.pyi b/koji/__init__.pyi index 267f64d..47a780a 100644 --- a/koji/__init__.pyi +++ b/koji/__init__.pyi @@ -430,6 +430,16 @@ class _ListTaskOpts(TypedDict, total=False): completeAfter: Union[float, str] +class _NVRInfo(TypedDict): + name: str + version: str + release: str + + +class _NVRAInfo(_NVRInfo): + arch: str + + class _PackageInfo(TypedDict): """ ``getPackage`` XMLRPC call. @@ -1084,12 +1094,12 @@ class PathInfo: def build( self, - build: _BuildInfo) -> str: + build: _NVRInfo) -> str: ... def build_logs( self, - build: _BuildInfo) -> str: + build: _NVRInfo) -> str: ... def distrepo( @@ -1101,12 +1111,12 @@ class PathInfo: def imagebuild( self, - build: _BuildInfo) -> str: + build: _NVRInfo) -> str: ... def mavenbuild( self, - build: _BuildInfo) -> str: + build: _NVRInfo) -> str: ... def mavenfile( @@ -1132,7 +1142,7 @@ class PathInfo: def rpm( self, - rpminfo: _RPMInfo) -> str: + rpminfo: _NVRAInfo) -> str: ... def scratch(self) -> str: @@ -1140,13 +1150,13 @@ class PathInfo: def sighdr( self, - rinfo: _RPMInfo, + rinfo: _NVRAInfo, sigkey: str) -> str: ... def signed( self, - rpminfo: _RPMInfo, + rpminfo: _NVRAInfo, sigkey: str) -> str: ... @@ -1168,7 +1178,7 @@ class PathInfo: def typedir( self, - build: _BuildInfo, + build: _NVRInfo, btype: str) -> str: ... @@ -1179,7 +1189,7 @@ class PathInfo: def winbuild( self, - build: _BuildInfo) -> str: + build: _NVRInfo) -> str: ... def winfile( @@ -1318,7 +1328,7 @@ class ClientSession: def applyVolumePolicy( self, - build: _BuildInfo, + build: _BuildSpec, strict: bool = False) -> None: ... From f2ea077407bb2d1d137573b218e54de7d804b021 Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: May 13 2024 07:47:01 +0000 Subject: [PATCH 7/13] fix _TaskInfo --- diff --git a/koji/__init__.pyi b/koji/__init__.pyi index 47a780a..4c50af1 100644 --- a/koji/__init__.pyi +++ b/koji/__init__.pyi @@ -517,8 +517,7 @@ class _RepoInfo(TypedDict): class _RPMInfo(TypedDict): """ Data representing a koji RPM. These are typically obtained via the - ``listRPMs`` XMLRPC call, or from the `kojismokydingo.as_rpminfo` - function + ``listRPMs`` XMLRPC call. """ arch: str @@ -622,8 +621,7 @@ class _TagGroupReq(TypedDict): class _TagInfo(TypedDict): """ Data representing a koji tag. Typically obtained via the - ``getTag`` XMLRPC call, or the `kojismokydingo.as_taginfo` and - `kojismokydingo.bulk_load_tags` functions. + ``getTag`` XMLRPC call. """ arches: str @@ -759,8 +757,7 @@ class _TagPackageInfo(TypedDict): class _TargetInfo(TypedDict): """ Data representing a koji build target. Typically obtained via the - ``getBuildTarget`` or ``getBuildTargets`` XMLRPC calls, or the - `kojismokydingo.as_targetinfo` function. + ``getBuildTarget`` or ``getBuildTargets`` XMLRPC calls. """ build_tag: int @@ -787,7 +784,7 @@ _TargetInfos = List[_TargetInfo] class _TaskInfo(TypedDict): """ - ``getTaskInfo`` XMLRPC call or `kojismokydingo.as_taskinfo` function + ``getTaskInfo`` XMLRPC call """ arch: str @@ -870,8 +867,7 @@ _TaskInfos: TypeAlias = List[_TaskInfo] class _UserInfo(TypedDict): """ Data representing a koji user account. These are typically - obtained via the ``getUser`` or ``getLoggedInUser`` XMLRPC calls, - or the ``kojismokydingo.as_userinfo`` function. + obtained via the ``getUser`` or ``getLoggedInUser`` XMLRPC calls. """ authtype: int @@ -1379,7 +1375,7 @@ class ClientSession: def buildReferences( self, - build: _BuildInfo, + build: _BuildSpec, limit: Optional[int] = None, lazy: bool = False) -> _BuildReferences: ... @@ -1395,7 +1391,7 @@ class ClientSession: def chainMaven( self, - builds: _BuildInfos, + builds: _BuildSpecs, target: str, opts: _Options = None, priority: Optional[int] = None, @@ -2623,7 +2619,7 @@ def genMockConfig( def buildLabel( - buildInfo: _BuildInfo, + buildInfo: _NVRInfo, showEpoch: bool = False) -> str: ... diff --git a/koji/tasks.pyi b/koji/tasks.pyi index 2cd1c4d..5662cd5 100644 --- a/koji/tasks.pyi +++ b/koji/tasks.pyi @@ -1,4 +1,4 @@ -from kojismokydingo.types import TaskInfo +import optparse from typing import Any, Optional, List, Union, Dict, TypedDict @@ -39,6 +39,29 @@ class _TagInfo(TypedDict): perm_id: int +class _TaskInfo(TypedDict): + arch: str + awaited: Union[bool, None] + channel_id: int + completion_time: str + completion_ts: float + create_time: str + create_ts: float + host_id: int + id: int + label: str + method: str + owner: int + parent: int + priority: int + start_time: str + start_ts: float + state: int + waiting: Union[bool, None] + weight: float + request: List[Any] + + def scan_mounts(topdir: str) -> List[str]: ... @@ -88,7 +111,7 @@ class BaseTaskHandler: method: str, params: list, session: Any, - options: dict, + options: optparse.Values, workdir: Optional[str] = ...) -> None: ... @@ -182,16 +205,16 @@ class BaseTaskHandler: def run_callbacks( self, plugin: str, - *args: list, - **kwargs: dict) -> None: + *args: Any, + **kwargs: Any) -> None: ... @property - def taskinfo(self) -> TaskInfo: + def taskinfo(self) -> _TaskInfo: ... @taskinfo.setter - def taskinfo(self, taskinfo: TaskInfo) -> None: + def taskinfo(self, taskinfo: _TaskInfo) -> None: ... From 4fe7b98193d5bf11e6a7555ef2ac1266cd439de7 Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: May 13 2024 07:47:01 +0000 Subject: [PATCH 8/13] remove kojismokydingo references (authorship remains) --- diff --git a/koji/__init__.pyi b/koji/__init__.pyi index 4c50af1..5025960 100644 --- a/koji/__init__.pyi +++ b/koji/__init__.pyi @@ -15,10 +15,9 @@ """ Koji - type stubs -Typing annotations stub for the parts of koji used by koji smoky -dingo. In particular there are annotations for the virtual XMLRPC -methods on the ClientSession class which should help check that the -calls are being used correctly. +Typing annotations stub for the parts of koji. In particular there +are annotations for the virtual XMLRPC methods on the ClientSession +class which should help check that the calls are being used correctly. :author: Christopher O'Brien :license: GPL v3 From 0b52b16d58413bbb1c0c43ecc58bda891a3f844e Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: May 13 2024 07:47:01 +0000 Subject: [PATCH 9/13] additional constants --- diff --git a/koji/__init__.pyi b/koji/__init__.pyi index 5025960..8fa2c00 100644 --- a/koji/__init__.pyi +++ b/koji/__init__.pyi @@ -971,6 +971,14 @@ AUTHTYPE_KERB: int AUTHTYPE_SSL: int AUTHTYPE_GSSAPI: int +DEP_REQUIRE = int +DEP_PROVIDE = int +DEP_OBSOLETE = int +DEP_CONFLICT = int +DEP_SUGGEST = int +DEP_ENHANCE = int +DEP_SUPPLEMENT = int +DEP_RECOMMEND = int REPO_INIT: int REPO_READY: int @@ -979,6 +987,11 @@ REPO_DELETED: int REPO_PROBLEM: int REPO_MERGE_MODES: Set[str] +# dependency flags +RPMSENSE_LESS = int +RPMSENSE_GREATER = int +RPMSENSE_EQUAL = int + RPM_SIGTAG_GPG: int RPM_SIGTAG_PGP: int RPM_SIGTAG_RSA: int From 96e6e8fd1975d91412b44f1c0155b87788a0481a Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: May 13 2024 07:47:01 +0000 Subject: [PATCH 10/13] db/auth stubs --- diff --git a/kojihub/auth.pyi b/kojihub/auth.pyi new file mode 100644 index 0000000..57a6763 --- /dev/null +++ b/kojihub/auth.pyi @@ -0,0 +1,96 @@ +import logging +from .db import ( + DeleteProcessor as DeleteProcessor, + InsertProcessor as InsertProcessor, + QueryProcessor as QueryProcessor, + UpdateProcessor as UpdateProcessor, + nextval as nextval) +from _typeshed import Incomplete +from typing import Any, Tuple, TypeAlias + +RetryWhitelist: list[str] +AUTH_METHODS: list[str] +logger: logging.Logger + +_SessionInfo: TypeAlias = dict[str, Any] + +class Session: + logged_in: bool + id: int | None + master: int | None + key: str | None + user_id: int | None + authtype: int | None + hostip: str | None + user_data: dict[str, Any] + message: str + exclusive: bool + lockerror: str | None + callnum: int | None + session_data: _SessionInfo + def __init__(self, + args: None = ..., + hostip: str | None = ...) -> None: ... + def __getattr__(self, name: str) -> dict | list | int: ... + def validate(self) -> bool: ... + def get_remote_ip(self, override: str | None = ...) -> str: ... + def checkLoginAllowed(self, user_id: str) -> None: ... + def login(self, + user: str, + password: str, + opts: dict[str, Any] | None = ..., + renew: bool = ..., + exclusive: bool = ...) -> _SessionInfo: ... + def getConnInfo(self) -> Tuple[str, int, str, int]: ... + def sslLogin(self, + proxyuser: str | None = ..., + proxyauthtype: int | None = ..., + renew: bool = ..., + exclusive: bool | None = ...) -> _SessionInfo: ... + def makeExclusive(self, force: bool = ...) -> None: ... + def makeShared(self) -> None: ... + def logout(self, session_id: int | None = ...) -> None: ... + def logoutChild(self, session_id: int) -> None: ... + def createSession(self, + user_id: int, + hostip: str, + authtype: int, + master: int | None = ..., + renew: bool = ...) -> _SessionInfo: ... + def subsession(self) -> _SessionInfo: ... + def getPerms(self) -> list[str]: ... + def hasPerm(self, name: str) -> bool: ... + def assertPerm(self, name: str) -> None: ... + def assertLogin(self) -> None: ... + def hasGroup(self, group_id: int) -> bool: ... + def isUser(self, user_id: int) -> bool: ... + def assertUser(self, user_id: int) -> None: ... + def getHostId(self) -> int: ... + def getUserId(self, username: str) -> int: ... + def getUserIdFromKerberos(self, krb_principal: str) -> int: ... + def createUser(self, + name: str, + usertype: int | None = ..., + status: int | None = ..., + krb_principal: str | None = ..., + krb_princ_check: bool = ...) -> int: ... + def setKrbPrincipal(self, + name: str, + krb_principal: str, + krb_princ_check: bool = ...) -> int: ... + def removeKrbPrincipal(self, + name: str, + krb_principal: str) -> int: ... + def createUserFromKerberos(self, krb_principal: str): ... + def checkKrbPrincipal(self, krb_principal: str) -> None: ... + +def get_user_groups(user_id: int) -> list[dict[str, int | str]]: ... +def get_user_perms(user_id: int) -> list[str]: ... +def get_user_data(user_id: int) -> dict[str, int | str]: ... +def login(*args, **opts) -> _SessionInfo: ... +def sslLogin(*args, **opts) -> _SessionInfo: ... +def logout(session_id: int | None = ...) -> int: ... +def subsession() -> _SessionInfo: ... +def logoutChild(session_id: int) -> None: ... +def exclusiveSession(*args, **opts) -> None: ... +def sharedSession() -> None: ... diff --git a/kojihub/db.pyi b/kojihub/db.pyi new file mode 100644 index 0000000..e40bc21 --- /dev/null +++ b/kojihub/db.pyi @@ -0,0 +1,176 @@ +from _typeshed import Incomplete +from typing import Any, Iterable, Optional, Callable, Tuple +import logging + +context: Incomplete +POSITIONAL_RE: Any +NAMED_RE: Any +logger: Incomplete + +class DBWrapper: + cnx: Incomplete + + def __init__(self, cnx: Any) -> None: + ... + + def __getattr__(self, key: Any): + ... + + def cursor(self, *args: Any, **kw: Any): + ... + + def close(self) -> None: + ... + + +class CursorWrapper: + cursor: Incomplete + logger: logging.Logger + def __init__(self, cursor) -> None: ... + def __getattr__(self, key: str) -> Any: ... + def fetchone(self, *args, **kwargs): ... + def fetchall(self, *args, **kwargs): ... + def quote(self, operation: str, parameters: dict[str, Any]) -> str: ... + def preformat(self, sql: str, params: dict[str, Any]): ... + def execute(self, operation: str, parameters=list, log_errors: bool = ...): ... + + +def provideDBopts(**opts: Any) -> None: ... +def setDBopts(**opts: Any) -> None: ... +def getDBopts() -> dict[str, Any]: ... +def connect() -> DBWrapper: ... + + +class QueryProcessor: + iterchunksize: int + columns: Optional[list[str]] + aliases: Optional[list[str]] + colsByAlias: dict[str, str] + tables: Optional[list[str]] + joins: Optional[list[str]] + clauses: Optional[list[str]] + cursors: int + values: dict[str, Any] + transform: Callable + opts: dict[str, Any] + enable_group: bool + logger: logging.Logger + + def __init__(self, + columns: Optional[Iterable[str]] = ..., + aliases: Optional[Iterable[str]] = ..., + tables: Optional[Iterable[str]] = ..., + joins: Optional[Iterable[str]] = ..., + clauses: Optional[Iterable[str]] = ..., + values: Optional[dict[str, Any]] = ..., + transform: Optional[Callable] = ..., + opts: Optional[dict[str, Any]] = ..., + enable_group: bool = ...) -> None: + ... + + def countOnly(self, count: int) -> None: + ... + + def singleValue(self, strict: bool = ...) -> Optional[dict[str, Any]]: + ... + + def execute(self) -> list[dict[str, Any]]: + ... + + def iterate(self) -> Iterable[dict[str, Any]]: + ... + + def executeOne(self, strict: bool = ...) -> Optional[dict[str, Any]]: + ... + +def get_event() -> int: ... +def nextval(sequence: str) -> int: ... +def currval(sequence: str) -> int: ... +def db_lock(name: str, wait: bool = ...) -> bool: ... + +class Savepoint: + name: str + def __init__(self, name: str) -> None: ... + def rollback(self) -> None: ... + +class InsertProcessor: + table: str + data: dict[str, Any] + rawdata: dict[str, Any] + + def __init__(self, + table: str, + data: Optional[dict[str, Any]] = ..., + rawdata: Optional[dict[str, Any]] = ...) -> None: + ... + + def set(self, **kwargs: Any) -> None: ... + def rawset(self, **kwargs: Any) -> None: ... + def make_create(self, + event_id: Optional[int] = ..., + user_id: Optional[int] = ...) -> None: + ... + + def dup_check(self) -> bool: ... + def execute(self) -> int: ... + + +class UpdateProcessor: + table: str + data: dict[str, Any] + rawdata: dict[str, Any] + clauses: list[str] + values: dict[str, Any] + def __init__(self, + table: str, + data: Optional[dict[str, Any]] = ..., + rawdata: Optional[dict[str, Any]] = ..., + clauses: Optional[Iterable[str]] = ..., + values: Optional[dict[str, Any]] = ...) -> None: + ... + + def get_values(self) -> dict[str, Any]: ... + def set(self, **kwargs: Any) -> None: ... + def rawset(self, **kwargs: Any) -> None: ... + def make_revoke(self, + event_id: Optional[int] = ..., + user_id: Optional[int] = ...) -> None: + ... + + def execute(self) -> int: ... + + +class DeleteProcessor: + table: str + clauses: list[str] + values: dict[str, Any] + def __init__(self, + table: str, + clauses: Optional[Iterable[str]] = ..., + values: Optional[dict[str, Any]] = ...) -> None: + ... + + def get_values(self) -> dict[str, Any]: ... + def execute(self) -> int: ... + + +class BulkInsertProcessor: + table: str + data: dict[str, Any] + columns: list[str] + strict: bool + batch: int + def __init__(self, + table: str, + data=Optional[list[dict[str, Any]]] = ..., + columns=Optional[list[str]] = ..., + strict=bool = ..., + batch=int = ...) -> None: + ... + + def __str__(self) -> str: ... + def _get_insert(self, data: list[dict[str, Any]]) -> Tuple[str, dict[str, Any]]: ... + def __repr__(self) -> str: ... + def add_record(self, **kwargs: Any) -> None: ... + def execute(self) -> None: ... + def _one_insert(self, data: dict[str, Any]) -> None: ... From a7301f3ad2577339c25e93b299b18d7837f97b81 Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: May 13 2024 07:47:01 +0000 Subject: [PATCH 11/13] remove unused import --- diff --git a/kojihub/auth.pyi b/kojihub/auth.pyi index 57a6763..d64b622 100644 --- a/kojihub/auth.pyi +++ b/kojihub/auth.pyi @@ -5,7 +5,6 @@ from .db import ( QueryProcessor as QueryProcessor, UpdateProcessor as UpdateProcessor, nextval as nextval) -from _typeshed import Incomplete from typing import Any, Tuple, TypeAlias RetryWhitelist: list[str] From dbe8819985ad3ecad05c2c530c0d682107d59e9e Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: May 13 2024 07:47:01 +0000 Subject: [PATCH 12/13] updates --- diff --git a/kojihub/auth.pyi b/kojihub/auth.pyi index d64b622..83e3087 100644 --- a/kojihub/auth.pyi +++ b/kojihub/auth.pyi @@ -1,95 +1,59 @@ -import logging -from .db import ( - DeleteProcessor as DeleteProcessor, - InsertProcessor as InsertProcessor, - QueryProcessor as QueryProcessor, - UpdateProcessor as UpdateProcessor, - nextval as nextval) -from typing import Any, Tuple, TypeAlias +from typing import Any, Optional -RetryWhitelist: list[str] -AUTH_METHODS: list[str] -logger: logging.Logger - -_SessionInfo: TypeAlias = dict[str, Any] +RetryWhitelist: Any class Session: - logged_in: bool - id: int | None - master: int | None - key: str | None - user_id: int | None - authtype: int | None - hostip: str | None - user_data: dict[str, Any] - message: str - exclusive: bool - lockerror: str | None - callnum: int | None - session_data: _SessionInfo - def __init__(self, - args: None = ..., - hostip: str | None = ...) -> None: ... - def __getattr__(self, name: str) -> dict | list | int: ... - def validate(self) -> bool: ... - def get_remote_ip(self, override: str | None = ...) -> str: ... - def checkLoginAllowed(self, user_id: str) -> None: ... - def login(self, - user: str, - password: str, - opts: dict[str, Any] | None = ..., - renew: bool = ..., - exclusive: bool = ...) -> _SessionInfo: ... - def getConnInfo(self) -> Tuple[str, int, str, int]: ... - def sslLogin(self, - proxyuser: str | None = ..., - proxyauthtype: int | None = ..., - renew: bool = ..., - exclusive: bool | None = ...) -> _SessionInfo: ... + logged_in: bool = ... + id: Any = ... + master: Any = ... + key: Any = ... + user_id: Any = ... + authtype: Any = ... + hostip: Any = ... + user_data: Any = ... + message: str = ... + exclusive: bool = ... + lockerror: Any = ... + callnum: Any = ... + session_data: Any = ... + def __init__(self, args: Optional[Any] = ..., hostip: Optional[Any] = ...): ... + def __getattr__(self, name: Any): ... + def validate(self): ... + def get_remote_ip(self, override: Optional[Any] = ...): ... + def checkLoginAllowed(self, user_id: Any) -> None: ... + def login(self, user: Any, password: Any, opts: Optional[Any] = ...): ... + def getConnInfo(self): ... + def sslLogin(self, proxyuser: Optional[Any] = ...): ... def makeExclusive(self, force: bool = ...) -> None: ... def makeShared(self) -> None: ... - def logout(self, session_id: int | None = ...) -> None: ... - def logoutChild(self, session_id: int) -> None: ... - def createSession(self, - user_id: int, - hostip: str, - authtype: int, - master: int | None = ..., - renew: bool = ...) -> _SessionInfo: ... - def subsession(self) -> _SessionInfo: ... - def getPerms(self) -> list[str]: ... - def hasPerm(self, name: str) -> bool: ... - def assertPerm(self, name: str) -> None: ... + def logout(self) -> None: ... + def logoutChild(self, session_id: Any) -> None: ... + def createSession(self, user_id: Any, hostip: Any, authtype: Any, master: Optional[Any] = ...): ... + def subsession(self): ... + def getPerms(self): ... + def hasPerm(self, name: Any): ... + def assertPerm(self, name: Any) -> None: ... def assertLogin(self) -> None: ... - def hasGroup(self, group_id: int) -> bool: ... - def isUser(self, user_id: int) -> bool: ... - def assertUser(self, user_id: int) -> None: ... - def getHostId(self) -> int: ... - def getUserId(self, username: str) -> int: ... - def getUserIdFromKerberos(self, krb_principal: str) -> int: ... - def createUser(self, - name: str, - usertype: int | None = ..., - status: int | None = ..., - krb_principal: str | None = ..., - krb_princ_check: bool = ...) -> int: ... - def setKrbPrincipal(self, - name: str, - krb_principal: str, - krb_princ_check: bool = ...) -> int: ... - def removeKrbPrincipal(self, - name: str, - krb_principal: str) -> int: ... - def createUserFromKerberos(self, krb_principal: str): ... - def checkKrbPrincipal(self, krb_principal: str) -> None: ... + def hasGroup(self, group_id: Any): ... + def isUser(self, user_id: Any): ... + def assertUser(self, user_id: Any) -> None: ... + def getHostId(self): ... + def getUserId(self, username: Any): ... + def getUserIdFromKerberos(self, krb_principal: Any): ... + def createUser(self, name: Any, usertype: Optional[Any] = ..., status: Optional[Any] = ..., krb_principal: Optional[Any] = ..., krb_princ_check: bool = ...): ... + def setKrbPrincipal(self, name: Any, krb_principal: Any, krb_princ_check: bool = ...): ... + def removeKrbPrincipal(self, name: Any, krb_principal: Any): ... + def createUserFromKerberos(self, krb_principal: Any): ... + def checkKrbPrincipal(self, krb_principal: Any) -> None: ... -def get_user_groups(user_id: int) -> list[dict[str, int | str]]: ... -def get_user_perms(user_id: int) -> list[str]: ... -def get_user_data(user_id: int) -> dict[str, int | str]: ... -def login(*args, **opts) -> _SessionInfo: ... -def sslLogin(*args, **opts) -> _SessionInfo: ... -def logout(session_id: int | None = ...) -> int: ... -def subsession() -> _SessionInfo: ... -def logoutChild(session_id: int) -> None: ... -def exclusiveSession(*args, **opts) -> None: ... -def sharedSession() -> None: ... +def get_user_groups(user_id: Any): ... +def get_user_perms(user_id: Any): ... +def get_user_data(user_id: Any): ... +def login(*args: Any, **opts: Any): ... +def krbLogin(*args: Any, **opts: Any): ... +def sslLogin(*args: Any, **opts: Any): ... +def logout(): ... +def subsession(): ... +def logoutChild(session_id: Any): ... +def exclusiveSession(*args: Any, **opts: Any): ... +def sharedSession(): ... diff --git a/kojihub/db.pyi b/kojihub/db.pyi index e40bc21..f3271c0 100644 --- a/kojihub/db.pyi +++ b/kojihub/db.pyi @@ -68,20 +68,12 @@ class QueryProcessor: enable_group: bool = ...) -> None: ... - def countOnly(self, count: int) -> None: - ... - - def singleValue(self, strict: bool = ...) -> Optional[dict[str, Any]]: - ... - - def execute(self) -> list[dict[str, Any]]: - ... - - def iterate(self) -> Iterable[dict[str, Any]]: - ... - - def executeOne(self, strict: bool = ...) -> Optional[dict[str, Any]]: - ... + def countOnly(self, count: int) -> None: ... + def singleValue(self, strict: bool = ...) -> Optional[dict[str, Any]]: ... + def execute(self) -> list[dict[str, Any]]: ... + #def execute(self) -> None: ... + def iterate(self) -> Iterable[dict[str, Any]]: ... + def executeOne(self, strict: bool = ...) -> Optional[dict[str, Any]]: ... def get_event() -> int: ... def nextval(sequence: str) -> int: ... @@ -160,12 +152,13 @@ class BulkInsertProcessor: columns: list[str] strict: bool batch: int - def __init__(self, - table: str, - data=Optional[list[dict[str, Any]]] = ..., - columns=Optional[list[str]] = ..., - strict=bool = ..., - batch=int = ...) -> None: + def __init__( + self, + table: str, + data: Optional[list[dict[str, Any]]] = ..., + columns: Optional[list[str]] = ..., + strict: bool = ..., + batch: int = ...) -> None: ... def __str__(self) -> str: ... From 9a333fe63471d496242d106556a3ed0ae52e9c39 Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: May 13 2024 07:47:01 +0000 Subject: [PATCH 13/13] new files --- diff --git a/koji/__init__.pyi b/koji/__init__.pyi index 8fa2c00..2310986 100644 --- a/koji/__init__.pyi +++ b/koji/__init__.pyi @@ -939,6 +939,7 @@ _TagGroups: TypeAlias = List[_TagGroup] # specs _ArchiveSpec = Union[int, str, _ArchiveInfo] _BuildSpec: TypeAlias = Union[int, str, _BuildInfo] +_BuildSpecs: Iterable[_BuildSpec] _CGSpec: TypeAlias = Union[int, str] _ChannelSpec = Union[int, str, _ChannelInfo] _GroupSpec = Union[int, str] @@ -953,7 +954,7 @@ _UserSpec = Union[int, str, _UserInfo] # koji/__init__.py part class Enum(dict): - def get( + def get( # type: ignore[override] self, key: Union[str, int], default: Optional[Union[str, int]] = None): @@ -1403,7 +1404,7 @@ class ClientSession: def chainMaven( self, - builds: _BuildSpecs, + builds: _BuildSpec, target: str, opts: _Options = None, priority: Optional[int] = None, @@ -1809,7 +1810,7 @@ class ClientSession: def getRepo( self, tag: Union[int, str], - state: Optional[_RepoState] = None, + state: Optional[int] = None, event: Optional[int] = None, dist: bool = False) -> _RepoInfo: ... @@ -2050,7 +2051,7 @@ class ClientSession: archiveID: Optional[int] = None, taskID: Optional[int] = None, buildrootID: Optional[int] = None, - queryOpts: Optional[_QueryOptsType] = None) -> BuildRootInfos: + queryOpts: Optional[_QueryOptsType] = None) -> _BuildRootInfos: ... def listBuilds( @@ -2760,7 +2761,7 @@ class SplicedSigStreamReader(io.RawIOBase): def readable(self) -> bool: ... - def readinto( + def readinto( # type: ignore[override] self, b: bytes) -> int: ... @@ -2786,7 +2787,7 @@ class POMHandler(xml.sax.handler.ContentHandler): def __init__(self, values: list, fields: dict) -> None: ... - def startElement(self, name: str, attrs: dict) -> None: + def startElement(self, name: str, attrs: dict) -> None: # type: ignore[override] ... def characters(self, content: str) -> None: @@ -2868,5 +2869,15 @@ def fixEncodingRecurse( fallback: Optional[str] = 'iso8859-15', remove_nonprintable: bool = False): ... -# -# The end. + +def gen_draft_release( + target_release: str, + build_id: int + ) -> str: + ... + +def parse_target_release( + draft_release: str + ) -> str: + ... + ) diff --git a/koji/daemon.pyi b/koji/daemon.pyi index 0f2bdd4..ed384da 100644 --- a/koji/daemon.pyi +++ b/koji/daemon.pyi @@ -1,7 +1,6 @@ from _typeshed import Incomplete import io import logging -from build.lib.koji import ClientSession import koji from koji.tasks import safe_rmtree, BaseTaskHandler from koji.util import ( diff --git a/koji/plugin.pyi b/koji/plugin.pyi index 5dcb9a3..6eb2c05 100644 --- a/koji/plugin.pyi +++ b/koji/plugin.pyi @@ -1,6 +1,6 @@ from _typeshed import Incomplete from koji.util import encode_datetime_recurse as encode_datetime_recurse -from typing import Callable, Optional +from typing import Callable, Optional, overload callbacks: dict[str, list[Callable]] @@ -20,7 +20,7 @@ class PluginTracker: self, name: str, path: Optional[str] = ..., - reload: bool = ...) -> Callable + reload: bool = ...) -> Callable: ... def get( @@ -28,9 +28,11 @@ class PluginTracker: name: str) -> Callable: ... + @overload def pathlist(self, path: str) -> str: ... + @overload def pathlist(self, path: list[str]) -> list[str]: ... diff --git a/koji/policy.pyi b/koji/policy.pyi index cc3f0a2..44e04d6 100644 --- a/koji/policy.pyi +++ b/koji/policy.pyi @@ -9,7 +9,7 @@ class BaseSimpleTest: def __init__(self, str: str) -> None: ... - def run(self, data: dict) -> None: + def run(self, data: dict): ... diff --git a/koji/tasks.pyi b/koji/tasks.pyi index 5662cd5..f79b2d3 100644 --- a/koji/tasks.pyi +++ b/koji/tasks.pyi @@ -29,7 +29,7 @@ class _RepoInfo(TypedDict): class _TagInfo(TypedDict): arches: str - extra: Dict[str, str] + extra: dict[str, str] id: int locked: bool maven_include_all: bool @@ -41,7 +41,7 @@ class _TagInfo(TypedDict): class _TaskInfo(TypedDict): arch: str - awaited: Union[bool, None] + awaited: Optional[bool] channel_id: int completion_time: str completion_ts: float @@ -91,7 +91,7 @@ def parse_task_params( ... -LEGACY_SIGNATURES: Dict[str, list] +LEGACY_SIGNATURES: dict[str, list] class BaseTaskHandler: @@ -121,7 +121,7 @@ class BaseTaskHandler: def handler(self) -> None: ... - def run(self) -> None: + def run(self): ... def weight(self) -> float: @@ -222,12 +222,12 @@ class FakeTask(BaseTaskHandler): Methods: List[str] Foreground: bool = ... - def handler(self, *args: list): + def handler(self, *args: list) -> None: # type: ignore[override] ... class SleepTask(BaseTaskHandler): - def handler(self, n: int) -> None: + def handler(self, n: int) -> None: # type: ignore[override] ... @@ -237,7 +237,7 @@ class ForkTask(BaseTaskHandler): class WaitTestTask(BaseTaskHandler): - def handler(self, count: int, seconds: int = ...) -> None: + def handler(self, count: int, seconds: int = ...) -> None: # type: ignore[override] ... @@ -257,25 +257,25 @@ class ShutdownTask(BaseTaskHandler): class RestartTask(BaseTaskHandler): - def handler(self, host: _HostInfo) -> str: + def handler(self, host: _HostInfo) -> str: # type: ignore[override] ... class RestartVerifyTask(BaseTaskHandler): - def handler(self, task_id: int, host: _HostInfo) -> None: + def handler(self, task_id: int, host: _HostInfo) -> None: # type: ignore[override] ... class RestartHostsTask(BaseTaskHandler): - def handler(self, options: Optional[Dict[str, Any]] = ...) -> None: + def handler(self, options: Optional[dict[str, Any]] = ...) -> None: ... class DependantTask(BaseTaskHandler): - def handler( + def handler( # type: ignore[override] self, wait_list: List[int], - task_list: List[int]) -> None: + task_list: List[int]) -> None: ... @@ -287,5 +287,5 @@ class MultiPlatformTask(BaseTaskHandler): build_target: int, build: int, repo_id: int, - **opts: Dict[str, Any]): + **opts: dict[str, Any]): ... diff --git a/koji/util.pyi b/koji/util.pyi index 34bf609..088f022 100644 --- a/koji/util.pyi +++ b/koji/util.pyi @@ -182,10 +182,10 @@ class LazyDict(dict): def copy(self) -> Self: ... - def values(self) -> Iterable: + def values(self) -> list: # type: ignore[override] ... - def items(self) -> Iterable: + def items(self) -> list[tuple]: # type: ignore[override] ... def itervalues(self) -> None: @@ -229,6 +229,24 @@ def rmtree( ... +class SimpleProxyLogger(object): + def __init__(self, filename: str) -> None: ... + def __enter__(self): ... + def __exit__(self, _type, value, traceback) -> bool: ... + def log(self, + level = int, + msg = str, + *args, + **kwargs) -> None: + ... + def info(self, msg = str, *args, **kwargs) -> None: ... + def warning(self, msg = str, *args, **kwargs) -> None: ... + def error(self, msg = str, *args, **kwargs) -> None: ... + def debug(self, msg = str, *args, **kwargs) -> None: ... + @staticmethod + def send(filename: str, logger) -> None: ... + + def safer_move(src: str, dst: str) -> None: ... @@ -243,7 +261,7 @@ def move_and_symlink( def joinpath( path: str, - *paths: List[str]) -> str: + *paths: str) -> str: ... @@ -361,3 +379,6 @@ def format_shell_cmd( cmd: List[str], text_width: int = 80) -> str: ... + +def extract_build_task(binfo: dict[str, Any]) -> int: + ... diff --git a/koji/xmlrpcplus.pyi b/koji/xmlrpcplus.pyi index 7b83615..faf464c 100644 --- a/koji/xmlrpcplus.pyi +++ b/koji/xmlrpcplus.pyi @@ -1,5 +1,5 @@ import types -import six.moves.xmlrpc_client as xmlrpc_client +#import six.moves.xmlrpc_client as xmlrpc_client from _typeshed import Incomplete from typing import Callable, Optional, Union @@ -9,7 +9,7 @@ Fault: Incomplete DateTime: Incomplete -class ExtendedMarshaller(xmlrpc_client.Marshaller): +class ExtendedMarshaller(object): dispatch: Incomplete def dump_generator( @@ -40,5 +40,5 @@ def dumps( methodresponse: Optional[Union[bool, int]] = ..., encoding: Optional[str] = ..., allow_none: Union[bool, int] = ..., - marshaller: Optional[xmlrpc_client.Marshaller] = ...) -> str: + marshaller: Optional[Incomplete] = ...) -> str: ... diff --git a/kojihub/__init__.pyi b/kojihub/__init__.pyi new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/kojihub/__init__.pyi diff --git a/kojihub/db.pyi b/kojihub/db.pyi index f3271c0..3681b83 100644 --- a/kojihub/db.pyi +++ b/kojihub/db.pyi @@ -1,5 +1,5 @@ from _typeshed import Incomplete -from typing import Any, Iterable, Optional, Callable, Tuple +from typing import Any, Iterable, Optional, Callable, Tuple, Union, TypeAlias import logging context: Incomplete @@ -7,6 +7,16 @@ POSITIONAL_RE: Any NAMED_RE: Any logger: Incomplete +''' +class _QueryOpts(TypedDict, total=False): + countOnly: bool + order: str + offset: int + limit: int +''' +_QueryOpts: TypeAlias = dict[str, Any] + + class DBWrapper: cnx: Incomplete @@ -52,7 +62,7 @@ class QueryProcessor: cursors: int values: dict[str, Any] transform: Callable - opts: dict[str, Any] + opts: _QueryOpts enable_group: bool logger: logging.Logger @@ -64,17 +74,52 @@ class QueryProcessor: clauses: Optional[Iterable[str]] = ..., values: Optional[dict[str, Any]] = ..., transform: Optional[Callable] = ..., - opts: Optional[dict[str, Any]] = ..., + opts: Optional[_QueryOpts] = ..., enable_group: bool = ...) -> None: ... def countOnly(self, count: int) -> None: ... - def singleValue(self, strict: bool = ...) -> Optional[dict[str, Any]]: ... + def singleValue(self, strict: bool = ...): ... def execute(self) -> list[dict[str, Any]]: ... #def execute(self) -> None: ... def iterate(self) -> Iterable[dict[str, Any]]: ... def executeOne(self, strict: bool = ...) -> Optional[dict[str, Any]]: ... + +class QueryView: + tables = list[str] + joins = list[str] + joinmap = dict[str, str] + fieldmap = dict[str, str] + default_fields: Iterable[str] + clauses: Optional[list[str]] + fields: Optional[Iterable[str]] + opts: _QueryOpts + extra_joins: list + values: dict + order_map: dict[str, str] + + def __init__(self, + clauses: Optional[Iterable[str]] = None, + fields: Optional[Iterable[str]] = None, + opts: Optional[_QueryOpts] = None) -> None: + ... + + @property + def query(self): ... + + + def get_query(self): ... + def get_fields(self, fields): ... + def check_opts(self) -> None: ... + def map_field(self, field): ... + def get_clauses(self): ... + def get_joins(self): ... + def execute(self): ... + def executeOne(self, strict: bool = False): ... + def iterate(self): ... + def singleValue(self, strict: bool = True): ... + def get_event() -> int: ... def nextval(sequence: str) -> int: ... def currval(sequence: str) -> int: ... @@ -167,3 +212,58 @@ class BulkInsertProcessor: def add_record(self, **kwargs: Any) -> None: ... def execute(self) -> None: ... def _one_insert(self, data: dict[str, Any]) -> None: ... + +class UpsertProcessor(InsertProcessor): + keys: Optional[Iterable[str]] + skip_dup: bool + + def __init__( + self, + table, + data: Optional[dict[str, Any]] = None, + rawdata: Optional[dict] = None, + keys: Optional[Iterable[str]] = None, + skip_dup: bool = False) -> None: + ... + +def _applyQueryOpts( + results: list[dict[str, Any]], + queryOpts: _QueryOpts) -> Union[int, list[dict]]: + ... + +def _dml( + operation: str, + values: dict[str, Any], + log_errors: bool = True): + ... + + +def _fetchMulti( + query: str, + values: dict[str, Any]): + ... + +def _fetchSingle( + query: str, + values: dict[str, Any], + strict: bool = False): + ... + +def _singleValue( + query: str, + values: Optional[dict[str, Any]] = None, + strict: bool =True): + ... + +def _multiRow( + query: str, + values: dict[str, Any], + fields: Iterable[str]): + ... + +def _singleRow( + query: str, + values: dict[str, Any], + fields: Iterable[str], + strict: bool = False): + ... diff --git a/kojihub/kojihub.pyi b/kojihub/kojihub.pyi new file mode 100644 index 0000000..c868a5e --- /dev/null +++ b/kojihub/kojihub.pyi @@ -0,0 +1,783 @@ +from typing import Any, Optional, Union + +import logging +import koji.policy +import koji.xmlrpcplus +from koji import _NVRInfo + +logger: logging.Logger + +NUMERIC_TYPES: tuple[type] + +def log_error(msg: Any) -> None: ... +def xform_user_krb(entry: dict) -> dict: ... + +def convert_value( + value: Any, + cast: Optional[type] = ..., + message: Optional[str] = ..., + exc_type: Exception = ..., + none_allowed: bool = ..., + check_only: bool = ...): + ... + + +class Task: + fields: Any = ... + id: Any = ... + logger: Any = ... + def __init__(self, id: Any) -> None: ... + def verifyHost(self, host_id: Optional[Any] = ...): ... + def assertHost(self, host_id: Any) -> None: ... + def getOwner(self): ... + def verifyOwner(self, user_id: Optional[Any] = ...): ... + def assertOwner(self, user_id: Optional[Any] = ...) -> None: ... + def lock(self, host_id: Any, newstate: str = ..., force: bool = ...): ... + def assign(self, host_id: Any, force: bool = ...): ... + def open(self, host_id: Any): ... + def free(self): ... + def setWeight(self, weight: Any) -> None: ... + def setPriority(self, priority: Any, recurse: bool = ...) -> None: ... + def close(self, result: Any) -> None: ... + def fail(self, result: Any) -> None: ... + def getState(self): ... + def isFinished(self): ... + def isCanceled(self): ... + def isFailed(self): ... + def cancel(self, recurse: bool = ...): ... + def cancelChildren(self) -> None: ... + def cancelFull(self, strict: bool = ...): ... + def getRequest(self): ... + def getResult(self, raise_fault: bool = ...): ... + def getInfo(self, strict: bool = ..., request: bool = ...): ... + def getChildren(self, request: bool = ...): ... + def runCallbacks(self, cbtype: Any, old_info: Any, attr: Any, new_val: Any) -> None: ... + +def make_task(method: Any, arglist: Any, **opts: Any): ... +def eventCondition(event: Any, table: Optional[Any] = ...): ... +def readInheritanceData(tag_id: Any, event: Optional[Any] = ...): ... +def readDescendantsData(tag_id: Any, event: Optional[Any] = ...): ... +def writeInheritanceData(tag_id: Any, changes: Any, clear: bool = ...) -> None: ... +def readFullInheritance(tag_id: Any, event: Optional[Any] = ..., reverse: bool = ...): ... +def readFullInheritanceRecurse(tag_id: Any, event: Any, order: Any, top: Any, hist: Any, currdepth: Any, maxdepth: Any, noconfig: Any, pfilter: Any, reverse: Any) -> None: ... +def pkglist_add(taginfo: Any, pkginfo: Any, owner: Optional[Any] = ..., block: Optional[Any] = ..., extra_arches: Optional[Any] = ..., force: bool = ..., update: bool = ...): ... +def pkglist_remove(taginfo: Any, pkginfo: Any, force: bool = ...) -> None: ... +def pkglist_block(taginfo: Any, pkginfo: Any, force: bool = ...) -> None: ... +def pkglist_unblock(taginfo: Any, pkginfo: Any, force: bool = ...) -> None: ... +def pkglist_setowner(taginfo: Any, pkginfo: Any, owner: Any, force: bool = ...) -> None: ... +def pkglist_setarches(taginfo: Any, pkginfo: Any, arches: Any, force: bool = ...) -> None: ... +def readPackageList(tagID: Optional[Any] = ..., userID: Optional[Any] = ..., pkgID: Optional[Any] = ..., event: Optional[Any] = ..., inherit: bool = ..., with_dups: bool = ..., with_owners: bool = ...): ... +def list_tags(build: Optional[Any] = ..., package: Optional[Any] = ..., perms: bool = ..., queryOpts: Optional[Any] = ..., pattern: Optional[Any] = ...): ... +def readTaggedBuilds(tag: Any, event: Optional[Any] = ..., inherit: bool = ..., latest: bool = ..., package: Optional[Any] = ..., owner: Optional[Any] = ..., type: Optional[Any] = ...): ... +def readTaggedRPMS(tag: Any, package: Optional[Any] = ..., arch: Optional[Any] = ..., event: Optional[Any] = ..., inherit: bool = ..., latest: bool = ..., rpmsigs: bool = ..., owner: Optional[Any] = ..., type: Optional[Any] = ...): ... +def readTaggedArchives(tag: Any, package: Optional[Any] = ..., event: Optional[Any] = ..., inherit: bool = ..., latest: bool = ..., type: Optional[Any] = ...): ... +def check_tag_access(tag_id: Any, user_id: Optional[Any] = ...): ... +def assert_tag_access(tag_id: Any, user_id: Optional[Any] = ..., force: bool = ...) -> None: ... +def grplist_add(taginfo: Any, grpinfo: Any, block: bool = ..., force: bool = ..., **opts: Any) -> None: ... +def grplist_remove(taginfo: Any, grpinfo: Any, force: bool = ...) -> None: ... +def grplist_block(taginfo: Any, grpinfo: Any) -> None: ... +def grplist_unblock(taginfo: Any, grpinfo: Any) -> None: ... +def grp_pkg_add(taginfo: Any, grpinfo: Any, pkg_name: Any, block: bool = ..., force: bool = ..., **opts: Any) -> None: ... +def grp_pkg_remove(taginfo: Any, grpinfo: Any, pkg_name: Any, force: bool = ...) -> None: ... +def grp_pkg_block(taginfo: Any, grpinfo: Any, pkg_name: Any) -> None: ... +def grp_pkg_unblock(taginfo: Any, grpinfo: Any, pkg_name: Any) -> None: ... +def grp_req_add(taginfo: Any, grpinfo: Any, reqinfo: Any, block: bool = ..., force: bool = ..., **opts: Any) -> None: ... +def grp_req_remove(taginfo: Any, grpinfo: Any, reqinfo: Any, force: bool = ...) -> None: ... +def grp_req_block(taginfo: Any, grpinfo: Any, reqinfo: Any) -> None: ... +def grp_req_unblock(taginfo: Any, grpinfo: Any, reqinfo: Any) -> None: ... +def get_tag_groups(tag: Any, event: Optional[Any] = ..., inherit: bool = ..., incl_pkgs: bool = ..., incl_reqs: bool = ...): ... +def readTagGroups(tag: Any, event: Optional[Any] = ..., inherit: bool = ..., incl_pkgs: bool = ..., incl_reqs: bool = ..., incl_blocked: bool = ...): ... +def set_host_enabled(hostname: Any, enabled: bool = ...) -> None: ... +def add_host_to_channel(hostname: Any, channel_name: Any, create: bool = ..., force: bool = ...) -> None: ... +def remove_host_from_channel(hostname: Any, channel_name: Any) -> None: ... +def rename_channel(old: Any, new: Any) -> None: ... +def edit_channel(channelInfo: Any, **kw: Any): ... +def remove_channel(channel_name: Any, force: bool = ...) -> None: ... +def add_channel(channel_name: Any, description: Optional[Any] = ...): ... +def set_channel_enabled(channelname: Any, enabled: bool = ..., comment: Optional[Any] = ...) -> None: ... +def get_ready_hosts(): ... +def get_all_arches(): ... +def get_active_tasks(host: Optional[Any] = ...): ... +def get_task_descendents(task: Any, childMap: Optional[Any] = ..., request: bool = ...): ... +def maven_tag_archives(tag_id: Any, event_id: Optional[Any] = ..., inherit: bool = ...): ... +def repo_init(tag: Any, task_id: Optional[Any] = ..., with_src: bool = ..., with_debuginfo: bool = ..., event: Optional[Any] = ..., with_separate_src: bool = ...): ... +def dist_repo_init(tag: Any, keys: Any, task_opts: Any): ... +def repo_set_state(repo_id: Any, state: Any, check: bool = ...) -> None: ... +def repo_info(repo_id: Any, strict: bool = ...): ... +def repo_ready(repo_id: Any) -> None: ... +def repo_expire(repo_id: Any) -> None: ... +def repo_problem(repo_id: Any) -> None: ... +def repo_delete(repo_id: Any): ... +def repo_expire_older(tag_id: Any, event_id: Any, dist: Optional[Any] = ...) -> None: ... +def repo_references(repo_id: Any): ... +def get_active_repos(): ... +def tag_changed_since_event(event: Any, taglist: Any): ... +def set_tag_update(tag_id: Any, utype: Any, event_id: Optional[Any] = ..., user_id: Optional[Any] = ...) -> None: ... +def create_build_target(name: Any, build_tag: Any, dest_tag: Any): ... +def edit_build_target(buildTargetInfo: Any, name: Any, build_tag: Any, dest_tag: Any) -> None: ... +def delete_build_target(buildTargetInfo: Any) -> None: ... +def get_build_targets(info: Optional[Any] = ..., event: Optional[Any] = ..., buildTagID: Optional[Any] = ..., destTagID: Optional[Any] = ..., queryOpts: Optional[Any] = ...): ... +def get_build_target(info: Any, event: Optional[Any] = ..., strict: bool = ...): ... + +def lookup_name( + table: str, + info: Union[str, int], + strict: bool = ..., + create: bool = ...) -> Optional[dict[str, Any]]: + ... + +def get_id(table: Any, info: Any, strict: bool = ..., create: bool = ...): ... +def get_tag_id(info: Any, strict: bool = ..., create: bool = ...): ... +def lookup_tag(info: Any, strict: bool = ..., create: bool = ...): ... +def get_perm_id(info: Any, strict: bool = ..., create: bool = ...): ... +def lookup_perm(info: Any, strict: bool = ..., create: bool = ...): ... +def get_package_id(info: Any, strict: bool = ..., create: bool = ...): ... +def lookup_package(info: Any, strict: bool = ..., create: bool = ...): ... +def get_channel_id(info: Any, strict: bool = ..., create: bool = ...): ... +def lookup_channel(info: Any, strict: bool = ..., create: bool = ...): ... +def get_group_id(info: Any, strict: bool = ..., create: bool = ...): ... +def lookup_group(info: Any, strict: bool = ..., create: bool = ...): ... +def get_build_target_id(info: Any, strict: bool = ..., create: bool = ...): ... +def lookup_build_target(info: Any, strict: bool = ..., create: bool = ...): ... +def create_tag(name: Any, parent: Optional[Any] = ..., arches: Optional[Any] = ..., perm: Optional[Any] = ..., locked: bool = ..., maven_support: bool = ..., maven_include_all: bool = ..., extra: Optional[Any] = ...): ... +def get_tag(tagInfo: Any, strict: bool = ..., event: Optional[Any] = ..., blocked: bool = ...): ... +def get_tag_extra(tagInfo: Any, event: Optional[Any] = ..., blocked: bool = ...): ... +def edit_tag(tagInfo: Any, **kwargs: Any) -> None: ... +def old_edit_tag(tagInfo: Any, name: Any, arches: Any, locked: Any, permissionID: Any, extra: Optional[Any] = ...): ... +def delete_tag(tagInfo: Any) -> None: ... +def get_external_repo_id(info: Any, strict: bool = ..., create: bool = ...): ... +def create_external_repo(name: Any, url: Any): ... +def get_external_repos(info: Optional[Any] = ..., url: Optional[Any] = ..., event: Optional[Any] = ..., queryOpts: Optional[Any] = ...): ... +def get_external_repo(info: Any, strict: bool = ..., event: Optional[Any] = ...): ... +def edit_external_repo(info: Any, name: Optional[Any] = ..., url: Optional[Any] = ...) -> None: ... +def delete_external_repo(info: Any) -> None: ... +def add_external_repo_to_tag(tag_info: Any, repo_info: Any, priority: Any, merge_mode: str = ..., arches: Optional[Any] = ...) -> None: ... +def remove_external_repo_from_tag(tag_info: Any, repo_info: Any) -> None: ... +def edit_tag_external_repo(tag_info: Any, repo_info: Any, priority: Optional[Any] = ..., merge_mode: Optional[Any] = ..., arches: Optional[Any] = ...): ... +def get_tag_external_repos(tag_info: Optional[Any] = ..., repo_info: Optional[Any] = ..., event: Optional[Any] = ...): ... +def get_external_repo_list(tag_info: Any, event: Optional[Any] = ...): ... +def get_user(userInfo: Optional[Any] = ..., strict: bool = ..., krb_princs: bool = ...): ... +def edit_user(userInfo: Any, name: Optional[Any] = ..., krb_principal_mappings: Optional[Any] = ...) -> None: ... +def list_user_krb_principals(user_info: Optional[Any] = ...): ... +def get_user_by_krb_principal(krb_principal: Any, strict: bool = ..., krb_princs: bool = ...): ... +def find_build_id(X: Any, strict: bool = ...): ... + +def get_build( + buildInfo: Any, + strict: bool = ...) -> _NVRInfo: + ... + +def get_build_logs(build: Any): ... + +def get_next_release(build_info: Any): ... +def get_rpm(rpminfo: Any, strict: bool = ..., multi: bool = ...): ... +def list_rpms(buildID: Optional[Any] = ..., buildrootID: Optional[Any] = ..., imageID: Optional[Any] = ..., componentBuildrootID: Optional[Any] = ..., hostID: Optional[Any] = ..., arches: Optional[Any] = ..., queryOpts: Optional[Any] = ...): ... +def get_maven_build(buildInfo: Any, strict: bool = ...): ... +def get_win_build(buildInfo: Any, strict: bool = ...): ... +def get_image_build(buildInfo: Any, strict: bool = ...): ... +def get_build_type(buildInfo: Any, strict: bool = ...): ... +def list_btypes(query: Optional[Any] = ..., queryOpts: Optional[Any] = ...): ... +def add_btype(name: Any) -> None: ... +def list_archives(buildID: Optional[Any] = ..., buildrootID: Optional[Any] = ..., componentBuildrootID: Optional[Any] = ..., hostID: Optional[Any] = ..., type: Optional[Any] = ..., filename: Optional[Any] = ..., size: Optional[Any] = ..., checksum: Optional[Any] = ..., typeInfo: Optional[Any] = ..., queryOpts: Optional[Any] = ..., imageID: Optional[Any] = ..., archiveID: Optional[Any] = ..., strict: bool = ...): ... +def get_archive(archive_id: Any, strict: bool = ...): ... +def get_maven_archive(archive_id: Any, strict: bool = ...): ... +def get_win_archive(archive_id: Any, strict: bool = ...): ... +def get_image_archive(archive_id: Any, strict: bool = ...): ... +def list_archive_files(archive_id: Any, queryOpts: Optional[Any] = ..., strict: bool = ...): ... +def get_archive_file(archive_id: Any, filename: Any, strict: bool = ...): ... +def list_task_output(taskID: Any, stat: bool = ..., all_volumes: bool = ..., strict: bool = ...): ... +def get_host(hostInfo: Any, strict: bool = ..., event: Optional[Any] = ...): ... +def edit_host(hostInfo: Any, **kw: Any): ... +def get_channel(channelInfo: Any, strict: bool = ...): ... +def query_buildroots(hostID: Optional[Any] = ..., tagID: Optional[Any] = ..., state: Optional[Any] = ..., rpmID: Optional[Any] = ..., archiveID: Optional[Any] = ..., taskID: Optional[Any] = ..., buildrootID: Optional[Any] = ..., queryOpts: Optional[Any] = ...): ... +def get_buildroot(buildrootID: Any, strict: bool = ...): ... +def list_channels(hostID: Optional[Any] = ..., event: Optional[Any] = ..., enabled: Optional[Any] = ...): ... +def new_package(name: Any, strict: bool = ...): ... +def add_volume(name: Any, strict: bool = ...): ... +def remove_volume(volume: Any) -> None: ... +def list_volumes(): ... +def change_build_volume(build: Any, volume: Any, strict: bool = ...) -> None: ... +def ensure_volume_symlink(binfo: Any) -> None: ... +def check_volume_policy(data: Any, strict: bool = ..., default: Optional[Any] = ...): ... +def apply_volume_policy(build: Any, strict: bool = ...) -> None: ... +def new_build(data: Any, strict: bool = ...): ... +def recycle_build(old: Any, data: Any) -> None: ... +def check_noarch_rpms(basepath: Any, rpms: Any, logs: Optional[Any] = ...): ... +def import_build(srpm: Any, rpms: Any, brmap: Optional[Any] = ..., task_id: Optional[Any] = ..., build_id: Optional[Any] = ..., logs: Optional[Any] = ...): ... +def import_rpm(fn: Any, buildinfo: Optional[Any] = ..., brootid: Optional[Any] = ..., wrapper: bool = ..., fileinfo: Optional[Any] = ...): ... +def generate_token(nbytes: int = ...): ... +def get_reservation_token(build_id: Any): ... +def clear_reservation(build_id: Any) -> None: ... +def cg_init_build(cg: Any, data: Any): ... +def cg_refund_build(cg: Any, build_id: Any, token: Any, state: Any = ...) -> None: ... +def cg_import(metadata: Any, directory: Any, token: Optional[Any] = ...): ... + +class CG_Importer: + buildinfo: Any = ... + metadata_only: bool = ... + def __init__(self) -> None: ... + directory: Any = ... + def do_import(self, metadata: Any, directory: Any, token: Optional[Any] = ...): ... + metadata: Any = ... + raw_metadata: Any = ... + def get_metadata(self, metadata: Any, directory: Any): ... + cg: Any = ... + def assert_cg_access(self) -> None: ... + def assert_policy(self) -> None: ... + def set_volume(self) -> None: ... + def check_build_dir(self, delete: bool = ...) -> None: ... + typeinfo: Any = ... + def prep_build(self, token: Optional[Any] = ...): ... + def get_build(self, token: Optional[Any] = ...): ... + def update_build(self): ... + def import_metadata(self) -> None: ... + br_prep: Any = ... + def prep_brs(self) -> None: ... + brmap: Any = ... + def import_brs(self) -> None: ... + def prep_buildroot(self, brdata: Any): ... + def import_buildroot(self, entry: Any): ... + def match_components(self, components: Any): ... + def match_rpm(self, comp: Any): ... + def match_file(self, comp: Any): ... + def match_kojifile(self, comp: Any): ... + prepped_outputs: Any = ... + def prep_outputs(self) -> None: ... + def import_outputs(self) -> None: ... + def prep_archive(self, fileinfo: Any) -> None: ... + def import_rpm(self, buildinfo: Any, brinfo: Any, fileinfo: Any) -> None: ... + def import_log(self, buildinfo: Any, fileinfo: Any) -> None: ... + def import_archive(self, buildinfo: Any, brinfo: Any, fileinfo: Any) -> None: ... + def import_components(self, archive_id: Any, fileinfo: Any) -> None: ... + +def add_external_rpm(rpminfo: Any, external_repo: Any, strict: bool = ...): ... +def import_build_log(fn: Any, buildinfo: Any, subdir: Optional[Any] = ...) -> None: ... +def import_rpm_file(fn: Any, buildinfo: Any, rpminfo: Any) -> None: ... +def merge_scratch(task_id: Any): ... +def get_archive_types(): ... +def get_archive_type(filename: Optional[Any] = ..., type_name: Optional[Any] = ..., type_id: Optional[Any] = ..., strict: bool = ...): ... +def add_archive_type(name: str, description: str, extensions: Any, compression_type: str) -> None: ... +def new_maven_build(build: Any, maven_info: Any) -> None: ... +def new_win_build(build_info: Any, win_info: Any) -> None: ... +def new_image_build(build_info: Any) -> None: ... +def new_typed_build(build_info: Any, btype: Any) -> None: ... +def import_archive(filepath: Any, buildinfo: Any, type: Any, typeInfo: Any, buildroot_id: Optional[Any] = ...): ... +def import_archive_internal(filepath: Any, buildinfo: Any, type: Any, typeInfo: Any, buildroot_id: Optional[Any] = ..., fileinfo: Optional[Any] = ...): ... +def add_rpm_sig(an_rpm: Any, sighdr: Any) -> None: ... +def delete_rpm_sig(rpminfo: Any, sigkey: Optional[Any] = ..., all_sigs: bool = ...) -> None: ... +def check_rpm_sig(an_rpm: Any, sigkey: Any, sighdr: Any) -> None: ... +def query_rpm_sigs(rpm_id: Optional[Any] = ..., sigkey: Optional[Any] = ..., queryOpts: Optional[Any] = ...): ... +def write_signed_rpm(an_rpm: Any, sigkey: Any, force: bool = ...) -> None: ... +def query_history(tables: Optional[Any] = ..., **kwargs: Any): ... +def untagged_builds(name: Optional[Any] = ..., queryOpts: Optional[Any] = ...): ... +def build_references(build_id: Any, limit: Optional[Any] = ..., lazy: bool = ...): ... +def delete_build(build: Any, strict: bool = ..., min_ref_age: int = ...): ... +def reset_build(build: Any) -> None: ... +def cancel_build(build_id: Any, cancel_task: bool = ...): ... +def get_notification_recipients(build: Any, tag_id: Any, state: Any): ... +def tag_notification(is_successful: Any, tag_id: Any, from_id: Any, build_id: Any, user_id: Any, ignore_success: bool = ..., failure_msg: str = ...): ... +def build_notification(task_id: Any, build_id: Any) -> None: ... +def get_build_notifications(user_id: Any): ... +def get_build_notification_blocks(user_id: Any): ... +def new_group(name: Any): ... +def add_group_member(group: Any, user: Any, strict: bool = ...) -> None: ... +def drop_group_member(group: Any, user: Any) -> None: ... +def get_group_members(group: Any): ... +def set_user_status(user: Any, status: Any) -> None: ... +def list_cgs(): ... +def grant_cg_access(user: Any, cg: Any, create: bool = ...) -> None: ... +def revoke_cg_access(user: Any, cg: Any) -> None: ... +def assert_cg(cg: Any, user: Optional[Any] = ...) -> None: ... +def get_event(): ... +def nextval(sequence: Any): ... + +class Savepoint: + name: Any = ... + def __init__(self, name: Any) -> None: ... + def rollback(self) -> None: ... + +def parse_json(value: Any, desc: Optional[Any] = ..., errstr: Optional[Any] = ...): ... + +class BulkInsertProcessor: + table: Any = ... + data: Any = ... + columns: Any = ... + strict: Any = ... + batch: Any = ... + def __init__(self, table: Any, data: Optional[Any] = ..., columns: Optional[Any] = ..., strict: bool = ..., batch: int = ...) -> None: ... + def add_record(self, **kwargs: Any) -> None: ... + def execute(self) -> None: ... + +class InsertProcessor: + table: Any = ... + data: Any = ... + rawdata: Any = ... + def __init__(self, table: Any, data: Optional[Any] = ..., rawdata: Optional[Any] = ...) -> None: ... + def set(self, **kwargs: Any) -> None: ... + def rawset(self, **kwargs: Any) -> None: ... + def make_create(self, event_id: Optional[Any] = ..., user_id: Optional[Any] = ...) -> None: ... + def dup_check(self): ... + def execute(self): ... + +class UpdateProcessor: + table: Any = ... + data: Any = ... + rawdata: Any = ... + clauses: Any = ... + values: Any = ... + def __init__(self, table: Any, data: Optional[Any] = ..., rawdata: Optional[Any] = ..., clauses: Optional[Any] = ..., values: Optional[Any] = ...) -> None: ... + def get_values(self): ... + def set(self, **kwargs: Any) -> None: ... + def rawset(self, **kwargs: Any) -> None: ... + def make_revoke(self, event_id: Optional[Any] = ..., user_id: Optional[Any] = ...) -> None: ... + def execute(self): ... + +class OperationTest(koji.policy.MatchTest): + name: str = ... + field: str = ... + +def policy_get_user(data: Any): ... +def policy_get_pkg(data: Any): ... +def policy_get_version(data: Any): ... +def policy_get_release(data: Any): ... +def policy_get_brs(data: Any): ... +def policy_get_cgs(data: Any): ... +def policy_get_build_tags(data: Any, taginfo: bool = ...): ... +def policy_get_build_types(data: Any): ... + +class NewPackageTest(koji.policy.BaseSimpleTest): + name: str = ... + def run(self, data: Any): ... + +class PackageTest(koji.policy.MatchTest): + name: str = ... + field: str = ... + def run(self, data: Any): ... + +class VersionTest(koji.policy.MatchTest): + name: str = ... + field: str = ... + def run(self, data: Any): ... + +class ReleaseTest(koji.policy.MatchTest): + name: str = ... + field: str = ... + def run(self, data: Any): ... + +class VolumeTest(koji.policy.MatchTest): + name: str = ... + field: str = ... + def run(self, data: Any): ... + +class CGMatchAnyTest(koji.policy.BaseSimpleTest): + name: str = ... + def run(self, data: Any): ... + +class CGMatchAllTest(koji.policy.BaseSimpleTest): + name: str = ... + def run(self, data: Any): ... + +class TagTest(koji.policy.MatchTest): + name: str = ... + field: str = ... + def get_tag(self, data: Any): ... + def run(self, data: Any): ... + +class FromTagTest(TagTest): + name: str = ... + def get_tag(self, data: Any): ... + +class HasTagTest(koji.policy.BaseSimpleTest): + name: str = ... + def run(self, data: Any): ... + +class SkipTagTest(koji.policy.BaseSimpleTest): + name: str = ... + def run(self, data: Any): ... + +class BuildTagTest(koji.policy.BaseSimpleTest): + name: str = ... + def run(self, data: Any): ... + +class BuildTagInheritsFromTest(koji.policy.BaseSimpleTest): + name: str = ... + def run(self, data: Any): ... + +class BuildTypeTest(koji.policy.BaseSimpleTest): + name: str = ... + def run(self, data: Any): ... + +class ImportedTest(koji.policy.BaseSimpleTest): + name: str = ... + def run(self, data: Any): ... + +class ChildTaskTest(koji.policy.BoolTest): + name: str = ... + field: str = ... + +class MethodTest(koji.policy.MatchTest): + name: str = ... + field: str = ... + +class UserTest(koji.policy.MatchTest): + name: str = ... + field: str = ... + def run(self, data: Any): ... + +class VMTest(koji.policy.MatchTest): + name: str = ... + field: str = ... + +class IsBuildOwnerTest(koji.policy.BaseSimpleTest): + name: str = ... + def run(self, data: Any): ... + +class UserInGroupTest(koji.policy.BaseSimpleTest): + name: str = ... + def run(self, data: Any): ... + +class HasPermTest(koji.policy.BaseSimpleTest): + name: str = ... + def run(self, data: Any): ... + +class SourceTest(koji.policy.MatchTest): + name: str = ... + field: str = ... + def run(self, data: Any): ... + +class PolicyTest(koji.policy.BaseSimpleTest): + name: str = ... + def __init__(self, str: Any) -> None: ... + def run(self, data: Any): ... + +def check_policy(name: Any, data: Any, default: str = ..., strict: bool = ..., force: bool = ...): ... +def eval_policy(name: Any, data: Any): ... +def policy_data_from_task(task_id: Any): ... +def policy_data_from_task_args(method: Any, arglist: Any): ... +def assert_policy(name: Any, data: Any, default: str = ..., force: bool = ...) -> None: ... +def rpmdiff(basepath: Any, rpmlist: Any, hashes: Any) -> None: ... +def importImageInternal(task_id: Any, build_info: Any, imgdata: Any) -> None: ... + +class RootExports: + def restartHosts(self, priority: int = ..., options: Optional[Any] = ...): ... + def build(self, src: Any, target: Any, opts: Optional[Any] = ..., priority: Optional[Any] = ..., channel: Optional[Any] = ...): ... + def chainBuild(self, srcs: Any, target: Any, opts: Optional[Any] = ..., priority: Optional[Any] = ..., channel: Optional[Any] = ...): ... + def mavenBuild(self, url: Any, target: Any, opts: Optional[Any] = ..., priority: Optional[Any] = ..., channel: str = ...): ... + def wrapperRPM(self, build: Any, url: Any, target: Any, priority: Optional[Any] = ..., channel: str = ..., opts: Optional[Any] = ...): ... + def chainMaven(self, builds: Any, target: Any, opts: Optional[Any] = ..., priority: Optional[Any] = ..., channel: str = ...): ... + def winBuild(self, vm: Any, url: Any, target: Any, opts: Optional[Any] = ..., priority: Optional[Any] = ..., channel: str = ...): ... + def buildImage(self, name: Any, version: Any, arch: Any, target: Any, ksfile: Any, img_type: Any, opts: Optional[Any] = ..., priority: Optional[Any] = ...): ... + def buildImageIndirection(self, opts: Optional[Any] = ..., priority: Optional[Any] = ...): ... + def buildImageOz(self, name: Any, version: Any, arches: Any, target: Any, inst_tree: Any, opts: Optional[Any] = ..., priority: Optional[Any] = ...): ... + def hello(self, *args: Any): ... + def fault(self) -> None: ... + def error(self) -> None: ... + def echo(self, *args: Any): ... + def getKojiVersion(self): ... + def getAPIVersion(self): ... + def mavenEnabled(self): ... + def winEnabled(self): ... + def showSession(self): ... + def getSessionInfo(self): ... + def showOpts(self): ... + def getEvent(self, id: Any): ... + def getLastEvent(self, before: Optional[Any] = ...): ... + evalPolicy: Any = ... + def makeTask(self, *args: Any, **opts: Any): ... + def uploadFile(self, path: Any, name: Any, size: Any, md5sum: Any, offset: Any, data: Any, volume: Optional[Any] = ..., checksum: Optional[Any] = ...): ... + def checkUpload(self, path: Any, name: Any, verify: Optional[Any] = ..., tail: Optional[Any] = ..., volume: Optional[Any] = ...): ... + def downloadTaskOutput(self, taskID: Any, fileName: Any, offset: int = ..., size: int = ..., volume: Optional[Any] = ...): ... + listTaskOutput: Any = ... + createTag: Any = ... + editTag: Any = ... + editTag2: Any = ... + deleteTag: Any = ... + createExternalRepo: Any = ... + listExternalRepos: Any = ... + getExternalRepo: Any = ... + editExternalRepo: Any = ... + deleteExternalRepo: Any = ... + def addExternalRepoToTag(self, tag_info: Any, repo_info: Any, priority: Any, merge_mode: str = ..., arches: Optional[Any] = ...) -> None: ... + def removeExternalRepoFromTag(self, tag_info: Any, repo_info: Any) -> None: ... + editTagExternalRepo: Any = ... + getTagExternalRepos: Any = ... + getExternalRepoList: Any = ... + resetBuild: Any = ... + def importArchive(self, filepath: Any, buildinfo: Any, type: Any, typeInfo: Any) -> None: ... + CGInitBuild: Any = ... + CGRefundBuild: Any = ... + CGImport: Any = ... + untaggedBuilds: Any = ... + queryHistory: Any = ... + deleteBuild: Any = ... + def buildReferences(self, build: Any, limit: Optional[Any] = ..., lazy: bool = ...): ... + addVolume: Any = ... + removeVolume: Any = ... + listVolumes: Any = ... + changeBuildVolume: Any = ... + def getVolume(self, volume: Any, strict: bool = ...): ... + def applyVolumePolicy(self, build: Any, strict: bool = ...): ... + def createEmptyBuild(self, name: Any, version: Any, release: Any, epoch: Any, owner: Optional[Any] = ...): ... + def createMavenBuild(self, build_info: Any, maven_info: Any) -> None: ... + def createWinBuild(self, build_info: Any, win_info: Any) -> None: ... + def createImageBuild(self, build_info: Any) -> None: ... + def importRPM(self, path: Any, basename: Any) -> None: ... + def mergeScratch(self, task_id: Any): ... + def addExternalRPM(self, rpminfo: Any, external_repo: Any, strict: bool = ...) -> None: ... + def tagBuildBypass(self, tag: Any, build: Any, force: bool = ..., notify: bool = ...) -> None: ... + def tagBuild(self, tag: Any, build: Any, force: bool = ..., fromtag: Optional[Any] = ...): ... + def untagBuild(self, tag: Any, build: Any, strict: bool = ..., force: bool = ...) -> None: ... + def untagBuildBypass(self, tag: Any, build: Any, strict: bool = ..., force: bool = ..., notify: bool = ...) -> None: ... + def moveBuild(self, tag1: Any, tag2: Any, build: Any, force: bool = ...): ... + def moveAllBuilds(self, tag1: Any, tag2: Any, package: Any, force: bool = ...): ... + listTags: Any = ... + getBuild: Any = ... + getBuildLogs: Any = ... + getNextRelease: Any = ... + getMavenBuild: Any = ... + getWinBuild: Any = ... + getImageBuild: Any = ... + getBuildType: Any = ... + getArchiveTypes: Any = ... + getArchiveType: Any = ... + listArchives: Any = ... + getArchive: Any = ... + getMavenArchive: Any = ... + getWinArchive: Any = ... + getImageArchive: Any = ... + listArchiveFiles: Any = ... + getArchiveFile: Any = ... + listBTypes: Any = ... + addBType: Any = ... + addArchiveType: Any = ... + def getChangelogEntries(self, buildID: Optional[Any] = ..., taskID: Optional[Any] = ..., filepath: Optional[Any] = ..., author: Optional[Any] = ..., before: Optional[Any] = ..., after: Optional[Any] = ..., queryOpts: Optional[Any] = ..., strict: bool = ...): ... + def cancelBuild(self, buildID: Any): ... + def assignTask(self, task_id: Any, host: Any, force: bool = ...): ... + def freeTask(self, task_id: Any) -> None: ... + def cancelTask(self, task_id: Any, recurse: bool = ...) -> None: ... + def cancelTaskFull(self, task_id: Any, strict: bool = ...) -> None: ... + def cancelTaskChildren(self, task_id: Any) -> None: ... + def setTaskPriority(self, task_id: Any, priority: Any, recurse: bool = ...) -> None: ... + def listTagged(self, tag: Any, event: Optional[Any] = ..., inherit: bool = ..., prefix: Optional[Any] = ..., latest: bool = ..., package: Optional[Any] = ..., owner: Optional[Any] = ..., type: Optional[Any] = ...): ... + def listTaggedRPMS(self, tag: Any, event: Optional[Any] = ..., inherit: bool = ..., latest: bool = ..., package: Optional[Any] = ..., arch: Optional[Any] = ..., rpmsigs: bool = ..., owner: Optional[Any] = ..., type: Optional[Any] = ...): ... + def listTaggedArchives(self, tag: Any, event: Optional[Any] = ..., inherit: bool = ..., latest: bool = ..., package: Optional[Any] = ..., type: Optional[Any] = ...): ... + def listBuilds(self, packageID: Optional[Any] = ..., userID: Optional[Any] = ..., taskID: Optional[Any] = ..., prefix: Optional[Any] = ..., state: Optional[Any] = ..., volumeID: Optional[Any] = ..., source: Optional[Any] = ..., createdBefore: Optional[Any] = ..., createdAfter: Optional[Any] = ..., completeBefore: Optional[Any] = ..., completeAfter: Optional[Any] = ..., type: Optional[Any] = ..., typeInfo: Optional[Any] = ..., queryOpts: Optional[Any] = ..., pattern: Optional[Any] = ...): ... + def getLatestBuilds(self, tag: Any, event: Optional[Any] = ..., package: Optional[Any] = ..., type: Optional[Any] = ...): ... + def getLatestRPMS(self, tag: Any, package: Optional[Any] = ..., arch: Optional[Any] = ..., event: Optional[Any] = ..., rpmsigs: bool = ..., type: Optional[Any] = ...): ... + def getLatestMavenArchives(self, tag: Any, event: Optional[Any] = ..., inherit: bool = ...): ... + def getAverageBuildDuration(self, package: Any, age: Optional[Any] = ...): ... + packageListAdd: Any = ... + packageListRemove: Any = ... + packageListBlock: Any = ... + packageListUnblock: Any = ... + packageListSetOwner: Any = ... + packageListSetArches: Any = ... + groupListAdd: Any = ... + groupListRemove: Any = ... + groupListBlock: Any = ... + groupListUnblock: Any = ... + groupPackageListAdd: Any = ... + groupPackageListRemove: Any = ... + groupPackageListBlock: Any = ... + groupPackageListUnblock: Any = ... + groupReqListAdd: Any = ... + groupReqListRemove: Any = ... + groupReqListBlock: Any = ... + groupReqListUnblock: Any = ... + getTagGroups: Any = ... + checkTagAccess: Any = ... + def getInheritanceData(self, tag: Any, event: Optional[Any] = ...): ... + def setInheritanceData(self, tag: Any, data: Any, clear: bool = ...): ... + def getFullInheritance(self, tag: Any, event: Optional[Any] = ..., reverse: bool = ...): ... + listRPMs: Any = ... + def listBuildRPMs(self, build: Any): ... + getRPM: Any = ... + def getRPMDeps(self, rpmID: Any, depType: Optional[Any] = ..., queryOpts: Optional[Any] = ..., strict: bool = ...): ... + def listRPMFiles(self, rpmID: Any, queryOpts: Optional[Any] = ...): ... + def getRPMFile(self, rpmID: Any, filename: Any, strict: bool = ...): ... + def getRPMHeaders(self, rpmID: Optional[Any] = ..., taskID: Optional[Any] = ..., filepath: Optional[Any] = ..., headers: Optional[Any] = ...): ... + queryRPMSigs: Any = ... + def writeSignedRPM(self, an_rpm: Any, sigkey: Any, force: bool = ...): ... + def addRPMSig(self, an_rpm: Any, data: Any): ... + def deleteRPMSig(self, rpminfo: Any, sigkey: Optional[Any] = ..., all_sigs: bool = ...): ... + findBuildID: Any = ... + getTagID: Any = ... + getTag: Any = ... + def getPackageID(self, name: Any, strict: bool = ...): ... + getPackage: Any = ... + def listPackages(self, tagID: Optional[Any] = ..., userID: Optional[Any] = ..., pkgID: Optional[Any] = ..., prefix: Optional[Any] = ..., inherited: bool = ..., with_dups: bool = ..., event: Optional[Any] = ..., queryOpts: Optional[Any] = ..., with_owners: bool = ...): ... + def listPackagesSimple(self, prefix: Optional[Any] = ..., queryOpts: Optional[Any] = ...): ... + def checkTagPackage(self, tag: Any, pkg: Any): ... + def getPackageConfig(self, tag: Any, pkg: Any, event: Optional[Any] = ...): ... + getUser: Any = ... + editUser: Any = ... + def grantPermission(self, userinfo: Any, permission: Any, create: bool = ...) -> None: ... + def revokePermission(self, userinfo: Any, permission: Any) -> None: ... + def createUser(self, username: Any, status: Optional[Any] = ..., krb_principal: Optional[Any] = ...): ... + def addUserKrbPrincipal(self, user: Any, krb_principal: Any): ... + def removeUserKrbPrincipal(self, user: Any, krb_principal: Any): ... + def enableUser(self, username: Any) -> None: ... + def disableUser(self, username: Any) -> None: ... + listCGs: Any = ... + grantCGAccess: Any = ... + revokeCGAccess: Any = ... + newGroup: Any = ... + addGroupMember: Any = ... + dropGroupMember: Any = ... + getGroupMembers: Any = ... + def listUsers(self, userType: Any = ..., prefix: Optional[Any] = ..., queryOpts: Optional[Any] = ...): ... + def getBuildConfig(self, tag: Any, event: Optional[Any] = ...): ... + def getRepo(self, tag: Any, state: Optional[Any] = ..., event: Optional[Any] = ..., dist: bool = ...): ... + repoInfo: Any = ... + getActiveRepos: Any = ... + def distRepo(self, tag: Any, keys: Any, **task_opts: Any): ... + def newRepo(self, tag: Any, event: Optional[Any] = ..., src: bool = ..., debuginfo: bool = ..., separate_src: bool = ...): ... + def repoExpire(self, repo_id: Any) -> None: ... + def repoDelete(self, repo_id: Any): ... + def repoProblem(self, repo_id: Any) -> None: ... + tagChangedSinceEvent: Any = ... + createBuildTarget: Any = ... + editBuildTarget: Any = ... + deleteBuildTarget: Any = ... + getBuildTargets: Any = ... + getBuildTarget: Any = ... + def taskFinished(self, taskId: Any): ... + def getTaskRequest(self, taskId: Any): ... + def getTaskResult(self, taskId: Any, raise_fault: bool = ...): ... + def getTaskInfo(self, task_id: Any, request: bool = ..., strict: bool = ...): ... + def getTaskChildren(self, task_id: Any, request: bool = ..., strict: bool = ...): ... + def getTaskDescendents(self, task_id: Any, request: bool = ...): ... + def listTasks(self, opts: Optional[Any] = ..., queryOpts: Optional[Any] = ...): ... + def taskReport(self, owner: Optional[Any] = ...): ... + def resubmitTask(self, taskID: Any): ... + def addHost(self, hostname: Any, arches: Any, krb_principal: Optional[Any] = ..., force: bool = ...): ... + def enableHost(self, hostname: Any) -> None: ... + def disableHost(self, hostname: Any) -> None: ... + def enableChannel(self, channelname: Any, comment: Optional[Any] = ...) -> None: ... + def disableChannel(self, channelname: Any, comment: Optional[Any] = ...) -> None: ... + getHost: Any = ... + editHost: Any = ... + addHostToChannel: Any = ... + removeHostFromChannel: Any = ... + renameChannel: Any = ... + editChannel: Any = ... + removeChannel: Any = ... + addChannel: Any = ... + def listHosts(self, arches: Optional[Any] = ..., channelID: Optional[Any] = ..., ready: Optional[Any] = ..., enabled: Optional[Any] = ..., userID: Optional[Any] = ..., queryOpts: Optional[Any] = ...): ... + def getLastHostUpdate(self, hostID: Any, ts: bool = ...): ... + getAllArches: Any = ... + getChannel: Any = ... + listChannels: Any = ... + getBuildroot: Any = ... + def getBuildrootListing(self, id: Any): ... + listBuildroots: Any = ... + def hasPerm(self, perm: Any, strict: bool = ...): ... + def getPerms(self): ... + def getUserPerms(self, userID: Optional[Any] = ...): ... + def getAllPerms(self): ... + def getLoggedInUser(self): ... + def setBuildOwner(self, build: Any, user: Any) -> None: ... + def setBuildTimestamp(self, build: Any, ts: Any) -> None: ... + def count(self, methodName: Any, *args: Any, **kw: Any): ... + def filterResults(self, methodName: Any, *args: Any, **kw: Any): ... + def countAndFilterResults(self, methodName: Any, *args: Any, **kw: Any): ... + def getBuildNotifications(self, userID: Optional[Any] = ...): ... + def getBuildNotification(self, id: Any, strict: bool = ...): ... + def getBuildNotificationBlocks(self, userID: Optional[Any] = ...): ... + def getBuildNotificationBlock(self, id: Any, strict: bool = ...): ... + def updateNotification(self, id: Any, package_id: Any, tag_id: Any, success_only: Any) -> None: ... + def createNotification(self, user_id: Any, package_id: Any, tag_id: Any, success_only: Any) -> None: ... + def deleteNotification(self, id: Any) -> None: ... + def createNotificationBlock(self, user_id: Any, package_id: Optional[Any] = ..., tag_id: Optional[Any] = ...) -> None: ... + def deleteNotificationBlock(self, id: Any) -> None: ... + def search(self, terms: Any, type: Any, matchType: Any, queryOpts: Optional[Any] = ...): ... + +class BuildRoot: + id: Any = ... + def __init__(self, id: Optional[Any] = ...) -> None: ... + data: Any = ... + is_standard: bool = ... + def load(self, id: Any) -> None: ... + def new(self, host: Any, repo: Any, arch: Any, task_id: Optional[Any] = ..., ctype: str = ...): ... + def cg_new(self, data: Any): ... + def assertStandard(self) -> None: ... + def verifyTask(self, task_id: Any): ... + def assertTask(self, task_id: Any) -> None: ... + def verifyHost(self, host_id: Any): ... + def assertHost(self, host_id: Any) -> None: ... + def setState(self, state: Any) -> None: ... + def getList(self): ... + def setList(self, rpmlist: Any) -> None: ... + def updateList(self, rpmlist: Any) -> None: ... + def getArchiveList(self, queryOpts: Optional[Any] = ...): ... + def updateArchiveList(self, archives: Any, project: bool = ...) -> None: ... + def setTools(self, tools: Any) -> None: ... + +class Host: + id: Any = ... + same_host: Any = ... + def __init__(self, id: Optional[Any] = ...) -> None: ... + def verify(self): ... + def taskUnwait(self, parent: Any) -> None: ... + def taskSetWait(self, parent: Any, tasks: Any) -> None: ... + def taskWaitCheck(self, parent: Any): ... + def taskWait(self, parent: Any): ... + def taskWaitResults(self, parent: Any, tasks: Any, canfail: Optional[Any] = ...): ... + def getHostTasks(self): ... + def updateHost(self, task_load: Any, ready: Any) -> None: ... + def getLoadData(self): ... + def getTask(self): ... + def isEnabled(self): ... + +class HostExports: + def getID(self): ... + def updateHost(self, task_load: Any, ready: Any) -> None: ... + def getLoadData(self): ... + def getHost(self): ... + def openTask(self, task_id: Any): ... + def closeTask(self, task_id: Any, response: Any): ... + def failTask(self, task_id: Any, response: Any): ... + def freeTasks(self, tasks: Any) -> None: ... + def setTaskWeight(self, task_id: Any, weight: Any): ... + def getHostTasks(self): ... + def taskSetWait(self, parent: Any, tasks: Any): ... + def taskWait(self, parent: Any): ... + def taskWaitResults(self, parent: Any, tasks: Any, canfail: Optional[Any] = ...): ... + def subtask(self, method: Any, arglist: Any, parent: Any, **opts: Any): ... + def subtask2(self, __parent: Any, __taskopts: Any, __method: Any, *args: Any, **opts: Any): ... + def moveBuildToScratch(self, task_id: Any, srpm: Any, rpms: Any, logs: Optional[Any] = ...) -> None: ... + def moveMavenBuildToScratch(self, task_id: Any, results: Any, rpm_results: Any) -> None: ... + def moveWinBuildToScratch(self, task_id: Any, results: Any, rpm_results: Any) -> None: ... + def moveImageBuildToScratch(self, task_id: Any, results: Any) -> None: ... + def initBuild(self, data: Any): ... + def completeBuild(self, task_id: Any, build_id: Any, srpm: Any, rpms: Any, brmap: Optional[Any] = ..., logs: Optional[Any] = ...): ... + def completeImageBuild(self, task_id: Any, build_id: Any, results: Any) -> None: ... + def initMavenBuild(self, task_id: Any, build_info: Any, maven_info: Any): ... + def createMavenBuild(self, build_info: Any, maven_info: Any) -> None: ... + def completeMavenBuild(self, task_id: Any, build_id: Any, maven_results: Any, rpm_results: Any) -> None: ... + def importArchive(self, filepath: Any, buildinfo: Any, type: Any, typeInfo: Any) -> None: ... + def importWrapperRPMs(self, task_id: Any, build_id: Any, rpm_results: Any) -> None: ... + def initImageBuild(self, task_id: Any, build_info: Any): ... + def initWinBuild(self, task_id: Any, build_info: Any, win_info: Any): ... + def completeWinBuild(self, task_id: Any, build_id: Any, results: Any, rpm_results: Any) -> None: ... + def failBuild(self, task_id: Any, build_id: Any) -> None: ... + def tagBuild(self, task_id: Any, tag: Any, build: Any, force: bool = ..., fromtag: Optional[Any] = ...) -> None: ... + def importImage(self, task_id: Any, build_info: Any, results: Any) -> None: ... + def tagNotification(self, is_successful: Any, tag_id: Any, from_id: Any, build_id: Any, user_id: Any, ignore_success: bool = ..., failure_msg: str = ...) -> None: ... + def checkPolicy(self, name: Any, data: Any, default: str = ..., strict: bool = ...): ... + def assertPolicy(self, name: Any, data: Any, default: str = ...) -> None: ... + def evalPolicy(self, name: Any, data: Any): ... + def newBuildRoot(self, repo: Any, arch: Any, task_id: Optional[Any] = ...): ... + def setBuildRootState(self, brootid: Any, state: Any, task_id: Optional[Any] = ...): ... + def setBuildRootList(self, brootid: Any, rpmlist: Any, task_id: Optional[Any] = ...): ... + def updateBuildRootList(self, brootid: Any, rpmlist: Any, task_id: Optional[Any] = ...): ... + def updateBuildrootArchives(self, brootid: Any, task_id: Any, archives: Any, project: bool = ...): ... + def updateMavenBuildRootList(self, brootid: Any, task_id: Any, mavenlist: Any, ignore: Optional[Any] = ..., project: bool = ..., ignore_unknown: bool = ..., extra_deps: Optional[Any] = ...): ... + def repoInit(self, tag: Any, task_id: Optional[Any] = ..., with_src: bool = ..., with_debuginfo: bool = ..., event: Optional[Any] = ..., with_separate_src: bool = ...): ... + def repoDone(self, repo_id: Any, data: Any, expire: bool = ...) -> None: ... + def distRepoMove(self, repo_id: Any, uploadpath: Any, arch: Any) -> None: ... + def isEnabled(self): ... + +def get_upload_path(reldir: Any, name: Any, create: bool = ..., volume: Optional[Any] = ...): ... +def get_verify_class(verify: Any): ... +def handle_upload(environ: Any): ... diff --git a/kojihub/kojixmlrpc.pyi b/kojihub/kojixmlrpc.pyi new file mode 100644 index 0000000..8a6e5b0 --- /dev/null +++ b/kojihub/kojixmlrpc.pyi @@ -0,0 +1,59 @@ +import logging +from koji.xmlrpcplus import ExtendedMarshaller +from typing import Any, Optional + +class Marshaller(ExtendedMarshaller): + dispatch: Any = ... + def dump_datetime(self, value: Any, write: Any) -> None: ... + +class HandlerRegistry: + funcs: Any = ... + argspec_cache: Any = ... + def __init__(self) -> None: ... + def register_function(self, function: Any, name: Optional[Any] = ...) -> None: ... + def register_module(self, instance: Any, prefix: Optional[Any] = ...) -> None: ... + def register_instance(self, instance: Any) -> None: ... + def register_plugin(self, plugin: Any) -> None: ... + def getargspec(self, func: Any): ... + def list_api(self): ... + def system_listMethods(self): ... + def system_methodSignature(self, method: Any): ... + def system_methodHelp(self, method: Any): ... + def get(self, name: Any): ... + +class HandlerAccess: + def __init__(self, registry: Any) -> None: ... + def call(self, __name: Any, *args: Any, **kwargs: Any): ... + def get(self, name: Any): ... + +class ModXMLRPCRequestHandler: + traceback: bool = ... + handlers: Any = ... + logger: Any = ... + def __init__(self, handlers: Any) -> None: ... + def handle_upload(self, environ: Any): ... + def handle_rpc(self, environ: Any): ... + def check_session(self) -> None: ... + def enforce_lockout(self) -> None: ... + def multiCall(self, calls: Any): ... + def handle_request(self, req: Any) -> None: ... + +def offline_reply(start_response: Any, msg: Optional[Any] = ...): ... +def load_config(environ: Any): ... +def load_plugins(opts: Any): ... +def get_policy(opts: Any, plugins: Any): ... + +class HubFormatter(logging.Formatter): + def format(self, record: Any): ... + +def setup_logging1() -> None: ... +def setup_logging2(opts: Any) -> None: ... +def load_scripts(environ: Any) -> None: ... +def get_memory_usage(): ... +def server_setup(environ: Any) -> None: ... + +firstcall: bool +firstcall_lock: Any + +def application(environ: Any, start_response: Any): ... +def get_registry(opts: Any, plugins: Any): ... diff --git a/kojihub/scheduler.pyi b/kojihub/scheduler.pyi new file mode 100644 index 0000000..42163a7 --- /dev/null +++ b/kojihub/scheduler.pyi @@ -0,0 +1,133 @@ +from _typeshed import Incomplete +from typing import Callable, Iterable, Optional, TypeAlias, TypedDict + +from . import kojihub as kojihub +from .db import ( + DeleteProcessor, + InsertProcessor, + QueryProcessor, + QueryView, + UpdateProcessor, + UpsertProcessor, + db_lock, +) + +logger: Incomplete + +_Tables: TypeAlias = list[str] +_Clauses: TypeAlias = Iterable[str] +_JoinMap: TypeAlias = dict[str, str] +_FieldMap: TypeAlias = dict[str, list[str|None]] +_DefaultFields: TypeAlias = tuple[str] +_Fields: TypeAlias = Iterable[str] +_TaskRun: TypeAlias = dict + +class _HostInfo(TypedDict): + id: int + user_id: int + name: str + update_ts: float + ready: bool + task_load: float + arches: str + capacity: float + description: str + comment: str + enabled: bool + +def log_db(msg, task_id: Optional[int] = None, host_id: Optional[int] = None) -> None: + ... + +def log_both(msg, task_id: Optional[int] = None, host_id: Optional[int] = None, level=...) -> None: + ... + +class LogMessagesQuery(QueryView): + tables: _Tables + joinmap: _JoinMap + fieldmap: _FieldMap + default_fields: _DefaultFields + +def get_log_messages( + clauses: Optional[_Clauses] = None, + fields: Optional[Iterable[str]] = None): + ... + +def get_tasks_for_host(hostID: Optional[int], retry: bool = True): + ... + +def set_refusal( + hostID: int, + taskID: int, + soft: bool = True, + by_host: bool = False, + msg: str = '') -> None: + ... + +class TaskRefusalsQuery(QueryView): + tables: _Tables + joinmap: _JoinMap + fieldmap: _FieldMap + default_fields: _DefaultFields + +def get_task_refusals( + clauses: Optional[_Clauses] = None, + fields: Optional[_Fields] = None): + ... + +def get_host_data(hostID: Optional[int] = None): ... +def set_host_data(hostID: Optional[int], data: dict) -> None: ... + +class TaskRunsQuery(QueryView): + tables: _Tables + joinmap: _JoinMap + fieldmap: _FieldMap + default_fields: _DefaultFields + +def get_task_runs( + clauses: Optional[_Clauses] = None, + fields: Optional[_Fields] = None): + ... + +class TaskScheduler: + hosts_by_bin: dict[str, list[_HostInfo]] + hosts: dict[int, _HostInfo] + active_tasks: list[dict] + free_tasks: Iterable[dict] + maxjobs: int + capacity_overcommit: int + ready_timeout: int + assign_timeout: int + soft_refusal_timeout: int + host_timeout: int + run_interval: int + def __init__(self) -> None: ... + def run(self, force: bool = False) -> bool: ... + def check_ts(self) -> bool: ... + def do_schedule(self) -> None: ... + def check_active_tasks(self) -> None: ... + def check_hosts(self) -> None: ... + def get_active_runs(self) -> dict[int, list[_TaskRun]]: ... + def get_tasks(self) -> None: ... + def get_refusals(self) -> dict[int, dict]: ... + def get_hosts(self) -> None: ... + def assign( + self, + task = dict[str, int], # just task_id for now + host = _HostInfo, + force: bool = False, + override: bool = False): + ... + +def do_assign( + task_id: int, + host: int, + force: bool = False, + override: bool = False): + ... + +class SchedulerExports: + getTaskRuns: Callable + getTaskRefusals: Callable + getHostData: Callable + getLogMessages: Callable + def doRun(self, force: bool = False) -> bool: ...