Skip to content

Commit

Permalink
Fix TODO-OLD-PYTHON flagged changes for python 3.8.
Browse files Browse the repository at this point in the history
Fix a number of issues documented as TODO-OLD-PYTHON in the
pr (#3145)  that set new minimum python version to 3.8.

1. Fix issue in cim_http.py, special code for Python < 3.6 by
   removing code.

2. mock/base_repository compatibleabstraceproperty. Remove the
   special function and apply the abstract definitions directly.

3. _recorder.py. Remove use of _longint.

4. _cim_http.py - remove test that was for python < 3.6

5. _cim_obj.py - Remove use of _longint

6. _cim_types -
  - Remove use of _longint.
  - Change text in _CIMComparisonMixin to reflect only python >= 3.8.
  - Remove external  __str__  methods def for CIMInt and CIMFloat
    in favor of __str__ methods in the classes.

7. Change fixed Signature() definition to dynamic signatue().
Removes the fixed Signature definition for simplified_test_function and
replaces it with signature() function that builds the signature.

8. tests/unittest/pywbem/test_cim_obj.py - change test to use int

9. mock tests - Change name of test to avoid duplicate test name and
allow execution of just a single test with name *innvoke_method.
  • Loading branch information
kschopmeyer authored and andy-maier committed May 14, 2024
1 parent 89eccdf commit 608d948
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 138 deletions.
2 changes: 1 addition & 1 deletion docs/mof_compiler.help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,4 @@ General options:
(Default=all)

Example: mof_compiler CIM_Schema_2.45.mof -s https://localhost -n root/cimv2
-u sheldon -p p42
-u sheldon -p 42
4 changes: 0 additions & 4 deletions pywbem/_cim_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,10 +319,6 @@ def pywbem_urllib3_exception(exc, conn):
if m:
exc_name = m.group(1)
exc_message = m.group(2)
if exc_message.endswith(','):
# TODO-OLDPYTHON: Rework
# Python <3.6 represents it as tuple with trailing comma
exc_message = exc_message.rstrip(',')
if exc_message.startswith('"'):
exc_message = exc_message.strip('"')
elif exc_message.startswith("'"):
Expand Down
4 changes: 2 additions & 2 deletions pywbem/_cim_obj.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ class (the parent object) has a list of CIM properties, CIM methods and CIM
from . import config
from ._cim_types import _CIMComparisonMixin, type_from_name, cimtype, \
atomic_to_cim_xml, CIMType, CIMDateTime, number_types, CIMInt, \
CIMFloat, _Longint, Char16, SlottedPickleMixin
CIMFloat, Char16, SlottedPickleMixin
from ._nocasedict import NocaseDict
from ._utils import _ensure_unicode, _ensure_bool, \
_hash_name, _hash_item, _hash_dict, _format, _integerValue_to_int, \
Expand Down Expand Up @@ -2209,7 +2209,7 @@ def case_sorted(keys):
# IEE-754 floating point numbers between decimal and binary
# without loss.
ret.append(repr(value))
elif isinstance(value, (CIMInt, int, _Longint)):
elif isinstance(value, (CIMInt, int)):
# intNN
ret.append(str(value))
elif isinstance(value, CIMInstanceName):
Expand Down
80 changes: 33 additions & 47 deletions pywbem/_cim_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,6 @@
from ._utils import _ensure_unicode, _hash_item, _format, _to_unicode, \
_eq_item


# pylint: disable=invalid-name
_Longint = int


__all__ = ['cimtype', 'type_from_name', 'MinutesFromUTC', 'CIMType',
'CIMDateTime', 'CIMInt', 'Uint8', 'Sint8', 'Uint16', 'Sint16',
'Uint32', 'Sint32', 'Uint64', 'Sint64', 'CIMFloat', 'Real32',
Expand All @@ -98,11 +93,6 @@ class _CIMComparisonMixin: # pylint: disable=too-few-public-methods
The implementations of ordering tests are also provided and raise an
exception because ordering of CIM objects is not supported.
In Python 2, the rich comparison operators (e.g. `__eq__()`) have
precedence over the traditional comparator method (`__cmp__()`).
In Python 3, the comparator method (`__cmp__()`) no longer exists.
Therefore, implementing the rich comparison operators works in both.
"""

__slots__ = []
Expand Down Expand Up @@ -168,23 +158,18 @@ def __hash__(self):

class SlottedPickleMixin:
"""
TODO-OLDPYTHON: Rework
Starting with Python 3.8, the default pickle protocol is protocol 4, which
supports objects with slots by default, without requiring that they define
methods __getstate__() and __setstate__().
On Python 2, the built-in 'pickle' module uses pickle protocol 0 by default.
Using protocol 0 causes pickle to raise TypeError for objects with slots
that do not define methods __getstate__() and __setstate__().
However, objects pickled from Python versions < 3.8 (using the built-in
methods) saved all attributes in one shot by saving their __dict__ value,
so the default unpickling after introduction of slots attempts to set the
__dict__ which fails with AttributeError.
In Python 3.0, the default pickle protocol changed to protocol 3 and in
Python 3.8 to protocol 4, both of which support objects with slots by
default, without requiring that they define methods __getstate__() and
__setstate__().
That led to the idea to provide these methods only when running on
Python 2. However, it turns out that objects pickled before this change
(using the built-in methods) save all attributes in one shot by saving
their __dict__ value, so the default unpickling after introduction of
slots attempts to set the __dict__ which fails with AttributeError.
Therefore, these methods need to be provided also for Python 3.
Therefore, these methods are provided to cover upgrading from use of
objects pickled with python versions older than 3.8 to define __getstate__
and __setstate__.
Also, because code in pywbem_mock/_resolvermixin.py dynamically added
the non-existing attributes 'classorigin' and 'propagated' to CIMClass
Expand Down Expand Up @@ -829,7 +814,7 @@ def __hash__(self):
# CIM integer types


class CIMInt(CIMType, _Longint):
class CIMInt(CIMType, int):
"""
Base type for CIM integer data types. Derived from :class:`~pywbem.CIMType`
and :class:`py3:int` (for Python 3) or :class:`py2:long` (for Python 2).
Expand Down Expand Up @@ -887,19 +872,20 @@ class (e.g. :class:`~pywbem.Uint8`) is created. Values outside of the
maxvalue = None

def __new__(cls, *args, **kwargs):
"" # Avoids docstring to be inherited
"" # Avoids docstring being inherited

# TODO-OLDPYTHON: Rework
# Python 3.7 removed support for passing the value for int() as a
# keyword argument named 'x'. It now needs to be passed as a positional
# argument. The testclient test case definitions rely on a keyword
# argument, so we now transform the keyword arg into a positional
# arg.
# arg. This is used in the invokemethod function tests for
# InvokeMethod Parameter and response return elements.
if 'x' in kwargs:
args = list(*args) # args is passed as a tuple
args.append(kwargs.pop('x'))

value = _Longint(*args, **kwargs)
value = int(*args, **kwargs)
if ENFORCE_INTEGER_RANGE:
if value > cls.maxvalue or value < cls.minvalue:
raise ValueError(
Expand All @@ -908,7 +894,13 @@ def __new__(cls, *args, **kwargs):
# The value needs to be processed here, because int/long is immutable
return super().__new__(cls, *args, **kwargs)

# Note: __str__() is added later, for Python 3.
def __str__(self):
"""
Python 3.8 removed __str__() on int causing recursive loop failures.
The int.__repr__method returns exactly what is needed for a string
representation.
"""
return f"{int.__repr__(self)}"

def __repr__(self):
"""
Expand All @@ -917,8 +909,8 @@ def __repr__(self):
return _format(
"{s.__class__.__name__}("
"cimtype={s.cimtype!A}, "
"minvalue={s.minvalue}, " # Avoid long indicator 'L' in Python 2
"maxvalue={s.maxvalue}, " # Avoid long indicator 'L' in Python 2
"minvalue={s.minvalue}, "
"maxvalue={s.maxvalue}, "
"{s})",
s=self)

Expand Down Expand Up @@ -1085,7 +1077,15 @@ class CIMFloat(CIMType, float):

__slots__ = []

# Note: __str__() is added later, for Python 3.
def __str__(self):
"""
Return a string representation of the value. Python 3.8 removed
__str__() on float causing an infinite recursion for the CIMInt and
class whose __repr__() calls __str__() on itself. The
float.__repr__method returns exactly what is needed for a string
representation.
"""
return float.__repr__(self)

def __repr__(self):
"""Return a string representation suitable for debugging."""
Expand Down Expand Up @@ -1130,20 +1130,6 @@ class Real64(CIMFloat):
number_types = (int, float) # pylint: disable=invalid-name


# TODO-OLDPYTHON: Rework
# Python 3.8 removed __str__() on int and float and thereby caused an infinite
# recursion for the CIMInt and CIMFloat classes whose __repr__() calls
# __str__() on itself.
# The following addresses that by implementing __str__() on these classes,
# representing the values using int/float.__repr__(). In Python 3, these
# methods return exactly what is needed for a string representation. Note that
# in Python 2, repr(long) has a trailing 'L' which would not be suitable.
CIMInt.__str__ = int.__repr__
CIMFloat.__str__ = float.__repr__
# MinutesFromUTC.__repr__() does not call str() on itself
# CIMDatetime has its own __str__()


def cimtype(obj):
"""
Return the CIM data type name of a CIM typed object, as a string.
Expand Down
17 changes: 3 additions & 14 deletions pywbem/_recorder.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@
'LogOperationRecorder',
'OpArgs', 'OpResult', 'HttpRequest', 'HttpResponse']

# pylint: disable=invalid-name
_Longint = int

OpArgsTuple = namedtuple("OpArgsTuple", ["method", "args"])

Expand Down Expand Up @@ -582,9 +580,8 @@ def stage_pywbem_args(self, method, **kwargs):
if self.enabled and self.api_detail_level is not None and \
self.apilogger.isEnabledFor(logging.DEBUG):

# Order kwargs. Note that this is done automatically starting
# with python 3.6
# TODO-OLDPYTHON: Rework
# Order kwargs.
# Sort required to pass tests. Ordering issue without this sort.
kwstr = ', '.join([(f'{key}={kwargs[key]!r}')
for key in sorted(kwargs.keys())])

Expand Down Expand Up @@ -994,16 +991,8 @@ def toyaml(self, obj):
# bool is a subclass of int in Python.
return obj
if isinstance(obj, CIMInt):
# TODO-OLDPYTHON: Resolve
# CIMInt is _Longint and therefore may exceed the value range of
# int in Python 2. Therefore, we convert it to _Longint.
return _Longint(obj)
return int(obj)
if isinstance(obj, int):
# TODO-OLDPYTHON: Resolve
# This case must be after CIMInt, because CIMInt is _Longint and
# would match a long value in Python 2.
# We don't convert int to _Longint, because the value
# fits into the provided type, and there is no need to convert it.
return obj
if isinstance(obj, CIMFloat):
return float(obj)
Expand Down
17 changes: 2 additions & 15 deletions pywbem_mock/_baserepository.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,6 @@
__all__ = ['BaseObjectStore', 'BaseRepository']


def compatibleabstractproperty(func):
"""
TODO-OLDPYTHON: Resolve
Python 2 and python 3 differ in decorator for abstract property.
in python 3 (gt 3.3) it is:
@property
@abstractproperty
in python 2
@abstractproperty
"""

return property(abstractmethod(func))


class BaseObjectStore:
"""
An abstract class that defines the APIs for the methods of an object store
Expand Down Expand Up @@ -271,7 +257,8 @@ class BaseRepository:
CIM objects of a single CIM type by namespace in the repository.
"""

@compatibleabstractproperty
@property
@abstractmethod
def namespaces(self):
"""
:term:`NocaseList` of :term:`string`:
Expand Down
2 changes: 1 addition & 1 deletion tests/functiontest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -311,5 +311,5 @@ Elements in `http_response` element

* `data`:
The CIM-XML payload in the HTTP response handed back to the PyWBEM
client. The CIm-XML is handed back as resulting from the specified
client. The CIM-XML is handed back as resulting from the specified
YAML, including any whitespace.

0 comments on commit 608d948

Please sign in to comment.