Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-osc-tiny for openSUSE:Factory checked in at 2021-11-03 17:26:21 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-osc-tiny (Old) and /work/SRC/openSUSE:Factory/.python-osc-tiny.new.1890 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-osc-tiny" Wed Nov 3 17:26:21 2021 rev:10 rq:928959 version:0.4.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-osc-tiny/python-osc-tiny.changes 2021-03-02 12:46:10.284392588 +0100 +++ /work/SRC/openSUSE:Factory/.python-osc-tiny.new.1890/python-osc-tiny.changes 2021-11-03 17:27:17.481370874 +0100 @@ -1,0 +2,11 @@ +Wed Sep 22 10:45:07 UTC 2021 - Andreas Hasenkopf <ahasenk...@suse.com> + +- Release 0.4.1 + * Bugfix for configuration utilities + +- Release 0.4.0 + * Added support to parse `osc` configuration + * Bugfix for `origin` extension + + +------------------------------------------------------------------- Old: ---- osc-tiny-0.3.3.tar.gz New: ---- osc-tiny-0.4.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-osc-tiny.spec ++++++ --- /var/tmp/diff_new_pack.ZIVeAq/_old 2021-11-03 17:27:17.921371114 +0100 +++ /var/tmp/diff_new_pack.ZIVeAq/_new 2021-11-03 17:27:17.925371116 +0100 @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python2 1 Name: python-osc-tiny -Version: 0.3.3 +Version: 0.4.1 Release: 0 Summary: Client API for openSUSE BuildService License: MIT ++++++ osc-tiny-0.3.3.tar.gz -> osc-tiny-0.4.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-tiny-0.3.3/PKG-INFO new/osc-tiny-0.4.1/PKG-INFO --- old/osc-tiny-0.3.3/PKG-INFO 2021-02-24 11:35:58.000000000 +0100 +++ new/osc-tiny-0.4.1/PKG-INFO 2021-09-22 11:55:15.028164000 +0200 @@ -1,58 +1,12 @@ Metadata-Version: 2.1 Name: osc-tiny -Version: 0.3.3 +Version: 0.4.1 Summary: Client API for openSUSE BuildService Home-page: http://github.com/crazyscientist/osc-tiny Author: Andreas Hasenkopf Author-email: ahasenk...@suse.com License: MIT Download-URL: http://github.com/crazyscientist/osc-tiny/tarball/master -Description: OSC Tiny - ======== - - [](https://travis-ci.com/crazyscientist/osc-tiny) - [](https://coveralls.io/github/crazyscientist/osc-tiny) - [](https://badge.fury.io/py/osc-tiny) - - This project aims to provide a minimalistic and transparent client for accessing - the [OpenBuildService](https://openbuildservice.org/) - [API](https://build.opensuse.org/apidocs/index). - - Usage - ----- - - This is a very basic example: - - ```python - from osctiny import Osc - - osc = Osc( - url="https://api.opensuse.org", - username="foobar", - password="helloworld", - ) - - # This returns an LXML object - osc.requests.get(request_id=1) - - # This returns an LXML object - osc.search.request(xpath="state/@name='new'") - ``` - - For more documentation see https://osc-tiny.readthedocs.io/en/latest/ - - Contributing - ------------ - - Any contributions are welcome. - - Links - ----- - - * https://osc-tiny.readthedocs.io/en/latest/ - * https://openbuildservice.org/ - * https://build.opensuse.org/apidocs/index - Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers @@ -64,3 +18,52 @@ Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Description-Content-Type: text/markdown +License-File: LICENSE + +OSC Tiny +======== + +[](https://travis-ci.com/crazyscientist/osc-tiny) +[](https://coveralls.io/github/crazyscientist/osc-tiny) +[](https://badge.fury.io/py/osc-tiny) + +This project aims to provide a minimalistic and transparent client for accessing +the [OpenBuildService](https://openbuildservice.org/) +[API](https://build.opensuse.org/apidocs/index). + +Usage +----- + +This is a very basic example: + +```python +from osctiny import Osc + +osc = Osc( + url="https://api.opensuse.org", + username="foobar", + password="helloworld", +) + +# This returns an LXML object +osc.requests.get(request_id=1) + +# This returns an LXML object +osc.search.request(xpath="state/@name='new'") +``` + +For more documentation see https://osc-tiny.readthedocs.io/en/latest/ + +Contributing +------------ + +Any contributions are welcome. + +Links +----- + +* https://osc-tiny.readthedocs.io/en/latest/ +* https://openbuildservice.org/ +* https://build.opensuse.org/apidocs/index + + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-tiny-0.3.3/osc_tiny.egg-info/PKG-INFO new/osc-tiny-0.4.1/osc_tiny.egg-info/PKG-INFO --- old/osc-tiny-0.3.3/osc_tiny.egg-info/PKG-INFO 2021-02-24 11:35:58.000000000 +0100 +++ new/osc-tiny-0.4.1/osc_tiny.egg-info/PKG-INFO 2021-09-22 11:55:15.000000000 +0200 @@ -1,58 +1,12 @@ Metadata-Version: 2.1 Name: osc-tiny -Version: 0.3.3 +Version: 0.4.1 Summary: Client API for openSUSE BuildService Home-page: http://github.com/crazyscientist/osc-tiny Author: Andreas Hasenkopf Author-email: ahasenk...@suse.com License: MIT Download-URL: http://github.com/crazyscientist/osc-tiny/tarball/master -Description: OSC Tiny - ======== - - [](https://travis-ci.com/crazyscientist/osc-tiny) - [](https://coveralls.io/github/crazyscientist/osc-tiny) - [](https://badge.fury.io/py/osc-tiny) - - This project aims to provide a minimalistic and transparent client for accessing - the [OpenBuildService](https://openbuildservice.org/) - [API](https://build.opensuse.org/apidocs/index). - - Usage - ----- - - This is a very basic example: - - ```python - from osctiny import Osc - - osc = Osc( - url="https://api.opensuse.org", - username="foobar", - password="helloworld", - ) - - # This returns an LXML object - osc.requests.get(request_id=1) - - # This returns an LXML object - osc.search.request(xpath="state/@name='new'") - ``` - - For more documentation see https://osc-tiny.readthedocs.io/en/latest/ - - Contributing - ------------ - - Any contributions are welcome. - - Links - ----- - - * https://osc-tiny.readthedocs.io/en/latest/ - * https://openbuildservice.org/ - * https://build.opensuse.org/apidocs/index - Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers @@ -64,3 +18,52 @@ Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Description-Content-Type: text/markdown +License-File: LICENSE + +OSC Tiny +======== + +[](https://travis-ci.com/crazyscientist/osc-tiny) +[](https://coveralls.io/github/crazyscientist/osc-tiny) +[](https://badge.fury.io/py/osc-tiny) + +This project aims to provide a minimalistic and transparent client for accessing +the [OpenBuildService](https://openbuildservice.org/) +[API](https://build.opensuse.org/apidocs/index). + +Usage +----- + +This is a very basic example: + +```python +from osctiny import Osc + +osc = Osc( + url="https://api.opensuse.org", + username="foobar", + password="helloworld", +) + +# This returns an LXML object +osc.requests.get(request_id=1) + +# This returns an LXML object +osc.search.request(xpath="state/@name='new'") +``` + +For more documentation see https://osc-tiny.readthedocs.io/en/latest/ + +Contributing +------------ + +Any contributions are welcome. + +Links +----- + +* https://osc-tiny.readthedocs.io/en/latest/ +* https://openbuildservice.org/ +* https://build.opensuse.org/apidocs/index + + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-tiny-0.3.3/osc_tiny.egg-info/SOURCES.txt new/osc-tiny-0.4.1/osc_tiny.egg-info/SOURCES.txt --- old/osc-tiny-0.3.3/osc_tiny.egg-info/SOURCES.txt 2021-02-24 11:35:58.000000000 +0100 +++ new/osc-tiny-0.4.1/osc_tiny.egg-info/SOURCES.txt 2021-09-22 11:55:15.000000000 +0200 @@ -37,9 +37,12 @@ osctiny/tests/test_requests.py osctiny/tests/test_search.py osctiny/tests/test_utils.py +osctiny/tests/osc/__init__.py +osctiny/tests/osc/conf.py osctiny/utils/__init__.py osctiny/utils/backports.py osctiny/utils/base.py osctiny/utils/changelog.py +osctiny/utils/conf.py osctiny/utils/errors.py osctiny/utils/mapping.py \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-tiny-0.3.3/osctiny/__init__.py new/osc-tiny-0.4.1/osctiny/__init__.py --- old/osc-tiny-0.3.3/osctiny/__init__.py 2021-02-24 11:35:35.000000000 +0100 +++ new/osc-tiny-0.4.1/osctiny/__init__.py 2021-09-22 11:55:07.000000000 +0200 @@ -6,4 +6,4 @@ __all__ = ['Osc', 'bs_requests', 'buildresults', 'comments', 'packages', 'projects', 'search', 'users'] -__version__ = "0.3.3" +__version__ = "0.4.1" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-tiny-0.3.3/osctiny/extensions/origin.py new/osc-tiny-0.4.1/osctiny/extensions/origin.py --- old/osc-tiny-0.3.3/osctiny/extensions/origin.py 2021-02-24 11:35:35.000000000 +0100 +++ new/osc-tiny-0.4.1/osctiny/extensions/origin.py 2021-09-22 11:55:07.000000000 +0200 @@ -25,7 +25,6 @@ import re from warnings import warn -from lxml.objectify import ObjectifiedElement from yaml import load from ..utils.backports import lru_cache @@ -280,10 +279,15 @@ This project is important, because it's meta can provide the list of maintained projects. - :return: Objectified XML element or ``None`` - :rtype: lxml.objectify.ObjectifiedElement + :return: Project name or ``None`` + :rtype: str or None + + .. versionchanged:: 0.4.0 + + Return string instead of XML object """ - response = self.osc.search.project(xpath="attribute/@name='OBS:MaintenanceProject'") + response = self.osc.search.search(path="project/id", + xpath="attribute/@name='OBS:MaintenanceProject'") projects = getattr(response, "project", []) if len(projects) < 1: warn("The build service defines no maintenance projects!") @@ -291,25 +295,26 @@ if len(projects) > 1: warn("The build service defines multiple maintenance projects!") - return projects[0] + return projects[0].get("name") @cached_property - def maintained_projects(self, from_project=None): + def maintained_projects(self): """ Get the list of maintained projects - By default this property uses :py:meth:`maintenance_project` and allows usage of a specified - ``from_project`` instead. + Maintained projects are identified by the presence of the ``OBS:Maintained`` attribute. + + :return: Project names + :rtype: List of str - :param from_project: The maintenance project to query - :return: Objectified XML element - :rtype: lxml.objectify.ObjectifiedElement - """ - from_project = from_project or self.maintenance_project - if not isinstance(from_project, ObjectifiedElement): - from_project = self.osc.projects.get_meta(project=from_project) + .. versionchanged:: 0.4.0 - return [m.get("project") for m in from_project.xpath("maintenance/maintains")] + Search maintained projects via the ``OBS:Maintained`` attribute and not via the + maintenance project. + """ + response = self.osc.search.search(path="project/id", + xpath="attribute/@name='OBS:Maintained'") + return [project.get("name") for project in getattr(response, "project", [])] @lru_cache(maxsize=16) def get_project_origin_config(self, project): @@ -529,6 +534,10 @@ :return: Generator of pairs: ('pkg', 'origin') :rtype: generator """ + if project not in self.expanded_origins: + warn("Project {} has no origin definition".format(project)) + return + packages = self.osc.projects.get_files(project, expand='1') for package in getattr(packages, "entry", []): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-tiny-0.3.3/osctiny/osc.py new/osc-tiny-0.4.1/osctiny/osc.py --- old/osc-tiny-0.3.3/osctiny/osc.py 2021-02-24 11:35:35.000000000 +0100 +++ new/osc-tiny-0.4.1/osctiny/osc.py 2021-09-22 11:55:07.000000000 +0200 @@ -26,6 +26,8 @@ from .extensions.bs_requests import Request as BsRequest from .extensions.search import Search from .extensions.users import Group, Person +from .utils.conf import get_credentials +from .utils.errors import OscError try: from cachecontrol import CacheControl @@ -78,6 +80,7 @@ :param password: Password for login :param verify: See `SSL Cert Verification`_ for more details :param cache: Store API responses in a cache + :raises osctiny.errors.OscError: if no credentials are provided .. versionadded:: 0.1.1 The ``cache`` parameter and the ``build`` extension @@ -94,6 +97,9 @@ .. versionadded:: 0.3.0 The ``origins`` extension + .. versionchanged:: 0.4.0 + Raises an exception when no credentials are provided + .. _SSL Cert Verification: http://docs.python-requests.org/en/master/user/advanced/ #ssl-cert-verification @@ -113,6 +119,13 @@ self.url = url or self.url self.username = username or self.username self.password = password or self.password + + if not self.username and not self.password: + try: + self.username, self.password = get_credentials(self.url) + except (ValueError, NotImplementedError, FileNotFoundError) as error: + raise OscError from error + self._session = Session() self._session.verify = verify or get_default_verify_paths().capath self.auth = HTTPBasicAuth(self.username, self.password) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-tiny-0.3.3/osctiny/tests/osc/__init__.py new/osc-tiny-0.4.1/osctiny/tests/osc/__init__.py --- old/osc-tiny-0.3.3/osctiny/tests/osc/__init__.py 1970-01-01 01:00:00.000000000 +0100 +++ new/osc-tiny-0.4.1/osctiny/tests/osc/__init__.py 2021-09-22 11:55:07.000000000 +0200 @@ -0,0 +1,5 @@ +""" +Mocking of the `osc` package + +Without the presence of a dummy module like this one, mocking on Python 3.6 fails. +""" \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-tiny-0.3.3/osctiny/tests/test_origin.py new/osc-tiny-0.4.1/osctiny/tests/test_origin.py --- old/osc-tiny-0.3.3/osctiny/tests/test_origin.py 2021-02-24 11:35:35.000000000 +0100 +++ new/osc-tiny-0.4.1/osctiny/tests/test_origin.py 2021-09-22 11:55:07.000000000 +0200 @@ -85,30 +85,29 @@ status = 200 body = """ <collection matches="1"> - <project name="openSUSE:Maintenance" kind="maintenance"> - <title>The openSUSE Maintenance project</title> - <description/> - <group groupid="maintenance-opensuse.org" role="maintainer"/> - <maintenance> - <maintains project="openSUSE:Leap:15.1:Update"/> - <maintains project="openSUSE:Leap:15.2:Update"/> - </maintenance> - </project> - </collection> + <project name="openSUSE:Maintenance"/> + </collection> + """ + elif "OBS:Maintained" in "".join(params.get("match", [])): + status = 200 + body = """ + <collection matches="2"> + <project name="openSUSE:Leap:15.1:Update"/> + <project name="openSUSE:Leap:15.2:Update"/> + </collection> """ return status, headers, body self.mock_request( method=responses.GET, - url=re.compile(self.osc.url + "/search/project/?"), + url=re.compile(self.osc.url + "/search/project/id"), callback=CallbackFactory(callback) ) with self.subTest("Maintenance Project"): maint_project = self.osc.origins.maintenance_project - self.assertEqual(maint_project.get("name"), "openSUSE:Maintenance") - self.assertEqual(maint_project.get("kind"), "maintenance") + self.assertEqual(maint_project, "openSUSE:Maintenance") with self.subTest("Maintained Projects"): self.assertEqual(self.osc.origins.maintained_projects, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-tiny-0.3.3/osctiny/tests/test_utils.py new/osc-tiny-0.4.1/osctiny/tests/test_utils.py --- old/osc-tiny-0.3.3/osctiny/tests/test_utils.py 2021-02-24 11:35:35.000000000 +0100 +++ new/osc-tiny-0.4.1/osctiny/tests/test_utils.py 2021-09-22 11:55:07.000000000 +0200 @@ -1,8 +1,12 @@ # -*- coding: utf-8 -*- +from base64 import b64encode +from bz2 import compress from unittest import TestCase, mock from datetime import datetime from io import StringIO -from os import remove +import os +from pathlib import Path +import sys from tempfile import mkstemp from types import GeneratorType @@ -10,7 +14,9 @@ from pytz import _UTC, timezone from ..utils.changelog import ChangeLog, Entry +from ..utils.conf import get_config_path, get_credentials +sys.path.append(os.path.dirname(__file__)) SAMPLE_CHANGES = """ ------------------------------------------------------------------- @@ -167,7 +173,7 @@ self.assertIsInstance(cl.entries, list) self.assertEqual(len(cl.entries), 2) finally: - remove(path) + os.remove(path) def test_parse_generative(self): with mock.patch("osctiny.utils.changelog.open", @@ -309,3 +315,62 @@ self.assertEqual(wmock.call_count, 1) self.assertIn("Cannot parse changelog entry", wmock.call_args[0][0]) + + +@mock.patch("osc.conf", side_effect=ImportError, create=True) +@mock.patch("pathlib.Path.is_file", return_value=True) +class TestConfig(TestCase): + def test_get_config_path(self, *_): + with self.subTest("No env vars"): + with mock.patch.dict(os.environ, values={}, clear=True): + self.assertEqual(Path.home().joinpath(".oscrc"), get_config_path()) + + with self.subTest("OSC_CONFIG"): + osc_config = "/foo/bar/oscrc" + with mock.patch.dict(os.environ, values={'OSC_CONFIG': osc_config}, clear=True): + self.assertEqual(Path(osc_config), get_config_path()) + + def test_get_credentials(self, *_): + _, path1 = mkstemp() + _, path2 = mkstemp() + + expected_insecure_credentials = ("my-dummy-user", "my-insecure-dummy-password") + expected_secure_credentials = ('my-dummy-user', 'my-secure-dummy-password') + + with open(path1, "w") as handle: + handle.write("[http://api.dummy-bs.org]\n") + handle.write("user={}\npass={}\n".format(*expected_insecure_credentials)) + + with open(path2, "w") as handle: + handle.write("[general]\n") + handle.write("apiurl=http://api.dummy-bs.org\n") + handle.write("[http://api.dummy-bs.org]\n") + handle.write("user={}\n".format(expected_secure_credentials[0])) + handle.write("passx={}\n".format(b64encode(compress( + expected_secure_credentials[1].encode("ascii") + )).decode("ascii"))) + + try: + with self.subTest("No URL, no default"): + with mock.patch.dict(os.environ, values={'OSC_CONFIG': path1}, clear=True): + self.assertRaises(ValueError, get_credentials) + + with self.subTest("Wrong URL"): + with mock.patch.dict(os.environ, values={'OSC_CONFIG': path1}, clear=True): + self.assertRaises(ValueError, get_credentials, "http://google.de") + + with self.subTest("Wrong scheme"): + with mock.patch.dict(os.environ, values={'OSC_CONFIG': path1}, clear=True): + self.assertRaises(ValueError, get_credentials, "https://api.dummy-bs.org") + + with self.subTest("Correct URL"): + with mock.patch.dict(os.environ, values={'OSC_CONFIG': path1}, clear=True): + credentials = get_credentials("http://api.dummy-bs.org") + self.assertEqual(expected_insecure_credentials, credentials) + + with self.subTest("No URL"): + with mock.patch.dict(os.environ, values={'OSC_CONFIG': path2}, clear=True): + self.assertEqual(expected_secure_credentials, get_credentials()) + finally: + os.remove(path1) + os.remove(path2) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-tiny-0.3.3/osctiny/utils/changelog.py new/osc-tiny-0.4.1/osctiny/utils/changelog.py --- old/osc-tiny-0.3.3/osctiny/utils/changelog.py 2021-02-24 11:35:35.000000000 +0100 +++ new/osc-tiny-0.4.1/osctiny/utils/changelog.py 2021-09-22 11:55:07.000000000 +0200 @@ -149,13 +149,13 @@ :param handle: An open and iterable (file) handle :type handle: Any derived object of :py:class:`io.IOBase` """ - # pylint: disable=too-many-branches + # pylint: disable=too-many-branches,consider-using-with entry = self.entry_factory() if isinstance(handle, TextIOBase): handle.seek(0) elif isinstance(handle, (str, bytes)): - handle = open(handle, "r") + handle = open(handle, "r") # pylint: disable=consider-using-with else: raise TypeError("Unexpected type for 'path': {}".format( type(handle))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-tiny-0.3.3/osctiny/utils/conf.py new/osc-tiny-0.4.1/osctiny/utils/conf.py --- old/osc-tiny-0.3.3/osctiny/utils/conf.py 1970-01-01 01:00:00.000000000 +0100 +++ new/osc-tiny-0.4.1/osctiny/utils/conf.py 2021-09-22 11:55:07.000000000 +0200 @@ -0,0 +1,107 @@ +""" +Configuration utilities +^^^^^^^^^^^^^^^^^^^^^^^ + +This module provides a collection of utilities to access the configuration of +`osc <https://github.com/openSUSE/osc>`_ in order to make it easier to create command line tools +with OSC Tiny. + +.. versionadded:: 0.4.0 +""" +from base64 import b64decode +from bz2 import decompress +from configparser import ConfigParser, NoSectionError +import os +from pathlib import Path +import warnings + +try: + from osc import conf as _conf +except ImportError: + _conf = None + + +def get_config_path(): + """ + Return path of ``osc`` configuration file + + :return: Path + :raises FileNotFoundError: if no config file found + """ + env_path = os.environ.get("OSC_CONFIG", None) + conf_path = os.environ.get('XDG_CONFIG_HOME', '~/.config') + if env_path: + path = Path(env_path) + if path.is_file(): + return path + + for path in (Path.home().joinpath(".oscrc"), + Path(conf_path).joinpath("osc/oscrc").expanduser()): + if path.is_file(): + return path + + raise FileNotFoundError("No `osc` configuration file found") + + +def get_credentials(url=None): + """ + Get credentials for Build Service instance identified by ``url`` + + .. important:: + + If the ``osc`` package is not installed, this function will only try to extract the username + and password from the configuration file. + + Any credentials stored on a keyring will not be accessible! + + :param str url: URL of Build Service instance (including schema). If not specified, the value + from the ``apiurl`` parameter in the config file will be used. + :return: (username, password) + :raises ValueError: if config provides no credentials + """ + if _conf is not None: + # pylint: disable=protected-access + parser = _conf.get_configParser() + try: + if url is None: + url = parser["general"].get("apiurl", url) + cred_mgr = _conf._get_credentials_manager(url, parser) + username = _conf._extract_user_compat(parser, url, cred_mgr) + except (KeyError, NoSectionError) as error: + raise ValueError("`osc` config does not provide the default API URL") from error + + if not username: + raise ValueError("`osc` config provides no username for URL {}".format(url)) + password = cred_mgr.get_password(url, username, defer=False) + if not password: + raise ValueError("`osc` config provides no password for URL {}".format(url)) + return username, password + + warnings.warn("`osc` is not installed. Not all configuration backends of `osc` will be " + "available.") + parser = ConfigParser() + path = get_config_path() + parser.read((path)) + try: + if url is None: + url = parser["general"].get("apiurl", url) + except (KeyError, NoSectionError) as error: + raise ValueError("`osc` config does not provide the default API URL") from error + + if url not in parser.sections(): + raise ValueError("`osc` config has no section for URL {}".format(url)) + + username = parser[url].get("user", None) + if not username: + raise ValueError("`osc` config provides no username for URL {}".format(url)) + + password = parser[url].get("pass", None) + if not password: + password = parser[url].get("passx", None) + if password: + password = decompress(b64decode(password.encode("ascii"))).decode("ascii") + + if not password: + raise ValueError("`osc` config provides no password for URL {}".format(url)) + + return username, password diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-tiny-0.3.3/setup.py new/osc-tiny-0.4.1/setup.py --- old/osc-tiny-0.3.3/setup.py 2021-02-24 11:35:35.000000000 +0100 +++ new/osc-tiny-0.4.1/setup.py 2021-09-22 11:55:07.000000000 +0200 @@ -19,7 +19,7 @@ setup( name='osc-tiny', - version='0.3.3', + version='0.4.1', description='Client API for openSUSE BuildService', long_description=long_description, long_description_content_type="text/markdown",