Hello community, here is the log from the commit of package python-osc-lib for openSUSE:Factory checked in at 2019-11-06 14:06:13 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-osc-lib (Old) and /work/SRC/openSUSE:Factory/.python-osc-lib.new.2990 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-osc-lib" Wed Nov 6 14:06:13 2019 rev:10 rq:745413 version:1.14.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-osc-lib/python-osc-lib.changes 2019-05-03 22:42:00.435188498 +0200 +++ /work/SRC/openSUSE:Factory/.python-osc-lib.new.2990/python-osc-lib.changes 2019-11-06 14:06:15.688795797 +0100 @@ -1,0 +2,19 @@ +Wed Oct 9 12:50:28 UTC 2019 - cloud-de...@suse.de + +- update to version 1.14.1 + - Corrent using auth_type=none in clouds.yaml + - Add Python 3 Train unit tests + - Add error message when occurrence Forbidden error + - Dropping the py35 testing + - format_dict() returns no value for None + - Updates for OpenDev transition + - Fix usage of NotFound exception + - Handle nested dicts in format_dict() + - Add FakeModule from OSC + - Final switch to stestr + - Move the _tag module from OSC to osc-lib + - Cleanups to prepare for OSC 4 release + - Update master for stable/stein + - OpenDev Migration Patch + +------------------------------------------------------------------- Old: ---- osc-lib-1.12.1.tar.gz New: ---- osc-lib-1.14.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-osc-lib.spec ++++++ --- /var/tmp/diff_new_pack.aF7irN/_old 2019-11-06 14:06:16.448796593 +0100 +++ /var/tmp/diff_new_pack.aF7irN/_new 2019-11-06 14:06:16.452796597 +0100 @@ -17,15 +17,14 @@ Name: python-osc-lib -Version: 1.12.1 +Version: 1.14.1 Release: 0 Summary: OpenStackClient Library License: Apache-2.0 Group: Development/Languages/Python URL: https://docs.openstack.org/developer/osc-lib -Source0: https://files.pythonhosted.org/packages/source/o/osc-lib/osc-lib-1.12.1.tar.gz +Source0: https://files.pythonhosted.org/packages/source/o/osc-lib/osc-lib-1.14.1.tar.gz BuildRequires: openstack-macros -BuildRequires: python-devel BuildRequires: python2-Babel >= 2.3.4 BuildRequires: python2-cliff >= 2.8.0 BuildRequires: python2-fixtures @@ -45,7 +44,6 @@ BuildRequires: python2-testtools BuildRequires: python3-Babel >= 2.3.4 BuildRequires: python3-cliff >= 2.8.0 -BuildRequires: python3-devel BuildRequires: python3-fixtures BuildRequires: python3-keystoneauth1 >= 3.7.0 BuildRequires: python3-mock @@ -81,16 +79,16 @@ %package -n python-osc-lib-doc Summary: Documentation for the OpenStack client library Group: Development/Languages/Python -BuildRequires: python-Sphinx -BuildRequires: python-openstackdocstheme -BuildRequires: python-reno -BuildRequires: python-sphinxcontrib-apidoc +BuildRequires: python3-Sphinx +BuildRequires: python3-openstackdocstheme +BuildRequires: python3-reno +BuildRequires: python3-sphinxcontrib-apidoc %description -n python-osc-lib-doc Documentation for the OpenStack client library. %prep -%autosetup -p1 -n osc-lib-1.12.1 +%autosetup -p1 -n osc-lib-1.14.1 %py_req_cleanup %build @@ -100,7 +98,7 @@ %{python_install} # generate html docs -PBR_VERSION=%version PYTHONPATH=. sphinx-build -a -E -d doc/build/doctrees -b html doc/source doc/build/html +PBR_VERSION=%{version} PYTHONPATH=. %sphinx_build -a -E -d doc/build/doctrees -b html doc/source doc/build/html # remove the sphinx-build leftovers rm -rf doc/build/html/.{doctrees,buildinfo} ++++++ _service ++++++ --- /var/tmp/diff_new_pack.aF7irN/_old 2019-11-06 14:06:16.500796647 +0100 +++ /var/tmp/diff_new_pack.aF7irN/_new 2019-11-06 14:06:16.504796652 +0100 @@ -1,8 +1,8 @@ <services> <service mode="disabled" name="renderspec"> - <param name="input-template">https://raw.githubusercontent.com/openstack/rpm-packaging/stable/stein/openstack/osc-lib/osc-lib.spec.j2</param> + <param name="input-template">https://raw.githubusercontent.com/openstack/rpm-packaging/stable/train/openstack/osc-lib/osc-lib.spec.j2</param> <param name="output-name">python-osc-lib.spec</param> - <param name="requirements">https://raw.githubusercontent.com/openstack/osc-lib/stable/stein/requirements.txt</param> + <param name="requirements">https://raw.githubusercontent.com/openstack/osc-lib/stable/train/requirements.txt</param> <param name="changelog-email">cloud-de...@suse.de</param> <param name="changelog-provider">gh,openstack,osc-lib</param> </service> ++++++ osc-lib-1.12.1.tar.gz -> osc-lib-1.14.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/.zuul.yaml new/osc-lib-1.14.1/.zuul.yaml --- old/osc-lib-1.12.1/.zuul.yaml 2019-03-01 02:31:55.000000000 +0100 +++ new/osc-lib-1.14.1/.zuul.yaml 2019-09-11 16:28:13.000000000 +0200 @@ -5,9 +5,7 @@ - lib-forward-testing-python3 - openstack-lower-constraints-jobs - openstack-python-jobs - - openstack-python35-jobs - - openstack-python36-jobs - - openstack-python37-jobs + - openstack-python3-train-jobs - osc-tox-unit-tips - publish-openstack-docs-pti - release-notes-jobs-python3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/AUTHORS new/osc-lib-1.14.1/AUTHORS --- old/osc-lib-1.12.1/AUTHORS 2019-03-01 02:34:12.000000000 +0100 +++ new/osc-lib-1.14.1/AUTHORS 2019-09-11 16:29:05.000000000 +0200 @@ -12,6 +12,7 @@ Amey Bhide <abh...@vmware.com> Andreas Jaeger <a...@suse.com> Andreas Jaeger <a...@suse.de> +Andrey Kurilin <andr.kuri...@gmail.com> Atsushi SAKAI <sak...@jp.fujitsu.com> Bar Elharar <elhar...@gmail.com> Bharat Kunwar <b.kun...@gmail.com> @@ -25,6 +26,7 @@ Chuck Short <chuck.sh...@canonical.com> Clark Boylan <clark.boy...@gmail.com> Colleen Murphy <coll...@puppetlabs.com> +Corey Bryant <corey.bry...@canonical.com> Cyril Roelandt <cyril.roela...@enovance.com> Daisuke Fujita <fuzita.dais...@jp.fujitsu.com> Daniel Gonzalez <dan...@gonzalez-nothnagel.de> @@ -34,11 +36,13 @@ David Moreau Simard <dmsim...@iweb.com> Dean Troyer <dtro...@gmail.com> Dina Belova <dbel...@mirantis.com> +Dmitry Tantsur <dtant...@protonmail.com> Doug Hellmann <doug.hellm...@dreamhost.com> Doug Hellmann <d...@doughellmann.com> Dougal Matthews <dou...@redhat.com> Eric Brown <bro...@vmware.com> Florent Flament <florent.flament-...@cloudwatt.com> +Ghanshyam Mann <gm...@ghanshyammann.com> Guojian Shao <guoj...@unitedstack.com> Hangdong Zhang <hdzh...@fiberhome.com> Hidekazu Nakamura <hid-nakam...@vf.jp.nec.com> @@ -78,6 +82,7 @@ Matt Riedemann <mrie...@us.ibm.com> Matthew Treinish <mtrein...@kortar.org> Matthieu Huin <m...@enovance.com> +Michael Johnson <johnso...@gmail.com> Michael McCune <m...@redhat.com> Monty Taylor <mord...@inaugust.com> Mouad Benchchaoui <m.benchcha...@x-ion.de> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/ChangeLog new/osc-lib-1.14.1/ChangeLog --- old/osc-lib-1.12.1/ChangeLog 2019-03-01 02:34:12.000000000 +0100 +++ new/osc-lib-1.14.1/ChangeLog 2019-09-11 16:29:05.000000000 +0200 @@ -1,6 +1,32 @@ CHANGES ======= +1.14.1 +------ + +* format\_dict() returns no value for None +* Handle nested dicts in format\_dict() + +1.14.0 +------ + +* Cleanups to prepare for OSC 4 release +* Fix usage of NotFound exception +* Add error message when occurrence Forbidden error +* Add Python 3 Train unit tests + +1.13.0 +------ + +* Corrent using auth\_type=none in clouds.yaml +* Add FakeModule from OSC +* Move the \_tag module from OSC to osc-lib +* Final switch to stestr +* Dropping the py35 testing +* Updates for OpenDev transition +* OpenDev Migration Patch +* Update master for stable/stein + 1.12.1 ------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/PKG-INFO new/osc-lib-1.14.1/PKG-INFO --- old/osc-lib-1.12.1/PKG-INFO 2019-03-01 02:34:12.000000000 +0100 +++ new/osc-lib-1.14.1/PKG-INFO 2019-09-11 16:29:05.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: osc-lib -Version: 1.12.1 +Version: 1.14.1 Summary: OpenStackClient Library Home-page: https://docs.openstack.org/osc-lib/latest/ Author: OpenStack @@ -32,7 +32,7 @@ .. _Online Documentation: http://docs.openstack.org/osc-lib/latest/ .. _Launchpad project: https://launchpad.net/python-openstackclient .. _Bugs: https://storyboard.openstack.org/#!/project_group/80 - .. _Source: https://git.openstack.org/cgit/openstack/osc-lib + .. _Source: https://opendev.org/openstack/osc-lib .. _Developer: http://docs.openstack.org/project-team-guide/project-setup/python.html .. _Contributing: http://docs.openstack.org/infra/manual/developers.html .. _Testing: http://docs.openstack.org/osc-lib/latest/contributor/#testing @@ -81,4 +81,5 @@ Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/README.rst new/osc-lib-1.14.1/README.rst --- old/osc-lib-1.12.1/README.rst 2019-03-01 02:31:55.000000000 +0100 +++ new/osc-lib-1.14.1/README.rst 2019-09-11 16:28:13.000000000 +0200 @@ -24,7 +24,7 @@ .. _Online Documentation: http://docs.openstack.org/osc-lib/latest/ .. _Launchpad project: https://launchpad.net/python-openstackclient .. _Bugs: https://storyboard.openstack.org/#!/project_group/80 -.. _Source: https://git.openstack.org/cgit/openstack/osc-lib +.. _Source: https://opendev.org/openstack/osc-lib .. _Developer: http://docs.openstack.org/project-team-guide/project-setup/python.html .. _Contributing: http://docs.openstack.org/infra/manual/developers.html .. _Testing: http://docs.openstack.org/osc-lib/latest/contributor/#testing diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/doc/source/contributor/index.rst new/osc-lib-1.14.1/doc/source/contributor/index.rst --- old/osc-lib-1.12.1/doc/source/contributor/index.rst 2019-03-01 02:31:55.000000000 +0100 +++ new/osc-lib-1.14.1/doc/source/contributor/index.rst 2019-09-11 16:28:13.000000000 +0200 @@ -9,7 +9,7 @@ :code:`openstack/osc-lib` project using `Gerrit`_. Developers may also be found in the `IRC channel`_ ``#openstack-sdks``. -.. _`on OpenStack's Git server`: https://git.openstack.org/cgit/openstack/python-openstackclient/tree +.. _`on OpenStack's Git server`: https://opendev.org/openstack/python-openstackclient/tree .. _Launchpad: https://launchpad.net/python-openstackclient .. _Gerrit: http://docs.openstack.org/infra/manual/developers.html#development-workflow .. _Bug reports: https://storyboard.openstack.org/#!/project_group/80 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/osc_lib/api/api.py new/osc-lib-1.14.1/osc_lib/api/api.py --- old/osc-lib-1.12.1/osc_lib/api/api.py 2019-03-01 02:31:55.000000000 +0100 +++ new/osc-lib-1.14.1/osc_lib/api/api.py 2019-09-11 16:28:13.000000000 +0200 @@ -361,7 +361,7 @@ num_bulk = len(bulk_list) if num_bulk == 0: msg = _("none found") - raise exceptions.NotFound(msg) + raise exceptions.NotFound(404, msg) elif num_bulk > 1: msg = _("many found") raise RuntimeError(msg) @@ -388,7 +388,7 @@ def raise_not_found(): msg = _("%s not found") % value - raise exceptions.NotFound(msg) + raise exceptions.NotFound(404, msg) try: ret = self._request( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/osc_lib/api/auth.py new/osc-lib-1.14.1/osc_lib/api/auth.py --- old/osc-lib-1.12.1/osc_lib/api/auth.py 2019-03-01 02:31:55.000000000 +0100 +++ new/osc-lib-1.14.1/osc_lib/api/auth.py 2019-09-11 16:28:13.000000000 +0200 @@ -101,7 +101,7 @@ msgs = [] # when no auth params are passed in, user advised to use os-cloud - if not options.auth: + if not options.auth and auth_plugin_name != 'none': msgs.append(_( 'Set a cloud-name with --os-cloud or OS_CLOUD' )) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/osc_lib/cli/client_config.py new/osc-lib-1.14.1/osc_lib/cli/client_config.py --- old/osc-lib-1.12.1/osc_lib/cli/client_config.py 2019-03-01 02:31:55.000000000 +0100 +++ new/osc-lib-1.14.1/osc_lib/cli/client_config.py 2019-09-11 16:28:13.000000000 +0200 @@ -162,10 +162,6 @@ strutils.mask_password(six.text_type(config))) return config - def _validate_auth_ksc(self, config, cloud, fixed_argparse=None): - """Old compatibility hack for OSC, no longer needed/wanted""" - return config - def _validate_auth(self, config, loader, fixed_argparse=None): """Validate auth plugin arguments""" # May throw a keystoneauth1.exceptions.NoMatchingPlugin @@ -226,3 +222,11 @@ config['auth'][p_opt.dest] = self._pw_callback(p_opt.prompt) return config + + def load_auth_plugin(self, config): + """Get auth plugin and validate args""" + + loader = self._get_auth_loader(config) + config = self._validate_auth(config, loader) + auth_plugin = loader.load_from_options(**config['auth']) + return auth_plugin diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/osc_lib/clientmanager.py new/osc-lib-1.14.1/osc_lib/clientmanager.py --- old/osc-lib-1.12.1/osc_lib/clientmanager.py 2019-03-01 02:31:55.000000000 +0100 +++ new/osc-lib-1.14.1/osc_lib/clientmanager.py 2019-09-11 16:28:13.000000000 +0200 @@ -202,9 +202,15 @@ self._auth_ref = self.auth.get_auth_ref(self.session) return self._auth_ref + def _override_for(self, service_type): + key = '%s_endpoint_override' % service_type.replace('-', '_') + return self._cli_options.config.get(key) + def is_service_available(self, service_type): """Check if a service type is in the current Service Catalog""" - + # If there is an override, assume the service is available + if self._override_for(service_type): + return True # Trigger authentication necessary to discover endpoint if self.auth_ref: service_catalog = self.auth_ref.service_catalog @@ -226,6 +232,11 @@ def get_endpoint_for_service_type(self, service_type, region_name=None, interface='public'): """Return the endpoint URL for the service type.""" + # Overrides take priority unconditionally + override = self._override_for(service_type) + if override: + return override + if not interface: interface = 'public' # See if we are using password flow auth, i.e. we have a diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/osc_lib/exceptions.py new/osc-lib-1.14.1/osc_lib/exceptions.py --- old/osc-lib-1.12.1/osc_lib/exceptions.py 2019-03-01 02:31:55.000000000 +0100 +++ new/osc-lib-1.14.1/osc_lib/exceptions.py 2019-09-11 16:28:13.000000000 +0200 @@ -55,6 +55,9 @@ """The base exception class for all exceptions this library raises.""" def __init__(self, code, message=None, details=None): + if not isinstance(code, int) and message is None: + message = code + code = self.http_status self.code = code self.message = message or self.__class__.message self.details = details diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/osc_lib/shell.py new/osc-lib-1.14.1/osc_lib/shell.py --- old/osc-lib-1.12.1/osc_lib/shell.py 2019-03-01 02:31:55.000000000 +0100 +++ new/osc-lib-1.14.1/osc_lib/shell.py 2019-09-11 16:28:13.000000000 +0200 @@ -410,6 +410,7 @@ self.cloud_config = cloud_config.OSC_Config( pw_func=prompt_for_password, override_defaults={ + 'interface': None, 'auth_type': self._auth_type, }, ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/osc_lib/tests/fakes.py new/osc-lib-1.14.1/osc_lib/tests/fakes.py --- old/osc-lib-1.12.1/osc_lib/tests/fakes.py 2019-03-01 02:31:55.000000000 +0100 +++ new/osc-lib-1.14.1/osc_lib/tests/fakes.py 2019-09-11 16:28:13.000000000 +0200 @@ -143,6 +143,16 @@ } +class FakeModule(object): + + def __init__(self, name, version): + self.name = name + self.__version__ = version + # Workaround for openstacksdk case + self.version = mock.Mock() + self.version.__version__ = version + + class FakeResource(object): def __init__(self, manager=None, info=None, loaded=False, methods=None): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/osc_lib/tests/test_clientmanager.py new/osc-lib-1.14.1/osc_lib/tests/test_clientmanager.py --- old/osc-lib-1.12.1/osc_lib/tests/test_clientmanager.py 2019-03-01 02:31:55.000000000 +0100 +++ new/osc-lib-1.14.1/osc_lib/tests/test_clientmanager.py 2019-09-11 16:28:13.000000000 +0200 @@ -419,6 +419,31 @@ self.assertEqual(client_manager.auth.project_id, fakes.PROJECT_ID) self.assertTrue(client_manager._auth_setup_completed) + def test_client_manager_none_auth(self): + # test token auth + client_manager = self._make_clientmanager( + auth_args={}, + auth_plugin_name='none', + ) + self.assertIsNone( + client_manager.get_endpoint_for_service_type('compute')) + + def test_client_manager_endpoint_override(self): + # test token auth + client_manager = self._make_clientmanager( + auth_args={}, + config_args={'compute_endpoint_override': 'http://example.com', + 'foo_bar_endpoint_override': 'http://example2.com'}, + auth_plugin_name='none', + ) + self.assertEqual( + 'http://example.com', + client_manager.get_endpoint_for_service_type('compute')) + self.assertEqual( + 'http://example2.com', + client_manager.get_endpoint_for_service_type('foo-bar')) + self.assertTrue(client_manager.is_service_available('compute')) + class TestClientManagerSDK(utils.TestClientManager): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/osc_lib/tests/utils/test_tags.py new/osc-lib-1.14.1/osc_lib/tests/utils/test_tags.py --- old/osc-lib-1.12.1/osc_lib/tests/utils/test_tags.py 1970-01-01 01:00:00.000000000 +0100 +++ new/osc-lib-1.14.1/osc_lib/tests/utils/test_tags.py 2019-09-11 16:28:13.000000000 +0200 @@ -0,0 +1,171 @@ +# Copyright 2019 Red Hat, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import argparse +import mock + +from osc_lib.tests import utils as test_utils +from osc_lib.utils import tags + + +class TestTags(test_utils.TestCase): + + def test_add_tag_filtering_option_to_parser(self): + parser = argparse.ArgumentParser() + tags.add_tag_filtering_option_to_parser(parser, 'test') + + parsed_args = parser.parse_args(['--tags', 'tag1,tag2', + '--any-tags', 'tag4', + '--not-tags', 'tag5', + '--not-any-tags', 'tag6']) + + actual = getattr(parsed_args, 'tags', []) + expected = ['tag1', 'tag2'] + self.assertItemsEqual(expected, actual) + + actual = getattr(parsed_args, 'any_tags', []) + expected = ['tag4'] + self.assertItemsEqual(expected, actual) + + actual = getattr(parsed_args, 'not_tags', []) + expected = ['tag5'] + self.assertItemsEqual(expected, actual) + + actual = getattr(parsed_args, 'not_any_tags', []) + expected = ['tag6'] + self.assertItemsEqual(expected, actual) + + def test_get_tag_filtering_args(self): + parser = argparse.ArgumentParser() + tags.add_tag_filtering_option_to_parser(parser, 'test') + + parsed_args = parser.parse_args(['--tags', 'tag1,tag2', + '--any-tags', 'tag4', + '--not-tags', 'tag5', + '--not-any-tags', 'tag6']) + expected = {'tags': 'tag1,tag2', 'any_tags': 'tag4', + 'not_tags': 'tag5', 'not_any_tags': 'tag6'} + args = {} + tags.get_tag_filtering_args(parsed_args, args) + self.assertEqual(expected, args) + + def test_add_tag_option_to_parser_for_create(self): + parser = argparse.ArgumentParser() + tags.add_tag_option_to_parser_for_create(parser, 'test') + + # Test that --tag and --no-tag are mutually exclusive + self.assertRaises(SystemExit, parser.parse_args, + ['--tag', 'tag1', '--no-tag']) + + parsed_args = parser.parse_args(['--tag', 'tag1']) + actual = getattr(parsed_args, 'tags', []) + expected = ['tag1'] + self.assertItemsEqual(expected, actual) + + parsed_args = parser.parse_args(['--no-tag']) + actual = getattr(parsed_args, 'no-tag', []) + expected = [] + self.assertItemsEqual(expected, actual) + + def test_add_tag_option_to_parser_for_set(self): + parser = argparse.ArgumentParser() + tags.add_tag_option_to_parser_for_set(parser, 'test') + + parsed_args = parser.parse_args(['--tag', 'tag1']) + actual = getattr(parsed_args, 'tags', []) + expected = ['tag1'] + self.assertItemsEqual(expected, actual) + + parsed_args = parser.parse_args(['--no-tag']) + actual = getattr(parsed_args, 'no-tag', []) + expected = [] + self.assertItemsEqual(expected, actual) + + def test_add_tag_option_to_parser_for_unset(self): + parser = argparse.ArgumentParser() + tags.add_tag_option_to_parser_for_unset(parser, 'test') + + # Test that --tag and --all-tag are mutually exclusive + self.assertRaises(SystemExit, parser.parse_args, + ['--tag', 'tag1', '--all-tag']) + + parsed_args = parser.parse_args(['--tag', 'tag1']) + actual = getattr(parsed_args, 'tags', []) + expected = ['tag1'] + self.assertItemsEqual(expected, actual) + + parsed_args = parser.parse_args(['--all-tag']) + actual = getattr(parsed_args, 'all-tag', []) + expected = [] + self.assertItemsEqual(expected, actual) + + def test_update_tags_for_set(self): + mock_client = mock.MagicMock() + mock_obj = mock.MagicMock() + mock_parsed_args = mock.MagicMock() + + # no-tag True path + mock_parsed_args.no_tag = True + mock_parsed_args.tags = ['tag1'] + mock_obj.tags = None + tags.update_tags_for_set(mock_client, mock_obj, mock_parsed_args) + mock_client.set_tags.assert_called_once_with( + mock_obj, list(mock_parsed_args.tags)) + + # no-tag False path + mock_client.set_tags.reset_mock() + mock_parsed_args.no_tag = False + mock_parsed_args.tags = ['tag1'] + mock_obj.tags = ['tag2'] + expected_list = ['tag1', 'tag2'] + tags.update_tags_for_set(mock_client, mock_obj, mock_parsed_args) + mock_client.set_tags.assert_called_once_with( + mock_obj, expected_list) + + # no new tags path + mock_client.set_tags.reset_mock() + mock_parsed_args.no_tag = False + mock_parsed_args.tags = None + mock_obj.tags = ['tag2'] + tags.update_tags_for_set(mock_client, mock_obj, mock_parsed_args) + mock_client.set_tags.assert_not_called() + + def test_update_tags_for_unset(self): + mock_client = mock.MagicMock() + mock_obj = mock.MagicMock() + mock_parsed_args = mock.MagicMock() + + # No new tags + mock_obj.tags = ['tag1'] + mock_parsed_args.all_tag = False + mock_parsed_args.tags = None + tags.update_tags_for_unset(mock_client, mock_obj, mock_parsed_args) + mock_client.set_tags.assert_not_called() + + # Clear all tags + mock_obj.tags = ['tag1'] + mock_parsed_args.all_tag = True + mock_parsed_args.tags = None + tags.update_tags_for_unset(mock_client, mock_obj, mock_parsed_args) + mock_client.set_tags.assert_called_once_with( + mock_obj, []) + + # Remove one tag + mock_client.set_tags.reset_mock() + mock_obj.tags = ['tag1', 'tag2'] + mock_parsed_args.all_tag = False + mock_parsed_args.tags = ['tag2'] + tags.update_tags_for_unset(mock_client, mock_obj, mock_parsed_args) + mock_client.set_tags.assert_called_once_with( + mock_obj, ['tag1']) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/osc_lib/tests/utils/test_utils.py new/osc-lib-1.14.1/osc_lib/tests/utils/test_utils.py --- old/osc-lib-1.12.1/osc_lib/tests/utils/test_utils.py 2019-03-01 02:31:55.000000000 +0100 +++ new/osc-lib-1.14.1/osc_lib/tests/utils/test_utils.py 2019-09-11 16:28:13.000000000 +0200 @@ -689,6 +689,50 @@ utils.format_dict({'e': 'f', 'c': 'd', 'a': 'b'})) self.assertIsNone(utils.format_dict(None)) + def test_format_dict_recursive(self): + expected = "a='b', c.1='d', c.2=''" + self.assertEqual( + expected, + utils.format_dict({'a': 'b', 'c': {'1': 'd', '2': ''}}) + ) + self.assertEqual( + expected, + utils.format_dict({'c': {'1': 'd', '2': ''}, 'a': 'b'}) + ) + self.assertIsNone(utils.format_dict(None)) + + expected = "a1='A', a2.b1.c1='B', a2.b1.c2=, a2.b2='D'" + self.assertEqual( + expected, + utils.format_dict( + { + 'a1': 'A', + 'a2': { + 'b1': { + 'c1': 'B', + 'c2': None, + }, + 'b2': 'D', + }, + } + ) + ) + self.assertEqual( + expected, + utils.format_dict( + { + 'a2': { + 'b1': { + 'c2': None, + 'c1': 'B', + }, + 'b2': 'D', + }, + 'a1': 'A', + } + ) + ) + def test_format_dict_of_list(self): expected = "a=a1, a2; b=b1, b2; c=c1, c2; e=" self.assertEqual(expected, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/osc_lib/utils/__init__.py new/osc-lib-1.14.1/osc_lib/utils/__init__.py --- old/osc-lib-1.12.1/osc_lib/utils/__init__.py 2019-03-01 02:31:55.000000000 +0100 +++ new/osc-lib-1.14.1/osc_lib/utils/__init__.py 2019-09-11 16:28:13.000000000 +0200 @@ -261,6 +261,16 @@ 'resource': manager.resource_class.__name__.lower(), 'id': name_or_id, }) + + if type(ex).__name__ == 'Forbidden': + msg = _( + "You are not authorized to find %(resource)s with the " + "name '%(id)s'." + ) + raise exceptions.CommandError(msg % { + 'resource': manager.resource_class.__name__.lower(), + 'id': name_or_id, + }) else: pass @@ -284,10 +294,11 @@ raise exceptions.CommandError(msg % name_or_id) -def format_dict(data): +def format_dict(data, prefix=None): """Return a formatted string of key value pairs :param data: a dict + :param prefix: the current parent keys in a recursive call :rtype: a string formatted to key='value' """ @@ -296,7 +307,18 @@ output = "" for s in sorted(data): - output = output + s + "='" + six.text_type(data[s]) + "', " + if prefix: + key_str = ".".join([prefix, s]) + else: + key_str = s + if isinstance(data[s], dict): + # NOTE(dtroyer): Only append the separator chars here, quoting + # is completely handled in the terminal case. + output = output + format_dict(data[s], prefix=key_str) + ", " + elif data[s] is not None: + output = output + key_str + "='" + six.text_type(data[s]) + "', " + else: + output = output + key_str + "=, " return output[:-2] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/osc_lib/utils/tags.py new/osc-lib-1.14.1/osc_lib/utils/tags.py --- old/osc-lib-1.12.1/osc_lib/utils/tags.py 1970-01-01 01:00:00.000000000 +0100 +++ new/osc-lib-1.14.1/osc_lib/utils/tags.py 2019-09-11 16:28:13.000000000 +0200 @@ -0,0 +1,174 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +import argparse + +from osc_lib.i18n import _ + + +class _CommaListAction(argparse.Action): + + def __call__(self, parser, namespace, values, option_string=None): + setattr(namespace, self.dest, values.split(',')) + + +def add_tag_filtering_option_to_parser(parser, resource_name): + """Add tag filtering options to a parser. + + :param parser: argparse.Argument parser object. + :param resource_name: Description of the object being filtered. + """ + parser.add_argument( + '--tags', + metavar='<tag>[,<tag>,...]', + action=_CommaListAction, + help=_('List %s which have all given tag(s) ' + '(Comma-separated list of tags)') % resource_name + ) + parser.add_argument( + '--any-tags', + metavar='<tag>[,<tag>,...]', + action=_CommaListAction, + help=_('List %s which have any given tag(s) ' + '(Comma-separated list of tags)') % resource_name + ) + parser.add_argument( + '--not-tags', + metavar='<tag>[,<tag>,...]', + action=_CommaListAction, + help=_('Exclude %s which have all given tag(s) ' + '(Comma-separated list of tags)') % resource_name + ) + parser.add_argument( + '--not-any-tags', + metavar='<tag>[,<tag>,...]', + action=_CommaListAction, + help=_('Exclude %s which have any given tag(s) ' + '(Comma-separated list of tags)') % resource_name + ) + + +def get_tag_filtering_args(parsed_args, args): + """Adds the tag arguments to an args list. + + Intended to be used to append the tags to an argument list that will be + used for service client. + + :param parsed_args: Parsed argument object returned by argparse parse_args. + :param args: The argument list to add tags to. + """ + if parsed_args.tags: + args['tags'] = ','.join(parsed_args.tags) + if parsed_args.any_tags: + args['any_tags'] = ','.join(parsed_args.any_tags) + if parsed_args.not_tags: + args['not_tags'] = ','.join(parsed_args.not_tags) + if parsed_args.not_any_tags: + args['not_any_tags'] = ','.join(parsed_args.not_any_tags) + + +def add_tag_option_to_parser_for_create(parser, resource_name): + """Add tag options to a parser for create commands. + + :param parser: argparse.Argument parser object. + :param resource_name: Description of the object being filtered. + """ + tag_group = parser.add_mutually_exclusive_group() + tag_group.add_argument( + '--tag', + action='append', + dest='tags', + metavar='<tag>', + help=_("Tag to be added to the %s " + "(repeat option to set multiple tags)") % resource_name + ) + tag_group.add_argument( + '--no-tag', + action='store_true', + help=_("No tags associated with the %s") % resource_name + ) + + +def add_tag_option_to_parser_for_set(parser, resource_name): + """Add tag options to a parser for set commands. + + :param parser: argparse.Argument parser object. + :param resource_name: Description of the object being filtered. + """ + parser.add_argument( + '--tag', + action='append', + dest='tags', + metavar='<tag>', + help=_("Tag to be added to the %s " + "(repeat option to set multiple tags)") % resource_name + ) + parser.add_argument( + '--no-tag', + action='store_true', + help=_("Clear tags associated with the %s. Specify both " + "--tag and --no-tag to overwrite current tags") % resource_name + ) + + +def add_tag_option_to_parser_for_unset(parser, resource_name): + """Add tag options to a parser for set commands. + + :param parser: argparse.Argument parser object. + :param resource_name: Description of the object being filtered. + """ + tag_group = parser.add_mutually_exclusive_group() + tag_group.add_argument( + '--tag', + action='append', + dest='tags', + metavar='<tag>', + help=_("Tag to be removed from the %s " + "(repeat option to remove multiple tags)") % resource_name) + tag_group.add_argument( + '--all-tag', + action='store_true', + help=_("Clear all tags associated with the %s") % resource_name) + + +def update_tags_for_set(client, obj, parsed_args): + """Set the tags on an object. + + :param client: The service client to use setting the tags. + :param obj: The object (Resource) to set the tags on. + :param parsed_args: Parsed argument object returned by argparse parse_args. + """ + if parsed_args.no_tag: + tags = set() + else: + tags = set(obj.tags or []) + if parsed_args.tags: + tags |= set(parsed_args.tags) + if set(obj.tags or []) != tags: + client.set_tags(obj, sorted(list(tags))) + + +def update_tags_for_unset(client, obj, parsed_args): + """Unset the tags on an object. + + :param client: The service client to use unsetting the tags. + :param obj: The object (Resource) to unset the tags on. + :param parsed_args: Parsed argument object returned by argparse parse_args. + """ + tags = set(obj.tags) + if parsed_args.all_tag: + tags = set() + if parsed_args.tags: + tags -= set(parsed_args.tags) + if set(obj.tags) != tags: + client.set_tags(obj, sorted(list(tags))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/osc_lib.egg-info/PKG-INFO new/osc-lib-1.14.1/osc_lib.egg-info/PKG-INFO --- old/osc-lib-1.12.1/osc_lib.egg-info/PKG-INFO 2019-03-01 02:34:12.000000000 +0100 +++ new/osc-lib-1.14.1/osc_lib.egg-info/PKG-INFO 2019-09-11 16:29:05.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: osc-lib -Version: 1.12.1 +Version: 1.14.1 Summary: OpenStackClient Library Home-page: https://docs.openstack.org/osc-lib/latest/ Author: OpenStack @@ -32,7 +32,7 @@ .. _Online Documentation: http://docs.openstack.org/osc-lib/latest/ .. _Launchpad project: https://launchpad.net/python-openstackclient .. _Bugs: https://storyboard.openstack.org/#!/project_group/80 - .. _Source: https://git.openstack.org/cgit/openstack/osc-lib + .. _Source: https://opendev.org/openstack/osc-lib .. _Developer: http://docs.openstack.org/project-team-guide/project-setup/python.html .. _Contributing: http://docs.openstack.org/infra/manual/developers.html .. _Testing: http://docs.openstack.org/osc-lib/latest/contributor/#testing @@ -81,4 +81,5 @@ Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/osc_lib.egg-info/SOURCES.txt new/osc-lib-1.14.1/osc_lib.egg-info/SOURCES.txt --- old/osc-lib-1.12.1/osc_lib.egg-info/SOURCES.txt 2019-03-01 02:34:12.000000000 +0100 +++ new/osc-lib-1.14.1/osc_lib.egg-info/SOURCES.txt 2019-09-11 16:29:05.000000000 +0200 @@ -72,16 +72,20 @@ osc_lib/tests/command/test_timing.py osc_lib/tests/utils/__init__.py osc_lib/tests/utils/test_columns.py +osc_lib/tests/utils/test_tags.py osc_lib/tests/utils/test_utils.py osc_lib/utils/__init__.py osc_lib/utils/columns.py +osc_lib/utils/tags.py releasenotes/notes/.placeholder releasenotes/notes/1.0-summary-47dcce446d6a512b.yaml releasenotes/notes/add-MultiKeyValueCommaAction-class-01dd254a287d70d2.yaml releasenotes/notes/arg-precedence-1ba9fd6929650830.yaml +releasenotes/notes/auth-type-none-d96760912605f822.yaml releasenotes/notes/bug-1558690-1528b637f2c0a449.yaml releasenotes/notes/bug-1630822-mask-password-on-debug-20dcdf1c54e84fa1.yaml releasenotes/notes/bug-2004898-686577a07e791051.yaml +releasenotes/notes/bug-2006480-436489d39643e76c.yaml releasenotes/notes/direct-openstacksdk-535a179f3c645cc0.yaml releasenotes/notes/find-project-203bf867619c557e.yaml releasenotes/notes/keystone-to-keystone-9b2e55b051775322.yaml @@ -95,6 +99,7 @@ releasenotes/source/pike.rst releasenotes/source/queens.rst releasenotes/source/rocky.rst +releasenotes/source/stein.rst releasenotes/source/unreleased.rst releasenotes/source/_static/.placeholder releasenotes/source/_templates/.placeholder \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/osc_lib.egg-info/pbr.json new/osc-lib-1.14.1/osc_lib.egg-info/pbr.json --- old/osc-lib-1.12.1/osc_lib.egg-info/pbr.json 2019-03-01 02:34:12.000000000 +0100 +++ new/osc-lib-1.14.1/osc_lib.egg-info/pbr.json 2019-09-11 16:29:05.000000000 +0200 @@ -1 +1 @@ -{"git_version": "9b610ea", "is_release": true} \ No newline at end of file +{"git_version": "a0d9746", "is_release": true} \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/releasenotes/notes/auth-type-none-d96760912605f822.yaml new/osc-lib-1.14.1/releasenotes/notes/auth-type-none-d96760912605f822.yaml --- old/osc-lib-1.12.1/releasenotes/notes/auth-type-none-d96760912605f822.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/osc-lib-1.14.1/releasenotes/notes/auth-type-none-d96760912605f822.yaml 2019-09-11 16:28:13.000000000 +0200 @@ -0,0 +1,7 @@ +--- +fixes: + - | + Fixes incorrect error when using ``auth_type: none`` in ``clouds.yaml``. + - | + Respects the ``<service type>_endpoint_override`` configuration options, + similarly to openstacksdk. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/releasenotes/notes/bug-2006480-436489d39643e76c.yaml new/osc-lib-1.14.1/releasenotes/notes/bug-2006480-436489d39643e76c.yaml --- old/osc-lib-1.12.1/releasenotes/notes/bug-2006480-436489d39643e76c.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/osc-lib-1.14.1/releasenotes/notes/bug-2006480-436489d39643e76c.yaml 2019-09-11 16:28:13.000000000 +0200 @@ -0,0 +1,4 @@ +--- +fixes: + - Fix format_columns.format_dict() to properly re-format nested dicts. + [Bug `2006480 <https://storyboard.openstack.org/#!/story/2006480>`_] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/releasenotes/source/index.rst new/osc-lib-1.14.1/releasenotes/source/index.rst --- old/osc-lib-1.12.1/releasenotes/source/index.rst 2019-03-01 02:31:55.000000000 +0100 +++ new/osc-lib-1.14.1/releasenotes/source/index.rst 2019-09-11 16:28:13.000000000 +0200 @@ -6,6 +6,7 @@ :maxdepth: 1 unreleased + stein rocky queens pike diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/releasenotes/source/stein.rst new/osc-lib-1.14.1/releasenotes/source/stein.rst --- old/osc-lib-1.12.1/releasenotes/source/stein.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/osc-lib-1.14.1/releasenotes/source/stein.rst 2019-09-11 16:28:13.000000000 +0200 @@ -0,0 +1,6 @@ +=================================== + Stein Series Release Notes +=================================== + +.. release-notes:: + :branch: stable/stein diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/setup.cfg new/osc-lib-1.14.1/setup.cfg --- old/osc-lib-1.12.1/setup.cfg 2019-03-01 02:34:12.000000000 +0100 +++ new/osc-lib-1.14.1/setup.cfg 2019-09-11 16:29:05.000000000 +0200 @@ -16,7 +16,8 @@ Programming Language :: Python :: 2 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 - Programming Language :: Python :: 3.5 + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 [files] packages = diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-lib-1.12.1/tox.ini new/osc-lib-1.14.1/tox.ini --- old/osc-lib-1.12.1/tox.ini 2019-03-01 02:31:55.000000000 +0100 +++ new/osc-lib-1.14.1/tox.ini 2019-09-11 16:28:13.000000000 +0200 @@ -1,6 +1,6 @@ [tox] minversion = 2.0 -envlist = py35,py27,pep8 +envlist = py27,py37,pep8 skipdist = True [testenv] @@ -11,11 +11,11 @@ OS_STDERR_CAPTURE=1 OS_TEST_TIMEOUT=60 deps = - -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} + -c{env:UPPER_CONSTRAINTS_FILE:https://opendev.org/openstack/requirements/raw/upper-constraints.txt} -r{toxinidir}/test-requirements.txt -r{toxinidir}/requirements.txt -commands = ostestr {posargs} -whitelist_externals = ostestr +commands = stestr run {posargs} +whitelist_externals = stestr [testenv:unit-tips] basepython = python3 @@ -24,8 +24,8 @@ pip install -q -e "git+file://{toxinidir}/../keystoneauth#egg=keystoneauth" pip install -q -e "git+file://{toxinidir}/../openstacksdk#egg=openstacksdk" pip freeze - ostestr {posargs} -whitelist_externals = ostestr + stestr run {posargs} +whitelist_externals = stestr [testenv:pep8] basepython = python3 @@ -48,7 +48,7 @@ [testenv:docs] basepython = python3 deps = - -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} + -c{env:UPPER_CONSTRAINTS_FILE:https://opendev.org/openstack/requirements/raw/upper-constraints.txt} -r{toxinidir}/requirements.txt -r{toxinidir}/doc/requirements.txt commands =