Skip to content

Commit

Permalink
Improved checks and conversions when setting attributes in cim_obj.py.
Browse files Browse the repository at this point in the history
The motivation for this change is:

1. The constructor parameters are subject to certain checks and automatic
   conversions. The instance attributes can be modified through their setter
   methods, but currently they only store the provided values. It would be
   more consistent if the same checks and automatic conversions would be
   performed by the setter methods, as in the constructor.
   This contributes also to addressing issue 746.

Details:

* Updating attributes of objects of CIM object classes (e.g. updating
  the `value` attribute of a `CIMProperty` object) now applies the same
  conversions and nearly the same checks as for the same-named
  constructor parameters.

* Changed parameter/attribute conversions and checks in applicable CIM
  object classes (from `CIMInstanceName`, `CIMInstance`, `CIMClassName`,
  `CIMClass`, `CIMProperty`, `CIMMethod`, `CIMParameter`, `CIMQualifier`,
  `CIMQualifierDeclaration`) as follows:

  - For classes with a `classname` parameter/attribute (i.e.
    `CIMInstanceName`, `CIMInstance`, `CIMClassName`, `CIMClass`),
    the requirement for the `classname` parameter/attribute not to be
    `None` that had previously been documented is now enforced by
    raising `ValueError`  both when initializing an object and when
    setting the `classname` attribute.

    Previously, `None` for the classname was tolerated for all classes
    when setting the attribute, and for `CIMInstance` and `CIMClass`
    when initializing an object, and `CIMClassName` and `CIMInstanceName`
    raised `TypeError` when it was `None`.

  - For classes with a `name` parameter/attribute (i.e. `CIMProperty`,
    `CIMMethod`, `CIMParameter`, `CIMQualifier`,
    `CIMQualifierDeclaration`), the requirement for the `name`
    parameter/attribute not to be `None` that had previously been
    documented is now enforced by raising `ValueError` both when
    initializing an object and when setting the `name` attribute.

    Previously, initializing an object with `None` for the name was
    tolerated in `CIMParameter`, `CIMQualifier`, and
    `CIMQualifierDeclaration`, caused `TypeError` to be raised in
    `CIMMethod` (and caused `ValueError` to be raised in `CIMProperty`
    like now). Setting the `name` atribute to `None` was tolerated
    by all those classes.

  - When initializing objects of classes with an optional `type`
    parameter and a `value` parameter (i.e. `CIMProperty`,
    `CIMQualifier`), the type is now inferred from the `value` parameter,
    if the type is `None`. If that is not possible (for example because
    the value is a Python integer, float or `None`), `ValueError` is
    raised. When setting the `type` attribute, no inferring from `value`
    is performed.

    Previously, inferring the type was implemented only for initializing
    `CIMProperty` and `CIMQualifier`, and `TypeError` was raised if the
    type could not be inferred. In all other cases, a type of `None` was
    tolerated.

  - For classes with a required `type` parameter (i.e. `CIMParameter`,
    `CIMQualifierDeclaration`), the `type` parameter is now enforced not
    to be `None` both when initializing an object and when setting the
    attribute, and `ValueError` is raised if it is `None`.

    Previously, this was tolerated and the resulting object had a type
    of `None`.

  - For classes with a `value` parameter/attribute (i.e. `CIMProperty`,
    `CIMParameter`, `CIMQualifier`, `CIMQualifierDeclaration`), the
    provided value is now guaranteed to be converted to a CIM data type,
    both when initializing an object and when setting the attribute.

    Previously, strings have been converted to unicode, but all other
    values were stored as provided, resulting in values that were not
    CIM data types.

  - For classes with an `is_array` parameter/attribute (i.e.
    `CIMProperty`, `CIMParameter`, `CIMQualifierDeclaration`, that
    attribute is now inferred (if passed as `None`) from whether the
    `value` attribute is a list.

    Previously, that was done only for `CIMProperty`, and it was
    required to be provided for the other classes.

  - For parameters/attributes that are dictionaries (`properties`,
    `keybindings`, `parameters`, `qualifiers`), the consistency between
    the dict keys and the names of the CIM elements that are the dict
    values is now enforced (case insensitively) and `ValueError` is
    raised in case of inconsistencies. Added `_cim_keybinding()`,
    `_cim_property_value()`, `_cim_property_decl()`, `_cim_method()`,
    and `_cim_qualifier()` in support of that.

    Previously, such inconsistencies were tolerated.

  - Boolean parameters/attributes (e.g. `is_array`) are now converted
    to `bool` type unless they are `None`. Added `_ensure_bool()` in
    support of that.

    Previously, the provided value was stored, resulting in non-bool values
    for these attributes.

* For `CIMInstanceName`, specifying input keybindings as Python numeric types
  (`int`, `float`) has been deprecated, and an according deprecation warning
  will now be raised. These types had previously been documented to be
  invalid.

* For `CIMInstanceName`, the keybindings can now be specified as
  `CIMProperty` objects from which their value will be used (this is in
  addition to specfying the values of keybindings as CIM data types).

* Added static `from_wbem_uri()` methods to `CIMInstanceName` and
  `CIMClassName`, that create a new object of these classes from a
  WBEM URI string.

* Docs: Added examples for constructing `CIMQualifier` objects
  to the documentation of its init function.

* Test: Added and changed testcases in test_cim_obj.py to accomodate
  the new behaviors of CIM object classes.

* Test: Added the examples documented for `CIMProperty` and `CIMQualifier`
  as tests.

* Test: Improved the assertion output in unittest_extensions.py by removing
  the fixed messages that did not really help.

* Test: In test_cim_obj.py, now using unittest2 because we started
  using `assertRaises()` as a context manager. This was introduced
  into unittest only in Python 2.7.

Signed-off-by: Andreas Maier <maiera@de.ibm.com>
  • Loading branch information
andy-maier committed Nov 8, 2017
1 parent 3997464 commit 34167ca
Show file tree
Hide file tree
Showing 8 changed files with 1,922 additions and 742 deletions.
97 changes: 96 additions & 1 deletion docs/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,106 @@ Released: Not yet
Incompatible changes
^^^^^^^^^^^^^^^^^^^^

* The following initialization parameters of some CIM object classes that are
required not to be `None` (as per the documentation) are now enforced not to
be `None`, and `ValueError` is now raised when providing them as `None`:

- `CIMInstanceName.classname` (already raised `ValueError`)
- `CIMInstance.classname`
- `CIMClassName.classname` (previously raised `TypeError`)
- `CIMClass.classname`
- `CIMProperty.name` (already raised `ValueError`)
- `CIMMethod.name` (previously raised `TypeError`)
- `CIMParameter.name`
- `CIMParameter.type`
- `CIMQualifier.name`
- `CIMQualifierDeclaration.name`
- `CIMQualifierDeclaration.type`

Unless otherwise noted, the previous behavior was to tolerate `None`.

Note that in all cases, the requirement not to be `None` had previously been
documented.

* When setting some attributes of CIM object classes that are required not to
be `None` (as per the documentation), `ValueError` is now raised when
attempting to set them to `None`:

- `CIMInstanceName.classname`
- `CIMInstance.classname`
- `CIMClassName.classname`
- `CIMClass.classname`
- `CIMProperty.name`
- `CIMMethod.name`
- `CIMParameter.name`
- `CIMParameter.type`
- `CIMQualifier.name`
- `CIMQualifierDeclaration.name`
- `CIMQualifierDeclaration.type`

The previous behavior was to tolerate `None`.

Note that in all cases, the requirement not to be `None` had previously been
documented.

* When initializing objects of the CIM object classes `CIMProperty` and
`CIMQualifier` with a `type` parameter of `None`, and when initializing
the properties of `CIMInstance`, their CIM type is (and has previously been)
inferred from the value.

If inferring the type is not possible (for example because the value is a
Python integer, float, long (Python 2 only), or `None`), the exception that
is raised is now `ValueError`. Previously, `TypeError` was raised in that
case.

* When setting the `type` attribute of the CIM object classes `CIMProperty` and
`CIMQualifier`, the type is now enforced not to be `None`, and `ValueError`
is raised when providing it as `None`.

Previously, setting a type of `None` was tolerated.

Note that in both cases, the requirement not to be `None` had previously been
documented.

* For CIM elements passed as dictionaries into CIM object classes (i.e.
the aparameters/attributes `properties`, `keybindings`, `parameters`,
`qualifiers`), the consistency between the dictionary key and the name of the
CIM object that is the dictionary value is now checked and `ValueError` is
raised if it does not match (case insensitively).

* Initializing a `CIMProperty` object as an embedded object or embedded
instance and with a value of `None` now requires specifying `type="string"`.

Previously (but only starting with pywbem v0.8.1), the type was inferred from
the `embedded_instance` parameter and thus could be omitted. This new
requirement for specifying `type` is not really intentional, but a by-product
of simplifying the implementation of `CIMProperty`. It was considered
acceptable because that should not be a common case (and has not been
supported before pywbem v0.8.1 anyway).

Deprecations
^^^^^^^^^^^^

* For `CIMInstanceName`, specifying input keybindings as Python numeric types
(`int`, `float`) has been deprecated, and an according deprecation warning
will now be raised.

Enhancements
^^^^^^^^^^^^

* For `CIMInstanceName`, the values of keybindings can now be specified as
`CIMProperty` objects from which their value will be used (this is in
addition to specfying the values of keybindings as CIM data types).

* Updating attributes of CIM objects (e.g. updating `CIMInstance.properties`)
now goes through the same conversions (e.g. binary string to unicode string)
as for the same-named constructor parameters. As a result, it is ensured
that all attributes that are strings (e.g. `name`) contain unicode strings,
all attributes that are booleans (e.g. `propagated`) contain bool values,
and all CIM values (e.g. `CIMProperty.value`) are of a :term:`CIM data type`.

* Changed public attributes to properties with getter and setter in all CIM
object classes (e.g. `CIMInstance`). This solves the Sphinx warnigs about
object classes (e.g. `CIMInstance`). This solves the Sphinx warnings about
duplicate 'host' attribute when building the documentation (issue #761).

* Docs: Editorial improvements in the documentation (links, typos, formatting).
Expand Down
2 changes: 2 additions & 0 deletions docs/client.rst
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ such as debugging.

.. autofunction:: pywbem.tocimobj

.. autofunction:: pywbem.cimvalue

.. _`CIM data types`:

CIM data types
Expand Down
Loading

0 comments on commit 34167ca

Please sign in to comment.