Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package osc for openSUSE:Factory checked in at 2026-08-04 21:34:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/osc (Old) and /work/SRC/openSUSE:Factory/.osc.new.16738 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "osc" Tue Aug 4 21:34:30 2026 rev:228 rq:1369301 version:1.27.3 Changes: -------- --- /work/SRC/openSUSE:Factory/osc/osc.changes 2026-07-01 17:12:31.303474578 +0200 +++ /work/SRC/openSUSE:Factory/.osc.new.16738/osc.changes 2026-08-04 21:37:22.694347402 +0200 @@ -1,0 +2,12 @@ +Mon Aug 3 14:59:29 UTC 2026 - Daniel Mach <[email protected]> + +- 1.27.3 + - Command-line: + - Fix 'osc lbl' to work with git based packages + - Library: + - Fix gitea api IssueTimelineEntry parsing by skipping None values + - Fix store.get_store() to work better with check=False + - Fix gitea exception init (MovedPermanently) + - Add a few type hints + +------------------------------------------------------------------- Old: ---- osc-1.27.2.tar.gz New: ---- osc-1.27.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ osc.spec ++++++ --- /var/tmp/diff_new_pack.SdRsR5/_old 2026-08-04 21:37:25.298438825 +0200 +++ /var/tmp/diff_new_pack.SdRsR5/_new 2026-08-04 21:37:25.298438825 +0200 @@ -30,6 +30,10 @@ %define use_python_pkg python36 %endif +%if 0%{?suse_version} && 0%{?suse_version} < 1600 +%define require_typing_extensions 1 +%endif + %define completion_dir_bash %{_datadir}/bash-completion/completions %define completion_dir_csh %{_sysconfdir}/profile.d %define completion_dir_fish %{_datadir}/fish/vendor_completions.d @@ -80,7 +84,7 @@ %endif Name: osc -Version: 1.27.2 +Version: 1.27.3 Release: 0 Summary: Command-line client for the Open Build Service License: GPL-2.0-or-later @@ -119,6 +123,10 @@ Requires: %{use_python_pkg}-cryptography Requires: %{use_python_pkg}-rpm Requires: %{use_python_pkg}-urllib3 +%if 0%{?require_typing_extensions} +Requires: %{use_python_pkg}-typing_extensions +BuildRequires: %{use_python_pkg}-typing_extensions +%endif Requires: %{yaml_pkg} # needed for git-obs completion ++++++ PKGBUILD ++++++ --- /var/tmp/diff_new_pack.SdRsR5/_old 2026-08-04 21:37:25.350440651 +0200 +++ /var/tmp/diff_new_pack.SdRsR5/_new 2026-08-04 21:37:25.358440932 +0200 @@ -1,5 +1,5 @@ pkgname=osc -pkgver=1.27.2 +pkgver=1.27.3 pkgrel=0 pkgdesc="Command-line client for the Open Build Service" arch=('x86_64') ++++++ debian.changelog ++++++ --- /var/tmp/diff_new_pack.SdRsR5/_old 2026-08-04 21:37:25.418443039 +0200 +++ /var/tmp/diff_new_pack.SdRsR5/_new 2026-08-04 21:37:25.426443319 +0200 @@ -1,4 +1,4 @@ -osc (1.27.2-0) unstable; urgency=low +osc (1.27.3-0) unstable; urgency=low * Placeholder ++++++ osc-1.27.2.tar.gz -> osc-1.27.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.27.2/NEWS new/osc-1.27.3/NEWS --- old/osc-1.27.2/NEWS 2026-07-01 13:24:02.000000000 +0200 +++ new/osc-1.27.3/NEWS 2026-08-03 16:54:23.000000000 +0200 @@ -1,3 +1,12 @@ +- 1.27.3 + - Command-line: + - Fix 'osc lbl' to work with git based packages + - Library: + - Fix gitea api IssueTimelineEntry parsing by skipping None values + - Fix store.get_store() to work better with check=False + - Fix gitea exception init (MovedPermanently) + - Add a few type hints + - 1.27.2 - Command-line: - Extend 'osc maintained' to also display maintained branches in git diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.27.2/osc/__init__.py new/osc-1.27.3/osc/__init__.py --- old/osc-1.27.2/osc/__init__.py 2026-07-01 13:24:02.000000000 +0200 +++ new/osc-1.27.3/osc/__init__.py 2026-08-03 16:54:23.000000000 +0200 @@ -13,7 +13,7 @@ from .util import git_version -__version__ = git_version.get_version('1.27.2') +__version__ = git_version.get_version('1.27.3') # vim: sw=4 et diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.27.2/osc/commandline.py new/osc-1.27.3/osc/commandline.py --- old/osc-1.27.2/osc/commandline.py 2026-07-01 13:24:02.000000000 +0200 +++ new/osc-1.27.3/osc/commandline.py 2026-08-03 16:54:23.000000000 +0200 @@ -6842,28 +6842,33 @@ self.do_repositories(None, None, *args) raise exc_class(exc_msg) - def _find_last_repo_arch(self, repo=None, fatal=True): + def _find_last_repo_arch(self, repo=None, arch=None, *, fatal=True, store=None): from .core import ET - from .core import store + from .store import get_store - files = \ - glob.glob(os.path.join(Path.cwd(), store, "_buildinfo-*")) + \ - glob.glob(os.path.join(Path.cwd(), "_buildinfo-*")) - if repo is not None: - files = [f for f in files - if os.path.basename(f).replace('_buildinfo-', '').startswith(repo + '-')] - if not files: + if repo and arch: + # we know both repo and arch, no need to look for any values + return repo, arch + + if not store: + store = get_store(".", check=False) + + br_repo = None + br_arch = None + if store.last_buildroot: + br_repo, br_arch, _ = store.last_buildroot + + if not repo: + repo = br_repo + + if not arch: + arch = br_arch + + if not repo and not arch: if not fatal: return None, None self.print_repos() - cfg = files[0] - # find newest file - for f in files[1:]: - if os.stat(f).st_atime > os.stat(cfg).st_atime: - cfg = f - root = xml_parse(cfg).getroot() - repo = root.get("repository") - arch = root.findtext("arch") + return repo, arch @cmdln.alias('lbl') @@ -6884,32 +6889,36 @@ from . import conf from .core import BUFSIZE from .core import buildlog_strip_time - from .core import is_package_dir - from .core import store_read_package - from .core import store_read_project + from .store import get_store if conf.config['build-type']: # FIXME: raise Exception instead print('Not implemented for VMs', file=sys.stderr) sys.exit(1) - if len(args) == 0 or len(args) == 1: - project = store_read_project('.') - package = store_read_package('.') + store = get_store(".", check=False) + project = store.project + package = store.package + + if len(args) == 0: repo = None - if args: - repo = args[0] - repo, arch = self._find_last_repo_arch(repo) + arch = None + elif len(args) == 1: + repo = args[0] + arch = None elif len(args) == 2: - project = store_read_project('.') - package = store_read_package('.') repo = args[0] arch = args[1] else: - if is_package_dir(Path.cwd()): + if store.is_package: self.print_repos() raise oscerr.WrongArgs('Wrong number of arguments.') + repo, arch = self._find_last_repo_arch(repo=repo, arch=arch, store=store) + + if not repo and not arch: + self.print_repos() + # TODO: refactor/unify buildroot calculation and move it to core.py apihost = urlsplit(self.get_api_url())[1] buildroot = osc_build.calculate_build_root(apihost, project, package, repo, arch) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.27.2/osc/conf.py new/osc-1.27.3/osc/conf.py --- old/osc-1.27.2/osc/conf.py 2026-07-01 13:24:02.000000000 +0200 +++ new/osc-1.27.3/osc/conf.py 2026-08-03 16:54:23.000000000 +0200 @@ -60,6 +60,7 @@ import textwrap from io import BytesIO from io import StringIO +from typing import Optional, Tuple from urllib.parse import urlsplit from . import credentials @@ -1569,7 +1570,10 @@ return urljoin(*parse_apisrv_url(None, apiurl)) -def parse_apisrv_url(scheme, apisrv): +def parse_apisrv_url(scheme: Optional[str], apisrv: str) -> Tuple[str, str, str]: + """ + Parses the api server url ``apisrv`` and returns the tuple (scheme, url, path). + """ if apisrv.startswith('http://') or apisrv.startswith('https://'): url = apisrv elif scheme is not None: @@ -1580,17 +1584,17 @@ return scheme, url, path.rstrip('/') -def urljoin(scheme, apisrv, path=''): - return f"{scheme}://{apisrv}" + path +def urljoin(scheme: str, apisrv: str, path: str='') -> str: + return f"{scheme}://{apisrv}{path}" -def is_known_apiurl(url): +def is_known_apiurl(url: str) -> bool: """returns ``True`` if url is a known apiurl""" apiurl = sanitize_apiurl(url) return apiurl in config['api_host_options'] -def extract_known_apiurl(url): +def extract_known_apiurl(url: str) -> Optional[str]: """ Return longest prefix of given url that is known apiurl, None if there is no known apiurl that is prefix of given url. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.27.2/osc/core.py new/osc-1.27.3/osc/core.py --- old/osc-1.27.2/osc/core.py 2026-07-01 13:24:02.000000000 +0200 +++ new/osc-1.27.3/osc/core.py 2026-08-03 16:54:23.000000000 +0200 @@ -28,12 +28,17 @@ from http.client import IncompleteRead from io import StringIO from pathlib import Path -from typing import Optional, Dict, Union, List, Iterable +from typing import TYPE_CHECKING, Optional, Dict, Union, List, Iterable, Tuple, overload from urllib.parse import parse_qs, urlsplit, urlunsplit, urlparse, urlunparse, quote, urlencode, unquote from urllib.error import HTTPError from xml.etree import ElementTree as ET try: + from typing import Literal +except ImportError: + from typing_extensions import Literal + +try: import distro except ImportError: distro = None @@ -1337,7 +1342,7 @@ raise -def show_package_meta(apiurl: str, prj: str, pac: str, meta=False, blame=None): +def show_package_meta(apiurl: str, prj: str, pac: str, meta: bool=False, blame=None) -> List[bytes]: query: Dict[str, Union[str, int]] = {} if meta: query['meta'] = 1 @@ -1396,7 +1401,7 @@ return project_obj.scmsync -def show_devel_project(apiurl, prj, pac): +def show_devel_project(apiurl: str, prj: str, pac: str) -> Tuple[Optional[str], Optional[str]]: from . import obs_api package_obj = obs_api.Package.from_api(apiurl, prj, pac) @@ -1523,7 +1528,7 @@ def __call__(self, **kwargs): return self._delegate(**kwargs) - def __init__(self, url, input, change_is_required=False, file_ext='.xml', method=None): + def __init__(self, url, input: Union[List[str], str, bytes, List[bytes]], change_is_required=False, file_ext='.xml', method=None): if isinstance(url, self._URLFactory): self._url_factory = url else: @@ -1610,8 +1615,20 @@ os.unlink(self.filename) +if TYPE_CHECKING: + from typing import TypedDict + + MetaType = Literal['prj', 'pkg', 'attribute', 'prjconf', 'user', 'group', 'pattern'] + + class _MetaType(TypedDict): + path: str + template: str + file_ext: str + + # different types of metadata -metatypes = {'prj': {'path': 'source/%s/_meta', +metatypes: "Dict[MetaType, _MetaType]" = { + 'prj': {'path': 'source/%s/_meta', 'template': new_project_templ, 'file_ext': '.xml' }, @@ -1642,7 +1659,7 @@ } -def meta_exists(metatype: str, path_args=None, template_args=None, create_new=True, apiurl=None): +def meta_exists(metatype: "MetaType", path_args=None, template_args=None, create_new=True, apiurl=None): global metatypes @@ -1663,7 +1680,7 @@ def make_meta_url( - metatype: str, + metatype: "MetaType", path_args=None, apiurl: Optional[str] = None, force=False, @@ -1706,7 +1723,7 @@ def edit_meta( - metatype, + metatype: "MetaType", path_args=None, data: Optional[List[str]] = None, template_args=None, @@ -3694,6 +3711,7 @@ return r +@overload def branch_pkg( apiurl: str, src_project: str, @@ -3715,7 +3733,54 @@ maintenance=False, newinstance=False, disable_build=False, -): +) -> Tuple[Literal[False], Optional[str], Optional[str], Optional[str], Optional[str]]: ... + +@overload +def branch_pkg( + apiurl: str, + src_project: str, + src_package: str, + nodevelproject=False, + rev=None, + linkrev=None, + target_project: Optional[str] = None, + target_package=None, + return_existing=True, + msg="", + force=False, + noaccess=False, + add_repositories=False, + add_repositories_block=None, + add_repositories_rebuild=None, + extend_package_names=False, + missingok=False, + maintenance=False, + newinstance=False, + disable_build=False, +) -> Union[Tuple[Literal[True], str, str, None, None], Tuple[Literal[False], Optional[str], Optional[str], Optional[str], Optional[str]]]: ... + +def branch_pkg( + apiurl: str, + src_project: str, + src_package: str, + nodevelproject=False, + rev=None, + linkrev=None, + target_project: Optional[str] = None, + target_package=None, + return_existing=False, + msg="", + force=False, + noaccess=False, + add_repositories=False, + add_repositories_block=None, + add_repositories_rebuild=None, + extend_package_names=False, + missingok=False, + maintenance=False, + newinstance=False, + disable_build=False, +) -> Union[Tuple[Literal[True], str, str, None, None], Tuple[Literal[False], Optional[str], Optional[str], Optional[str], Optional[str]]]: """ Branch a package (via API call) """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.27.2/osc/gitea_api/exceptions.py new/osc-1.27.3/osc/gitea_api/exceptions.py --- old/osc-1.27.2/osc/gitea_api/exceptions.py 2026-07-01 13:24:02.000000000 +0200 +++ new/osc-1.27.3/osc/gitea_api/exceptions.py 2026-08-03 16:54:23.000000000 +0200 @@ -87,7 +87,7 @@ re.compile(r"(?P<message>.*)"), ] - def __init__(self, response: GiteaHTTPResponse, message: str): + def __init__(self, response: GiteaHTTPResponse, message: str, **_kwargs): super().__init__(response) self.message = message diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.27.2/osc/gitea_api/issue_timeline_entry.py new/osc-1.27.3/osc/gitea_api/issue_timeline_entry.py --- old/osc-1.27.2/osc/gitea_api/issue_timeline_entry.py 2026-07-01 13:24:02.000000000 +0200 +++ new/osc-1.27.3/osc/gitea_api/issue_timeline_entry.py 2026-08-03 16:54:23.000000000 +0200 @@ -273,5 +273,11 @@ url = conn.makeurl("repos", owner, repo, "issues", str(number), "timeline", query=q) obj_list = [] for response in conn.request_all_pages("GET", url): - obj_list.extend([cls(i, response=response, conn=conn) for i in response.json() or []]) + obj_list.extend([ + cls(i, response=response, conn=conn) + for i in response.json() or [] + # Gitea may return `null` entries in issue/PR timeline responses. + # Only dict items are valid IssueTimelineEntry payloads. + if isinstance(i, dict) + ]) return obj_list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.27.2/osc/gitea_api/pr_review.py new/osc-1.27.3/osc/gitea_api/pr_review.py --- old/osc-1.27.2/osc/gitea_api/pr_review.py 2026-07-01 13:24:02.000000000 +0200 +++ new/osc-1.27.3/osc/gitea_api/pr_review.py 2026-08-03 16:54:23.000000000 +0200 @@ -105,7 +105,7 @@ :param number: Number of the pull request in owner/repo. :param review_id: ID of the review. """ - url = conn.makeurl("repos", owner, repo, "pulls", str(number), "reviews", review_id) + url = conn.makeurl("repos", owner, repo, "pulls", str(number), "reviews", str(review_id)) response = conn.request("GET", url, context={"owner": owner, "repo": repo, "number": number}) obj = cls(response.json(), response=response, conn=conn) return obj diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.27.2/osc/store.py new/osc-1.27.3/osc/store.py --- old/osc-1.27.2/osc/store.py 2026-07-01 13:24:02.000000000 +0200 +++ new/osc-1.27.3/osc/store.py 2026-08-03 16:54:23.000000000 +0200 @@ -23,24 +23,27 @@ # if there are '.osc' and '.git' directories next to each other, '.osc' takes preference store = None - try: - store = Store(path, check) - except oscerr.NoWorkingCopy: - pass + if os.path.exists(os.path.join(path, Store.STORE_DIR)): + try: + store = Store(path, check=check) + except oscerr.NoWorkingCopy: + pass if not store: try: - store = git_scm.GitStore(path, check) + store = git_scm.GitStore(path, check=check) if print_warnings: git_scm.warn_experimental() except oscerr.NoWorkingCopy: - if not os.path.exists(os.path.join(path, ".osc")): - raise pass if not store: - msg = f"Directory '{path}' is not a working copy" - raise oscerr.NoWorkingCopy(msg) + if check: + msg = f"Directory '{path}' is not a working copy" + raise oscerr.NoWorkingCopy(msg) + else: + # return an empty Store for compatibility even if there's no '.osc' available + store = Store(path, check=False) return store diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.27.2/osc/util/git_version.py new/osc-1.27.3/osc/util/git_version.py --- old/osc-1.27.2/osc/util/git_version.py 2026-07-01 13:24:02.000000000 +0200 +++ new/osc-1.27.3/osc/util/git_version.py 2026-08-03 16:54:23.000000000 +0200 @@ -9,7 +9,7 @@ """ # the `version` variable contents get substituted during `git archive` # it requires adding this to .gitattributes: <path to this file> export-subst - version = "1.27.2" + version = "1.27.3" if version.startswith(("$", "%")): # "$": version hasn't been substituted during `git archive` # "%": "Format:" and "$" characters get removed from the version string (a GitHub bug?) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.27.2/setup.cfg new/osc-1.27.3/setup.cfg --- old/osc-1.27.2/setup.cfg 2026-07-01 13:24:02.000000000 +0200 +++ new/osc-1.27.3/setup.cfg 2026-08-03 16:54:23.000000000 +0200 @@ -52,6 +52,7 @@ rpm ruamel.yaml urllib3 + typing_extensions; python_version < "3.8" [options.extras_require] lint = diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.27.2/tests/test_gitea_exceptions.py new/osc-1.27.3/tests/test_gitea_exceptions.py --- old/osc-1.27.2/tests/test_gitea_exceptions.py 1970-01-01 01:00:00.000000000 +0100 +++ new/osc-1.27.3/tests/test_gitea_exceptions.py 2026-08-03 16:54:23.000000000 +0200 @@ -0,0 +1,213 @@ +import contextlib +import unittest +from unittest.mock import patch + +from urllib3 import HTTPResponse + +from osc.gitea_api import ( + Branch, + Fork, + Issue, + Login, + PullRequest, + PullRequestReview, + Repo, + SSHKey, + User, +) +from osc.gitea_api.connection import Connection +from osc.gitea_api.exceptions import MovedPermanently + +# Sample response for GET pullrequest: +# it doesn't really make sense for the other entities, but are mostly interested +# in the context passed to Exception's __init__ anyway, so the response +# itself is only important for its status code. +RESPONSE_301 = HTTPResponse( + status=301, + body=b'<a href="/api/v1/repos/new-owner/repo/pulls/1">Moved Permanently</a>.\n\n', + headers={ + "content-type": "text/html; charset=utf-8", + "location": "/api/v1/repos/new-owner/repo/pulls/1", + }, +) + + [email protected] +def patch_connection(connection: Connection, response: HTTPResponse): + with patch.object(connection.conn, "getresponse", new=lambda: response): + with patch.object(connection.conn, "request"): + yield + + +class TestGiteaResponseToException(unittest.TestCase): + """Test that a 301 response properly raises MovedPermanently across all API entities""" + + def setUp(self): + self.connection = Connection( + login=Login(name="mock", user="mock", url="https://mock.src.suse.de") + ) + + # --- PullRequest --- + + def test_pull_request_get_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + PullRequest.get( + repo="test", number=1, owner="ADMIN", conn=self.connection + ) + + def test_pull_request_list_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + PullRequest.list(owner="ADMIN", repo="test", conn=self.connection) + + def test_pull_request_close_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + PullRequest.close( + owner="ADMIN", repo="test", number=1, conn=self.connection + ) + + def test_pull_request_reopen_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + PullRequest.reopen( + owner="ADMIN", repo="test", number=1, conn=self.connection + ) + + def test_pull_request_add_comment_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + PullRequest.add_comment( + owner="ADMIN", + repo="test", + number=1, + msg="hello", + conn=self.connection, + ) + + def test_pull_request_get_patch_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + PullRequest.get_patch( + owner="ADMIN", repo="test", number=1, conn=self.connection + ) + + # --- PullRequestReview --- + + def test_pull_request_review_get_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + PullRequestReview.get( + owner="ADMIN", + repo="test", + number=1, + review_id=1, + conn=self.connection, + ) + + def test_pull_request_review_list_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + PullRequestReview.list( + owner="ADMIN", repo="test", number=1, conn=self.connection + ) + + # --- Repo --- + + def test_repo_get_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + Repo.get(owner="ADMIN", repo="test", conn=self.connection) + + def test_repo_list_org_repos_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + Repo.list_org_repos(owner="ADMIN", conn=self.connection) + + def test_repo_list_my_repos_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + Repo.list_my_repos(conn=self.connection) + + # --- Branch --- + + def test_branch_get_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + Branch.get( + owner="ADMIN", repo="test", branch="main", conn=self.connection + ) + + def test_branch_list_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + Branch.list(owner="ADMIN", repo="test", conn=self.connection) + + def test_branch_create_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + Branch.create( + owner="ADMIN", + repo="test", + new_branch_name="new-branch", + conn=self.connection, + ) + + # --- Fork --- + + def test_fork_list_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + Fork.list(owner="ADMIN", repo="test", conn=self.connection) + + def test_fork_create_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + Fork.create(owner="ADMIN", repo="test", conn=self.connection) + + # --- User --- + + def test_user_get_current_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + User.get(conn=self.connection) + + def test_user_get_by_name_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + User.get(username="ADMIN", conn=self.connection) + + # --- SSHKey --- + + def test_ssh_key_get_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + SSHKey.get(id=1, conn=self.connection) + + def test_ssh_key_list_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + SSHKey.list(conn=self.connection) + + def test_ssh_key_delete_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + SSHKey.delete(id=1, conn=self.connection) + + # --- Issue --- + + def test_issue_create_301(self): + with patch_connection(self.connection, response=RESPONSE_301): + with self.assertRaises(MovedPermanently): + Issue.create( + owner="ADMIN", + repo="test", + title="test issue", + body="test body", + conn=self.connection, + ) + + +if __name__ == "__main__": + unittest.main() ++++++ osc.dsc ++++++ --- /var/tmp/diff_new_pack.SdRsR5/_old 2026-08-04 21:37:26.794491348 +0200 +++ /var/tmp/diff_new_pack.SdRsR5/_new 2026-08-04 21:37:26.806491769 +0200 @@ -1,6 +1,6 @@ Format: 1.0 Source: osc -Version: 1.27.2-0 +Version: 1.27.3-0 Binary: osc Maintainer: Adrian Schroeter <[email protected]> Architecture: any
