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

Reply via email to