commit python-pywbem for openSUSE:Factory

Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-pywbem for openSUSE:Factory checked in at 2022-06-29 16:00:58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pywbem (Old) and /work/SRC/openSUSE:Factory/.python-pywbem.new.1548 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-pywbem" Wed Jun 29 16:00:58 2022 rev:19 rq:985569 version:1.4.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pywbem/python-pywbem.changes 2022-01-05 15:44:35.290258239 +0100 +++ /work/SRC/openSUSE:Factory/.python-pywbem.new.1548/python-pywbem.changes 2022-06-29 16:01:53.644665497 +0200 @@ -1,0 +2,29 @@ +Thu Jun 23 10:37:07 UTC 2022 - Ben Greiner <code@bnavigator.de> + +- Update to 1.4.1 + * Fix issue where the DeepInheritance parameter not passed to the + mocker OpenEnumerateInstances method so the result is that the + mocker always uses the default (DeepInheritance=True). (see + issue #2839) + * Modified compiler and pywbem_mock to allow creating instances + from abstract classes because SNIA ignored DMTF rule making + this illegal and many MOF compilers also ignored it. Pywbem + now issue a warning from the MOF compiler if an instance of an + abstract class is compiled but complete the compile and another + warning from pywbem_mock.CreateInstance if the instance is for + an abstract class. (see issue #2825) +- Release 1.4.0 + * Aligned minimum versions of pip,setuptools,wheel with + pywbemtools, nocasedict,nocaselist. This increased the minimum + version of pip on Python 3.5 to fix an issue. + * Improved verbosity of namespace creation and deletion: Added + optional 'verbose' parameters to the create_namecpace() and + delete_namespace() methods of WBEMServer, and to the + add_namecpace() and remove_namespace() methods of + FakedWBEMConnection (and subsequently to BaseProvider) in the + mock support. +- Actually cythonize if --with cythonize is given + * switched off by default, because the produced commands throw + yacc parser errors in the pywbemtools tests + +------------------------------------------------------------------- Old: ---- pywbem-1.3.0.tar.gz New: ---- pywbem-1.4.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pywbem.spec ++++++ --- /var/tmp/diff_new_pack.BCaVEF/_old 2022-06-29 16:01:54.236666285 +0200 +++ /var/tmp/diff_new_pack.BCaVEF/_new 2022-06-29 16:01:54.240666291 +0200 @@ -18,9 +18,10 @@ %{?!python_module:%define python_module() python3-%{**}} %define skip_python2 1 -%bcond_without cythonize +# cythonized pywbem produces yacc parser errors +%bcond_with cythonize Name: python-pywbem -Version: 1.3.0 +Version: 1.4.1 Release: 0 Summary: Python module for making CIM operation calls using the WBEM protocol License: LGPL-2.1-or-later @@ -29,7 +30,6 @@ Source0: https://github.com/pywbem/pywbem/archive/%{version}.tar.gz#/pywbem-%{version}.tar.gz BuildRequires: %{python_module FormEncode >= 2.0.0} BuildRequires: %{python_module PyYAML > 5.3.1} -BuildRequires: %{python_module base} BuildRequires: %{python_module httpretty} BuildRequires: %{python_module lxml >= 4.6.4} BuildRequires: %{python_module nocasedict >= 1.0.1} @@ -45,6 +45,7 @@ BuildRequires: %{python_module urllib3 >= 1.26.5} BuildRequires: %{python_module yamlloader >= 0.5.5} BuildRequires: %{python_module wheel} +BuildRequires: %{python_module pip} %if %{with cythonize} BuildRequires: %{python_module Cython} BuildRequires: %{python_module devel} @@ -76,10 +77,19 @@ %autopatch -p1 %build -%python_build +%if %{with cythonize} +%{python_expand # build cythonized wheel +$python setup.py bdist_wheel --cythonized +mv dist/pywbem-%{version}-cp%{$python_version_nodots}*.whl build/ +} +%else +# build one noarch wheel for all flavor installs +python3 setup.py bdist_wheel +mv dist/pywbem-%{version}-*py3-none-any.whl . +%endif %install -%python_install +%pyproject_install %fdupes %{buildroot} rm %{buildroot}%{_bindir}/*.bat %python_clone -a %{buildroot}%{_bindir}/mof_compiler @@ -98,8 +108,14 @@ %doc README.rst %license LICENSE.txt %python_alternative %{_bindir}/mof_compiler +%if %{with cythonize} +%{python_sitearch}/pywbem +%{python_sitearch}/pywbem_mock +%{python_sitearch}/pywbem-%{version}*-info +%else %{python_sitelib}/pywbem %{python_sitelib}/pywbem_mock %{python_sitelib}/pywbem-%{version}*-info +%endif %changelog ++++++ pywbem-1.3.0.tar.gz -> pywbem-1.4.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pywbem-1.3.0/.github/workflows/test.yml new/pywbem-1.4.1/.github/workflows/test.yml --- old/pywbem-1.3.0/.github/workflows/test.yml 2021-12-09 18:35:17.000000000 +0100 +++ new/pywbem-1.4.1/.github/workflows/test.yml 2022-02-01 17:17:43.000000000 +0100 @@ -9,9 +9,9 @@ - # cron (in UTC): minute hour day_of_month month day_of_week cron: '00 01 * * SUN' push: - branches: [ master, stable_1.3 ] + branches: [ master, stable_1.4 ] pull_request: - branches: [ master, stable_1.3 ] + branches: [ master, stable_1.4 ] env: # Local Docker image cache directory @@ -103,6 +103,11 @@ }, \ { \ \"os\": \"macos-latest\", \ + \"python-version\": \"3.5\", \ + \"package_level\": \"minimum\" \ + }, \ + { \ + \"os\": \"macos-latest\", \ \"python-version\": \"3.5\", \ \"package_level\": \"latest\" \ }, \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pywbem-1.3.0/Makefile new/pywbem-1.4.1/Makefile --- old/pywbem-1.3.0/Makefile 2021-12-09 18:35:17.000000000 +0100 +++ new/pywbem-1.4.1/Makefile 2022-02-01 17:17:43.000000000 +0100 @@ -293,6 +293,7 @@ # - 42298 Bleach before 3.12, mutation XSS affects bleach.clean # - 42293 babel, before 2.9.1 CVS-2021-42771, Bable.locale issue # - 42559 pip, before 21.1 CVE-2021-3572 +# - 43366 lxml, before 4.6.5 CVE-2021-43818, code not used safety_ignore_opts := \ -i 38100 \ @@ -329,6 +330,7 @@ -i 42298 \ -i 42203 \ -i 42559 \ + -i 43366 \ # Python source files for test (unit test and function test) test_src_files := \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pywbem-1.3.0/README_PYPI.rst new/pywbem-1.4.1/README_PYPI.rst --- old/pywbem-1.3.0/README_PYPI.rst 2021-12-09 18:35:17.000000000 +0100 +++ new/pywbem-1.4.1/README_PYPI.rst 2022-02-01 17:17:43.000000000 +0100 @@ -4,10 +4,10 @@ .. # we have to specify the package version directly in the links. .. # begin of customization for the current version -.. |pywbem-version-mn| replace:: 1.3 -.. _Readme file on GitHub: https://github.com/pywbem/pywbem/blob/stable_1.3/README.rst -.. _Documentation on RTD: https://pywbem.readthedocs.io/en/stable_1.3/ -.. _Change log on RTD: https://pywbem.readthedocs.io/en/stable_1.3/changes.html +.. |pywbem-version-mn| replace:: 1.4 +.. _Readme file on GitHub: https://github.com/pywbem/pywbem/blob/stable_1.4/README.rst +.. _Documentation on RTD: https://pywbem.readthedocs.io/en/stable_1.4/ +.. _Change log on RTD: https://pywbem.readthedocs.io/en/stable_1.4/changes.html .. # end of customization for the current version Pywbem is a WBEM client and WBEM indication listener and provides related diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pywbem-1.3.0/docs/changes.rst new/pywbem-1.4.1/docs/changes.rst --- old/pywbem-1.3.0/docs/changes.rst 2021-12-09 18:35:17.000000000 +0100 +++ new/pywbem-1.4.1/docs/changes.rst 2022-02-01 17:17:43.000000000 +0100 @@ -14,6 +14,46 @@ :revisions: 1 +pywbem 1.4.1 +------------ + +Released: 2022-02-01 + +**Bug fixes:** + +* Fix issue where the DeepInheritance parameter not passed to the mocker + OpenEnumerateInstances method so the result is that the mocker always + uses the default (DeepInheritance=True). (see issue #2839) + +**Cleanup:** + +* Modified compiler and pywbem_mock to allow creating instances from + abstract classes because SNIA ignored DMTF rule making this illegal and many + MOF compilers also ignored it. Pywbem now issue a warning from the MOF + compiler if an instance of an abstract class is compiled but complete + the compile and another warning from pywbem_mock.CreateInstance if the + instance is for an abstract class. (see issue #2825) + + +pywbem 1.4.0 +------------ + +Released: 2022-01-01 + +**Bug fixes:** + +* Aligned minimum versions of pip,setuptools,wheel with pywbemtools, + nocasedict,nocaselist. This increased the minimum version of pip + on Python 3.5 to fix an issue. + +**Enhancements:** + +* Improved verbosity of namespace creation and deletion: Added optional + 'verbose' parameters to the create_namecpace() and delete_namespace() methods + of WBEMServer, and to the add_namecpace() and remove_namespace() methods of + FakedWBEMConnection (and subsequently to BaseProvider) in the mock support. + + pywbem 1.3.0 ------------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pywbem-1.3.0/minimum-constraints.txt new/pywbem-1.4.1/minimum-constraints.txt --- old/pywbem-1.3.0/minimum-constraints.txt 2021-12-09 18:35:17.000000000 +0100 +++ new/pywbem-1.4.1/minimum-constraints.txt 2022-02-01 17:17:43.000000000 +0100 @@ -69,12 +69,14 @@ # setuptools 41.5.0 # wheel 0.33.5 -# For the base packages, we use the versions from Ubuntu 18.04 as a general -# minimum, and then increase it to the first version that introduced support -# for a particular Python version: -# The cryptography package requires pip>=21.0 on Windows on GitHub Actions. -# Pip 20.2 introduced a new resolver whose backtracking had issues that were resolved only in 21.2.2. -pip==9.0.1; python_version <= '3.5' +# Additional requirements: +# * pip>=9.0.0 to support the --upgrade-strategy option +# * setuptools>=20.5 to support environment markers +# * pip 10.0.0 introduced the --exclude-editable option. +# * pip 18.0 is needed on pypy3 (py36) to support constraints like cffi!=1.11.3,>=1.8. +# * pip 20.2 introduced a new resolver whose backtracking had issues that were resolved only in 21.2.2. +# * pip>=21.0 is needed for the cryptography package on Windows on GitHub Actions. +pip==10.0.1; python_version <= '3.5' pip==21.2.2; python_version >= '3.6' # setuptools before 49.0.0 compares Python versions in requirements based on strings and thus # ignores certain requirements on Python 3.10. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pywbem-1.3.0/pywbem/_mof_compiler.py new/pywbem-1.4.1/pywbem/_mof_compiler.py --- old/pywbem-1.3.0/pywbem/_mof_compiler.py 2021-12-09 18:35:17.000000000 +0100 +++ new/pywbem-1.4.1/pywbem/_mof_compiler.py 2022-02-01 17:17:43.000000000 +0100 @@ -79,6 +79,7 @@ import io import re import tempfile +import warnings from abc import ABCMeta, abstractmethod try: @@ -103,6 +104,7 @@ CIM_ERR_NOT_SUPPORTED from ._exceptions import Error, CIMError from ._utils import _format, _ensure_unicode +from ._warnings import ToleratedSchemaIssueWarning __all__ = ['MOFCompileError', 'MOFParseError', 'MOFDependencyError', 'MOFRepositoryError', 'MOFCompiler', 'BaseRepositoryConnection'] @@ -632,7 +634,8 @@ assert not fixedNS # Should not happen if we created it if p.parser.verbose: p.parser.log( - _format("Creating namespace {0}", ns)) + _format("Creating namespace {0} (in MOF compiler)", + ns)) p.parser.server.create_namespace(ns) fixedNS = True continue # Try again to create the class @@ -894,7 +897,7 @@ if ce.status_code == CIM_ERR_INVALID_NAMESPACE: if p.parser.verbose: p.parser.log( - _format("Creating namespace {0}", ns)) + _format("Creating namespace {0} (in MOF compiler)", ns)) p.parser.server.create_namespace(ns) if p.parser.verbose: p.parser.log( @@ -1117,7 +1120,7 @@ cim_error=ce) if p.parser.verbose: p.parser.log( - _format("Creating namespace {0}", ns)) + _format("Creating namespace {0} (in MOF compiler)", ns)) p.parser.server.create_namespace(ns) quals = None @@ -2403,11 +2406,11 @@ cls, inst, namespace=ns) if "Abstract" in cls.qualifiers: - raise CIMError( - CIM_ERR_FAILED, - _format("CreateInstance failed. Cannot instantiate abstract " - "class {0!A} in Namespace {1!A}.", - inst.classname, ns)) + warnings.warn( + _format("Tolerating instance creation of abstract class {0} " + " in namepace {1} which is forbidden by DMTF DSP0004.", + inst.classname, ns), + ToleratedSchemaIssueWarning, 1) try: self.instances[ns].append(inst) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pywbem-1.3.0/pywbem/_server.py new/pywbem-1.4.1/pywbem/_server.py --- old/pywbem-1.3.0/pywbem/_server.py 2021-12-09 18:35:17.000000000 +0100 +++ new/pywbem-1.4.1/pywbem/_server.py 2022-02-01 17:17:43.000000000 +0100 @@ -381,7 +381,7 @@ self._determine_profiles() return self._profiles - def create_namespace(self, namespace): + def create_namespace(self, namespace, verbose=False): """ Create the specified CIM namespace in the WBEM server and update this WBEMServer object to reflect the new namespace @@ -420,6 +420,9 @@ The namespace may contain leading and a trailing slash, both of which will be ignored. + verbose (:class:`py:bool`): + Verbose mode: Print a message about the namespace creation. + Returns: :term:`unicode string`: The specified CIM namespace name in its @@ -433,6 +436,10 @@ std_namespace = _ensure_unicode(namespace.strip('/')) + if verbose: + print("Creating namespace {} (in WBEMServer)". + format(std_namespace)) + try: ws_profiles = self.get_selected_profiles('DMTF', 'WBEM Server') except (CIMError, ModelError): @@ -513,7 +520,8 @@ ns_inst['SystemCreationClassName'] = \ self.cimom_inst['SystemCreationClassName'] - self.conn.CreateInstance(ns_inst, namespace=self.interop_ns) + interop_ns = self.interop_ns # Determines the Interop namespace + self.conn.CreateInstance(ns_inst, namespace=interop_ns) # Refresh the list of namespaces in this object to include the one # we just created. @@ -524,7 +532,7 @@ return std_namespace - def delete_namespace(self, namespace): + def delete_namespace(self, namespace, verbose=False): """ Delete the specified CIM namespace in the WBEM server and update this WBEMServer object to reflect the removed namespace @@ -562,6 +570,9 @@ The namespace may contain leading and a trailing slash, both of which will be ignored. + verbose (:class:`py:bool`): + Verbose mode: Print a message about the namespace creation. + Returns: :term:`unicode string`: The specified CIM namespace name in its @@ -578,6 +589,10 @@ std_namespace = _ensure_unicode(namespace.strip('/')) + if verbose: + print("Deleting namespace {} (in WBEMServer)". + format(std_namespace)) + # Use approach 1: DeleteInstance of CIM class for namespaces # Refresh the list of namespaces in this object to make sure @@ -667,7 +682,8 @@ and does not include the required properties. """ - org_vm = ValueMapping.for_property(self, self.interop_ns, + interop_ns = self.interop_ns # Determines the Interop namespace + org_vm = ValueMapping.for_property(self, interop_ns, 'CIM_RegisteredProfile', 'RegisteredOrganization') org_lower = registered_org.lower() \ @@ -686,7 +702,7 @@ _format("CIM_RegisteredProfile instance in namespace " "{0!A} does not have a property " "'RegisteredOrganization'", - self.interop_ns)) + interop_ns)) inst_org = org_vm.tovalues(inst_org_value) try: inst_name = inst['RegisteredName'] @@ -695,7 +711,7 @@ _format("CIM_RegisteredProfile instance in namespace " "{0!A} does not have a property " "'RegisteredName'", - self.interop_ns)) + interop_ns)) try: inst_version = inst['RegisteredVersion'] except KeyError: @@ -703,7 +719,7 @@ _format("CIM_RegisteredProfile instance in namespace " "{0!A} does not have a property " "'RegisteredVersion'", - self.interop_ns)) + interop_ns)) inst_org_lower = inst_org.lower() \ if inst_org is not None else None @@ -1104,8 +1120,8 @@ if interop_ns is None: # Exhausted the possible namespaces raise ModelError( - _format("Interop namespace could not be determined " - "(tried {0!A})", self.INTEROP_NAMESPACES), + _format("Interop namespace does not exist (tried {0!A})", + self.INTEROP_NAMESPACES), conn_id=self.conn.conn_id) self._interop_ns = interop_ns @@ -1224,8 +1240,9 @@ Exceptions raised by :class:`~pywbem.WBEMConnection`. ModelError: An error with the model implemented by the WBEM server. """ + interop_ns = self.interop_ns # Determines the Interop namespace cimom_insts = self._conn.EnumerateInstances( - "CIM_ObjectManager", namespace=self.interop_ns) + "CIM_ObjectManager", namespace=interop_ns) if len(cimom_insts) != 1: raise ModelError( _format("Unexpected number of CIM_ObjectManager instances: " @@ -1299,6 +1316,7 @@ Exceptions raised by :class:`~pywbem.WBEMConnection`. ModelError: An error with the model implemented by the WBEM server. """ + interop_ns = self.interop_ns # Determines the Interop namespace mp_insts = self._conn.EnumerateInstances("CIM_RegisteredProfile", - namespace=self.interop_ns) + namespace=interop_ns) self._profiles = mp_insts diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pywbem-1.3.0/pywbem/_subscription_manager.py new/pywbem-1.4.1/pywbem/_subscription_manager.py --- old/pywbem-1.3.0/pywbem/_subscription_manager.py 2021-12-09 18:35:17.000000000 +0100 +++ new/pywbem-1.4.1/pywbem/_subscription_manager.py 2022-02-01 17:17:43.000000000 +0100 @@ -371,6 +371,8 @@ _format("WBEM server already known by listener: {0!A}", server_id)) + interop_ns = server.interop_ns # Determines the Interop namespace + # Create dictionary entries for this server self._servers[server_id] = server self._owned_subscriptions[server_id] = [] @@ -396,7 +398,7 @@ this_client, self._subscription_manager_id)) dest_insts = server.conn.EnumerateInstances( - DESTINATION_CLASSNAME, namespace=server.interop_ns) + DESTINATION_CLASSNAME, namespace=interop_ns) for inst in dest_insts: if re.match(dest_name_pattern, inst.path.keybindings['Name']): @@ -418,7 +420,7 @@ this_client, self._subscription_manager_id)) filter_insts = server.conn.EnumerateInstances( - FILTER_CLASSNAME, namespace=server.interop_ns) + FILTER_CLASSNAME, namespace=interop_ns) for inst in filter_insts: if re.match(filter_name_pattern, inst.path.keybindings['Name']): @@ -433,7 +435,7 @@ OldNameFilterWarning, 2) sub_insts = server.conn.EnumerateInstances( - SUBSCRIPTION_CLASSNAME, namespace=server.interop_ns) + SUBSCRIPTION_CLASSNAME, namespace=interop_ns) owned_filter_paths = [inst.path for inst in self._owned_filters[server_id]] owned_destination_paths = [inst.path for inst in @@ -741,8 +743,10 @@ # Validate server_id server = self._get_server(server_id) + interop_ns = server.interop_ns # Determines the Interop namespace + return server.conn.EnumerateInstances(DESTINATION_CLASSNAME, - namespace=server.interop_ns) + namespace=interop_ns) def remove_destinations(self, server_id, destination_paths): # pylint: disable=line-too-long @@ -1023,8 +1027,10 @@ # Validate server_id server = self._get_server(server_id) + interop_ns = server.interop_ns # Determines the Interop namespace + return server.conn.EnumerateInstances('CIM_IndicationFilter', - namespace=server.interop_ns) + namespace=interop_ns) def remove_filter(self, server_id, filter_path): """ @@ -1242,8 +1248,10 @@ # Validate server_id server = self._get_server(server_id) + interop_ns = server.interop_ns # Determines the Interop namespace + return server.conn.EnumerateInstances(SUBSCRIPTION_CLASSNAME, - namespace=server.interop_ns) + namespace=interop_ns) def remove_subscriptions(self, server_id, sub_paths): # pylint: disable=line-too-long @@ -1371,6 +1379,8 @@ # Validate the URL by reconstructing it. Do not allow defaults _, _, listener_url = parse_url(dest_url, allow_defaults=False) + interop_ns = server.interop_ns # Determines the Interop namespace + dest_inst = CIMInstance(DESTINATION_CLASSNAME) dest_inst['CreationClassName'] = DESTINATION_CLASSNAME dest_inst['SystemCreationClassName'] = SYSTEM_CREATION_CLASSNAME @@ -1387,7 +1397,7 @@ # Test if instance already exists in the WBEM server existing_dest_insts = server.conn.EnumerateInstances( - DESTINATION_CLASSNAME, namespace=server.interop_ns) + DESTINATION_CLASSNAME, namespace=interop_ns) for inst in existing_dest_insts: name_prop = inst.properties.get('Name', None) # CIMProperty if name_prop and name_prop.value == name: @@ -1405,8 +1415,7 @@ inst['PersistenceType'] == dest_inst['PersistenceType']: return inst - dest_path = server.conn.CreateInstance( - dest_inst, namespace=server.interop_ns) + dest_path = server.conn.CreateInstance(dest_inst, namespace=interop_ns) dest_inst = server.conn.GetInstance(dest_path) if owned: @@ -1466,6 +1475,8 @@ # Validate server_id server = self._get_server(server_id) + interop_ns = server.interop_ns # Determines the Interop namespace + owned = filter_id is not None filter_inst = CIMInstance(FILTER_CLASSNAME) @@ -1485,7 +1496,7 @@ filter_inst['QueryLanguage'] = query_language existing_filter_insts = server.conn.EnumerateInstances( - FILTER_CLASSNAME, namespace=server.interop_ns) + FILTER_CLASSNAME, namespace=interop_ns) for inst in existing_filter_insts: name_prop = inst.properties.get('Name', None) # CIMProperty if name_prop and name_prop.value == name: @@ -1494,7 +1505,7 @@ "Filter instance with Name='{0}' already exists: {1}". format(name, inst.path)) filter_path = server.conn.CreateInstance( - filter_inst, namespace=server.interop_ns) + filter_inst, namespace=interop_ns) filter_inst = server.conn.GetInstance(filter_path) if owned: @@ -1541,8 +1552,10 @@ # Validate server_id server = self._get_server(server_id) + interop_ns = server.interop_ns # Determines the Interop namespace + sub_path = CIMInstanceName(SUBSCRIPTION_CLASSNAME, - namespace=server.interop_ns, + namespace=interop_ns, keybindings=[('Filter', filter_path), ('Handler', dest_path)]) @@ -1561,13 +1574,13 @@ # exists. return inst sub_path = server.conn.CreateInstance( - sub_inst, namespace=server.interop_ns) + sub_inst, namespace=interop_ns) sub_inst = server.conn.GetInstance(sub_path) self._owned_subscriptions[server_id].append(sub_inst) else: # Responsibility to ensure it does not exist yet is with the user sub_path = server.conn.CreateInstance( - sub_inst, namespace=server.interop_ns) + sub_inst, namespace=interop_ns) sub_inst = server.conn.GetInstance(sub_path) return sub_inst diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pywbem-1.3.0/pywbem/_version.py new/pywbem-1.4.1/pywbem/_version.py --- old/pywbem-1.3.0/pywbem/_version.py 2021-12-09 18:35:17.000000000 +0100 +++ new/pywbem-1.4.1/pywbem/_version.py 2022-02-01 17:17:43.000000000 +0100 @@ -29,4 +29,4 @@ #: #: * "M.N.P.devD": Development level D of a not yet released version M.N.P #: * "M.N.P": A released version M.N.P -__version__ = '1.3.0' +__version__ = '1.4.1' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pywbem-1.3.0/pywbem_mock/_baseprovider.py new/pywbem-1.4.1/pywbem_mock/_baseprovider.py --- old/pywbem-1.3.0/pywbem_mock/_baseprovider.py 2021-12-09 18:35:17.000000000 +0100 +++ new/pywbem-1.4.1/pywbem_mock/_baseprovider.py 2022-02-01 17:17:43.000000000 +0100 @@ -153,7 +153,7 @@ _format("Namespace does not exist in CIM repository: {0!A}", namespace)) - def add_namespace(self, namespace): + def add_namespace(self, namespace, verbose=False): """ Add a CIM namespace to the CIM repository. @@ -170,6 +170,9 @@ `None`. Any leading or trailing slash characters are removed before the string is used to define the namespace name. + verbose (:class:`py:bool`): + Verbose mode: Print a message about the namespace creation. + Raises: ValueError: Namespace argument must not be None. @@ -193,6 +196,9 @@ _format("An Interop namespace {0!A} already exists in the " "CIM repository. {1!A} cannot be added. ", self.find_interop_namespace(), namespace)) + if verbose: + print("Creating namespace {} (in mock support)". + format(namespace)) try: self.cimrepository.add_namespace(namespace) except ValueError: @@ -201,7 +207,7 @@ _format("Namespace {0!A} already exists in the CIM repository ", namespace)) - def remove_namespace(self, namespace): + def remove_namespace(self, namespace, verbose=False): """ Remove a CIM namespace from the CIM repository. @@ -216,6 +222,9 @@ insensitive). Must not be `None`. Leading or trailing slash characters are ignored. + verbose (:class:`py:bool`): + Verbose mode: Print a message about the namespace deletion. + Raises: ValueError: Namespace argument must not be None. @@ -246,6 +255,9 @@ _format("The Interop namespace {0!A} cannot be removed from " "the CIM repository.", namespace)) + if verbose: + print("Deleting namespace {} (in mock support)". + format(namespace)) try: self.cimrepository.remove_namespace(namespace) # KeyError cannot happen because existence was already verified diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pywbem-1.3.0/pywbem_mock/_inmemoryrepository.py new/pywbem-1.4.1/pywbem_mock/_inmemoryrepository.py --- old/pywbem-1.3.0/pywbem_mock/_inmemoryrepository.py 2021-12-09 18:35:17.000000000 +0100 +++ new/pywbem-1.4.1/pywbem_mock/_inmemoryrepository.py 2022-02-01 17:17:43.000000000 +0100 @@ -181,7 +181,7 @@ Parameters: - initial_namespace:(:term:`string` or None): + initial_namespace (:term:`string` or None): Optional initial namespace that will be added to the CIM repository. """ @@ -204,7 +204,7 @@ return _format( "InMemoryRepository(data={s._repository})", s=self) - def print_repository(self, dest=None, ): + def print_repository(self, dest=None): """ Print the CIM repository to a destination. This displays information on the items in the data base and is only a diagnostic tool. @@ -214,6 +214,7 @@ File path of an output file. If `None`, the output is written to stdout. """ + def objstore_info(objstore_name): """ Display the data for the object store diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pywbem-1.3.0/pywbem_mock/_providerdispatcher.py new/pywbem-1.4.1/pywbem_mock/_providerdispatcher.py --- old/pywbem-1.3.0/pywbem_mock/_providerdispatcher.py 2021-12-09 18:35:17.000000000 +0100 +++ new/pywbem-1.4.1/pywbem_mock/_providerdispatcher.py 2022-02-01 17:17:43.000000000 +0100 @@ -32,6 +32,7 @@ from __future__ import absolute_import, print_function from copy import deepcopy +import warnings import six try: from collections.abc import Mapping, Sequence @@ -41,7 +42,8 @@ from pywbem import CIMInstance, CIMInstanceName, CIMClass, CIMClassName, \ CIMParameter, CIMError, CIM_ERR_NOT_FOUND, CIM_ERR_INVALID_PARAMETER, \ - CIM_ERR_INVALID_CLASS, CIM_ERR_METHOD_NOT_FOUND, cimtype, CIM_ERR_FAILED + CIM_ERR_INVALID_CLASS, CIM_ERR_METHOD_NOT_FOUND, cimtype, \ + ToleratedSchemaIssueWarning from pywbem._utils import _format from pywbem._nocasedict import NocaseDict @@ -215,11 +217,11 @@ NewInstance.classname, namespace)) if "Abstract" in creation_class.qualifiers: - raise CIMError( - CIM_ERR_FAILED, - _format("CreateInstance failed. Cannot instantiate abstract " - "class {0!A} in Namespace {1!A}.", - NewInstance.classname, namespace)) + warnings.warn( + _format("Tolerating instance creation of abstract class {0} " + " in namepace {1} which is forbidden by DMTF DSP0004.", + NewInstance.classname, namespace), + ToleratedSchemaIssueWarning, 1) # Verify that the properties in the new instance are exposed by the # creation class and have the correct type-related attributes. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pywbem-1.3.0/pywbem_mock/_wbemconnection_mock.py new/pywbem-1.4.1/pywbem_mock/_wbemconnection_mock.py --- old/pywbem-1.3.0/pywbem_mock/_wbemconnection_mock.py 2021-12-09 18:35:17.000000000 +0100 +++ new/pywbem-1.4.1/pywbem_mock/_wbemconnection_mock.py 2022-02-01 17:17:43.000000000 +0100 @@ -406,7 +406,7 @@ # so they can be access with call to the methods from instance of # this class. they are considered part of the external API. - def add_namespace(self, namespace): + def add_namespace(self, namespace, verbose=False): """ Add a CIM namespace to the CIM repository of the faked connection. @@ -419,15 +419,18 @@ Must not be `None`. Any leading or trailing slash characters are removed before the string is used to define the namespace name. + verbose (:class:`py:bool`): + Verbose mode: Print a message about the namespace creation. + Raises: ValueError: Namespace argument must not be None. :exc:`~pywbem.CIMError`: CIM_ERR_ALREADY_EXISTS if the namespace already exists in the CIM repository. """ - self._mainprovider.add_namespace(namespace) + self._mainprovider.add_namespace(namespace, verbose=verbose) - def remove_namespace(self, namespace): + def remove_namespace(self, namespace, verbose=False): """ Remove a CIM namespace from the CIM repository of the faked connection. @@ -440,6 +443,9 @@ insensitive). Must not be `None`. Leading or trailing slash characters are ignored. + verbose (:class:`py:bool`): + Verbose mode: Print a message about the namespace deletion. + Raises: ValueError: Namespace argument must not be None @@ -451,7 +457,7 @@ to delete the default connection namespace. This namespace cannot be deleted from the CIM repository """ - self._mainprovider.remove_namespace(namespace) + self._mainprovider.remove_namespace(namespace, verbose=verbose) def is_interop_namespace(self, namespace): """ @@ -1765,6 +1771,7 @@ context_tuple = self._mainprovider.OpenEnumerateInstances( namespace=namespace, ClassName=_cvt_rqd_classname(params['ClassName']), + DeepInheritance=params.get('DeepInheritance', None), IncludeClassOrigin=params.get('IncludeClassOrigin', None), PropertyList=params.get('PropertyList', None), FilterQueryLanguage=params.get('FilterQueryLanguage', None), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pywbem-1.3.0/tests/unittest/pywbem/test_mof_compiler.py new/pywbem-1.4.1/tests/unittest/pywbem/test_mof_compiler.py --- old/pywbem-1.3.0/tests/unittest/pywbem/test_mof_compiler.py 2021-12-09 18:35:17.000000000 +0100 +++ new/pywbem-1.4.1/tests/unittest/pywbem/test_mof_compiler.py 2022-02-01 17:17:43.000000000 +0100 @@ -34,6 +34,8 @@ from pywbem import _mof_compiler, CIMInstance, CIMError # noqa: E402 from pywbem._utils import _format # noqa: E402 from pywbem._nocasedict import NocaseDict # noqa: E402 +from pywbem._warnings import ToleratedSchemaIssueWarning # noqa: E402 + pywbem_mock = import_installed('pywbem_mock') from pywbem_mock import FakedWBEMConnection # noqa: E402 # pylint: enable=wrong-import-position, wrong-import-order, invalid-name @@ -3232,5 +3234,113 @@ assert rtn_property_value.classname == 'TST_Embedded1' +ABSTRACT_INSTANCE_TEST_MOF = """ + + Qualifier Abstract : boolean = false, + Scope(class, association, indication), + Flavor(EnableOverride, Restricted); + + Qualifier Key : boolean = false, + Scope(property, reference), + Flavor(DisableOverride, ToSubclass); + + Qualifier Description : string = null, + Scope(any), + Flavor(EnableOverride, ToSubclass, Translatable); + + Qualifier Version : string, + Scope(class, association, indication), + Flavor(EnableOverride, Restricted, Translatable); + + [Abstract, Version ( "2.6.0" ), + Description ("Test class that is abstract")] + class TST_AbstractClass { + [Key, Description ("Key property")] + string InstanceID; + }; + [Description ("Subclass of abstract class")] + class TST_AbstractClassSub: TST_AbstractClass { + }; + +""" + +TESTCASES_ABSTRACT_MOF_INSTANCE_COMPILE = [ + + # Testcases for testing good, warning generating and error mof where + # the MOF can be defined for each test. + + # Each list item is a testcase tuple with these items: + # * desc: Short testcase description. + # * kwargs: Keyword arguments for the test function: + # * instmof: name of the embedded instance property + # * pstr: String containing mof for property + # * result_inst - Instance retrieved to test creation of instmof + # * exp_exc_types: Expected exception type(s), or None. + # * exp_warn_types: Expected warning type(s), or None. + # * condition: Boolean condition for testcase to run, or 'pdb' for debugger + # NOTE: All embedded property mof defintions that are python strings must + # define any included EOL with either the python raw (r'<string' or double + # \\ (\\n). + ( + "Validate creation single instance of Abstract class", + dict( + instmof="instance of TST_AbstractClass { " \ + 'InstanceID = "Inst1"; ' \ + "};", + result_inst=CIMInstance( + "TST_AbstractClass", + path=CIMInstanceName("TST_AbstractClass", + keybindings=dict(InstanceID='Inst1')), + properties=[ + CIMProperty('InstanceID', value='Inst1')]) + ), + None, ToleratedSchemaIssueWarning, OK + ), + + ( + "Validate creation single instance of not Abstract class", + dict( + instmof="instance of TST_AbstractClassSub { " \ + 'InstanceID = "Inst1"; ' \ + "};", + result_inst=CIMInstance( + "TST_AbstractClassSub", + path=CIMInstanceName("TST_AbstractClassSub", + keybindings=dict(InstanceID='Inst1')), + properties=[ + CIMProperty('InstanceID', value='Inst1')]) + ), + None, None, OK + ), +] + + +@pytest.mark.parametrize( + "desc, kwargs, exp_exc_types, exp_warn_types, condition", + TESTCASES_ABSTRACT_MOF_INSTANCE_COMPILE) +@simplified_test_function +def test_abstract_mof_instance_compile(testcase, instmof, result_inst): + # pylint: disable=unused-argument + """ + Test embedded object instances warning + """ + conn = FakedWBEMConnection() + conn.compile_mof_string(ABSTRACT_INSTANCE_TEST_MOF, verbose=False) + + conn.compile_mof_string(instmof) + + # Get created instance and validate instance(s) created + + path = CIMInstanceName(result_inst.classname, + keybindings=dict(InstanceID="Inst1")) + rtn_inst = conn.GetInstance(path) + + # Account for differences in namespace, host in paths + rtn_inst.path.namespace = None + rtn_inst.path.host = None + + assert rtn_inst == result_inst + + if __name__ == '__main__': unittest.main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pywbem-1.3.0/tests/unittest/pywbem_mock/test_wbemconnection_mock.py new/pywbem-1.4.1/tests/unittest/pywbem_mock/test_wbemconnection_mock.py --- old/pywbem-1.3.0/tests/unittest/pywbem_mock/test_wbemconnection_mock.py 2021-12-09 18:35:17.000000000 +0100 +++ new/pywbem-1.4.1/tests/unittest/pywbem_mock/test_wbemconnection_mock.py 2022-02-01 17:17:43.000000000 +0100 @@ -75,6 +75,8 @@ from pywbem._nocasedict import NocaseDict # noqa: E402 from pywbem._utils import _format # noqa: E402 from pywbem._cim_operations import pull_path_result_tuple # noqa: E402 +from pywbem._warnings import ToleratedSchemaIssueWarning # noqa: E402 + pywbem_mock = import_installed('pywbem_mock') from pywbem_mock import FakedWBEMConnection, DMTFCIMSchema, \ InstanceWriteProvider, MethodProvider, BaseProvider, \ @@ -5762,6 +5764,10 @@ # test_enumerateinstances_pl_di @pytest.mark.parametrize( "ns", INITIAL_NAMESPACES + [None]) + # Define strings to run test with the three operations. This does not + # test the use_pull_operation flag in the connection init. + @pytest.mark.parametrize( + "operation", ['orig', 'pull', 'iter']) @pytest.mark.parametrize( "cln, di, pl, exp_pls", [ @@ -5823,7 +5829,8 @@ ] ) def test_enumerateinstances_pl_di(self, conn, tst_classeswqualifiers, - tst_instances, ns, cln, di, pl, exp_pls): + tst_instances, ns, operation, cln, di, + pl, exp_pls): # pylint: disable=no-self-use """ Test mock EnumerateInstances with namespace as an input @@ -5837,6 +5844,36 @@ DeepInheritance=di, PropertyList=pl) + # The code to be tested + if operation == 'pull': + # The code to be tested when pull used + result_tuple = conn.OpenEnumerateInstances(cln, namespace=ns, + DeepInheritance=di, + PropertyList=pl, + MaxObjectCount=100) + + rslt_insts = result_tuple.instances + + while result_tuple.eos is False: + result_tuple = conn.PullInstancesWithPath( + result_tuple.context, MaxObjectCount=100) + rslt_insts.extend(result_tuple.instances) + + elif operation == 'iter': + rslt_insts = list(conn.IterEnumerateInstances(cln, namespace=ns, + DeepInheritance=di, + PropertyList=pl, + MaxObjectCount=100)) + # iter returns host name with instances but get_instancce + # the compare basis does not. + for inst in rslt_insts: + inst.path.host = None + + elif operation == 'orig': + rslt_insts = conn.EnumerateInstances(cln, namespace=ns, + DeepInheritance=di, + PropertyList=pl) + # If exp_props is dict, test for returned properties by class in # dict. All returned classes must be in dict for inst in rslt_insts: @@ -5851,6 +5888,10 @@ @pytest.mark.parametrize( "ns", INITIAL_NAMESPACES + [None]) + # Define strings to run test with the three operations. This does not + # test the use_pull_operation flag in the connection init. + @pytest.mark.parametrize( + "operation", ['orig', 'pull', 'iter']) @pytest.mark.parametrize( "cln, di, pl, exp_pl, exp_num_insts", [ @@ -5872,18 +5913,44 @@ ] ) def test_enumerateinstances_di(self, conn, tst_classeswqualifiers, - tst_instances, ns, cln, di, pl, exp_pl, - exp_num_insts): + tst_instances, ns, operation, cln, di, pl, + exp_pl, exp_num_insts): # pylint: disable=no-self-use,unused-argument """ Test EnumerateInstances with DeepInheritance and propertylist options. """ add_objects_to_repo(conn, ns, [tst_classeswqualifiers, tst_instances]) - # The code to be tested - rslt_insts = conn.EnumerateInstances(cln, namespace=ns, - DeepInheritance=di, - PropertyList=pl) + if operation == 'pull': + # The code to be tested when pull used + result_tuple = conn.OpenEnumerateInstances(cln, namespace=ns, + DeepInheritance=di, + PropertyList=pl, + MaxObjectCount=100) + + rslt_insts = result_tuple.instances + + while result_tuple.eos is False: + result_tuple = conn.PullInstancesWithPath( + result_tuple.context, MaxObjectCount=100) + rslt_insts.extend(result_tuple.instances) + + elif operation == 'iter': + rslt_insts = list(conn.IterEnumerateInstances(cln, namespace=ns, + DeepInheritance=di, + PropertyList=pl, + MaxObjectCount=100)) + # iter returns host name with instances but get_instancce + # the compare basis does not. + for inst in rslt_insts: + inst.path.host = None + + elif operation == 'orig': + rslt_insts = conn.EnumerateInstances(cln, namespace=ns, + DeepInheritance=di, + PropertyList=pl) + else: + assert False, "Invalid operation parameter for test" assert len(rslt_insts) == exp_num_insts @@ -5924,7 +5991,7 @@ # Test returned inst for equality with instance we built assert exp_inst == inst - # test_enumerateinstances_er + # testenumerate instance errors @pytest.mark.parametrize( "tst_ns, cln, in_ns, exp_exc", [ @@ -6160,10 +6227,11 @@ @pytest.mark.parametrize( "ns", INITIAL_NAMESPACES + [None]) - def test_createinstance_abstract(self, conn, ns): + def test_addinstance_abstract(self, conn, ns): # pylint: disable=no-self-use """ - Test createinstance of an abstract class. This test generates exception + Test createinstance of an abstract class. Does not generate a + warning because the add_objects does not test for abstrace. """ # Create the model environment, qualifier decls and class @@ -6199,24 +6267,82 @@ conn.add_cimobjects([c], namespace=ns) # create the new instance - new_inst = CIMInstance('CIM_AbstractClass', - properties={'InstanceID': "AbstractTestFail"}) + exp_warn_types = None + with pytest.warns(exp_warn_types) as rec_warnings: + new_inst = CIMInstance( + 'CIM_AbstractClass', + properties={'InstanceID': "AbstractTestWarn"}) + new_inst.path = CIMInstanceName( + 'CIM_AbstractClass', namespace=ns, + keybindings={"InstanceID": "AbstractTestWarn"} + ) - # test add a second time. Should generate exception. - with pytest.raises(CIMError) as exec_info: + # NOTE: add_cimobjects does not test for Abstract + conn.add_cimobjects(new_inst, namespace=ns) - # The code to be tested + assert len(rec_warnings) == 0, \ + "Unexpected warn msg {}".format(exp_warn_types) + + @pytest.mark.parametrize( + "ns", INITIAL_NAMESPACES + [None]) + def test_createinstance_abstract(self, conn, ns): + # pylint: disable=no-self-use + """ + Test createinstance of an abstract class. This test generates + a warning + """ + + # Create the model environment, qualifier decls and class + scopesc = NocaseDict([('CLASS', True), ('ASSOCIATION', True), + ('INDICATION', True), ('PROPERTY', False), + ('REFERENCE', False), ('METHOD', False), + ('PARAMETER', False), ('ANY', False)]) + + scopesp = NocaseDict([('CLASS', False), ('ASSOCIATION', False), + ('INDICATION', True), ('PROPERTY', True), + ('REFERENCE', False), ('METHOD', False), + ('PARAMETER', False), ('ANY', False)]) + + q1 = CIMQualifierDeclaration('Abstract', 'boolean', is_array=False, + scopes=scopesc, + overridable=False, tosubclass=True, + toinstance=False, translatable=None) + q2 = CIMQualifierDeclaration('key', 'boolean', is_array=False, + scopes=scopesp, + overridable=False, tosubclass=True, + toinstance=False, translatable=None) + qdecls = [q1, q2] + + c = CIMClass( + 'CIM_AbstractClass', qualifiers={'Abstract': + CIMQualifier('Abstract', True)}, + properties={'InstanceID': + CIMProperty('InstanceID', None, type='string', + qualifiers={'Key': CIMQualifier('Key', + True)})}) + + conn.add_cimobjects(qdecls, namespace=ns) + conn.add_cimobjects([c], namespace=ns) + + # create the new instance + exp_warn_types = ToleratedSchemaIssueWarning + with pytest.warns(exp_warn_types) as rec_warnings: + new_inst = CIMInstance( + 'CIM_AbstractClass', + properties={'InstanceID': "AbstractTestWarn"}) + + # NOTE: add_cimobjects does not test for Abstract conn.CreateInstance(new_inst) - exc = exec_info.value - assert exc.status_code == CIM_ERR_FAILED + assert len(rec_warnings) == 1, \ + "Expected warning(s) missing: {}".format(exp_warn_types) @pytest.mark.parametrize( "ns", INITIAL_NAMESPACES + [None]) def test_compile_inst_abstract(self, conn, ns): # pylint: disable=no-self-use """ - Test compile that has an error compiling instance of abstract class + Test compile generates warning compiling instance of abstract class """ tst_mof = """ Qualifier Abstract : boolean = false, @@ -6228,13 +6354,12 @@ instance of CIM_Abstract {InstanceID="blah";}; """ skip_if_moftab_regenerated() - - with pytest.raises(MOFRepositoryError) as exec_info: - # The code to be tested + exp_warn_types = ToleratedSchemaIssueWarning + with pytest.warns(exp_warn_types) as rec_warnings: conn.compile_mof_string(tst_mof, namespace=ns) - exc = exec_info.value - assert exc.cim_error.status_code == CIM_ERR_FAILED + assert len(rec_warnings) >= 1, \ + "Expected warning(s) missing: {}".format(exp_warn_types) @pytest.mark.parametrize( "interop_ns",
participants (1)
-
Source-Sync