Hello community,

here is the log from the commit of package python-pyghmi for openSUSE:Factory 
checked in at 2018-09-07 15:39:28
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pyghmi (Old)
 and      /work/SRC/openSUSE:Factory/.python-pyghmi.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pyghmi"

Fri Sep  7 15:39:28 2018 rev:10 rq:633117 version:1.1.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pyghmi/python-pyghmi.changes      
2018-04-30 22:53:20.264723250 +0200
+++ /work/SRC/openSUSE:Factory/.python-pyghmi.new/python-pyghmi.changes 
2018-09-07 15:39:29.502530490 +0200
@@ -1,0 +2,24 @@
+Tue Sep  4 08:05:43 UTC 2018 - cloud-de...@suse.de
+
+- update to version 1.1.0
+  - Support '=' as a list delimiter
+  - Do not run functional (API) tests in the CI
+  - Switch the dsvm job to the "ipmi" hardware type
+  - Prefer cyrptodomex if present
+  - add lower-constraints
+  - Add hostname for FPC and XCC
+  - Normalize spaces in values and candidates
+  - Handle missing properties
+  - Fix SMM updates on newer SMM firmware versions
+  - Improve performance of get_health for XCC
+  - Error on invalid signature
+  - More informative message on password expiry
+  - Update to newer hacking
+  - Get additional enclosure data
+  - Revise the FPC fix
+  - Have logged set to 0 early
+  - Check the status for no power permission
+  - Fix duplicate adapter name handling
+  - Migrate from PyCrypto to Cryptography
+
+-------------------------------------------------------------------

Old:
----
  pyghmi-1.0.44.tar.gz

New:
----
  pyghmi-1.1.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pyghmi.spec ++++++
--- /var/tmp/diff_new_pack.Oznfhq/_old  2018-09-07 15:39:29.946530014 +0200
+++ /var/tmp/diff_new_pack.Oznfhq/_new  2018-09-07 15:39:29.950530009 +0200
@@ -17,21 +17,23 @@
 
 
 Name:           python-pyghmi
-Version:        1.0.44
+Version:        1.1.0
 Release:        0
 Summary:        General Hardware Management Initiative (IPMI and others)
 License:        Apache-2.0
 Group:          Development/Languages/Python
 URL:            https://launchpad.net/pyghmi
-Source0:        
https://files.pythonhosted.org/packages/source/p/pyghmi/pyghmi-1.0.44.tar.gz
+Source0:        
https://files.pythonhosted.org/packages/source/p/pyghmi/pyghmi-1.1.0.tar.gz
 BuildRequires:  openstack-macros
 BuildRequires:  python-devel
-BuildRequires:  python2-oslotest >= 3.2.0
-BuildRequires:  python2-pycrypto >= 2.6
+BuildRequires:  python2-cryptography >= 2.1
+BuildRequires:  python2-oslotest
+BuildRequires:  python2-testrepository
+BuildRequires:  python3-cryptography >= 2.1
 BuildRequires:  python3-devel
-BuildRequires:  python3-oslotest >= 3.2.0
-BuildRequires:  python3-pycrypto >= 2.6
-Requires:       python-pycrypto >= 2.6
+BuildRequires:  python3-oslotest
+BuildRequires:  python3-testrepository
+Requires:       python-cryptography >= 2.1
 BuildArch:      noarch
 %if 0%{?suse_version}
 Requires(post): update-alternatives
@@ -53,7 +55,6 @@
 Summary:        General Hardware Management Initiative (IPMI and others) -- 
Documentation
 Group:          Documentation/HTML
 BuildRequires:  python-Sphinx
-BuildRequires:  python-openstackdocstheme >= 1.18.1
 
 %description -n python-pyghmi-doc
 This is a pure python implementation of IPMI protocol.

++++++ _service ++++++
--- /var/tmp/diff_new_pack.Oznfhq/_old  2018-09-07 15:39:29.970529988 +0200
+++ /var/tmp/diff_new_pack.Oznfhq/_new  2018-09-07 15:39:29.974529984 +0200
@@ -1,8 +1,8 @@
 <services>
   <service mode="disabled" name="renderspec">
-    <param 
name="input-template">https://raw.githubusercontent.com/openstack/rpm-packaging/master/openstack/pyghmi/pyghmi.spec.j2</param>
+    <param 
name="input-template">https://raw.githubusercontent.com/openstack/rpm-packaging/stable/rocky/openstack/pyghmi/pyghmi.spec.j2</param>
     <param name="output-name">python-pyghmi.spec</param>
-    <param 
name="requirements">https://raw.githubusercontent.com/openstack/rpm-packaging/master/requirements.txt</param>
+    <param 
name="requirements">https://raw.githubusercontent.com/openstack/pyghmi/master/requirements.txt</param>
     <param name="changelog-email">cloud-de...@suse.de</param>
     <param name="changelog-provider">gh,openstack,pyghmi</param>
   </service>

++++++ pyghmi-1.0.44.tar.gz -> pyghmi-1.1.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/.zuul.yaml new/pyghmi-1.1.0/.zuul.yaml
--- old/pyghmi-1.0.44/.zuul.yaml        2018-04-10 16:27:36.000000000 +0200
+++ new/pyghmi-1.1.0/.zuul.yaml 2018-05-22 20:15:14.000000000 +0200
@@ -1,30 +0,0 @@
-- project:
-    check:
-      jobs:
-        - pyghmi-tempest-devstack-ironic-pxe_ipmitool-src:
-            irrelevant-files:
-              - ^(test-|)requirements.txt$
-              - ^setup.cfg$
-    gate:
-      jobs:
-        - pyghmi-tempest-devstack-ironic-pxe_ipmitool-src:
-            irrelevant-files:
-              - ^(test-|)requirements.txt$
-              - ^setup.cfg$
-
-- job:
-    name: pyghmi-tempest-devstack-ironic-pxe_ipmitool-src
-    parent: legacy-dsvm-base
-    run: 
playbooks/legacy/tempest-devstack-ironic-pxe_ipmitool-pyghmi-src/run.yaml
-    post-run: 
playbooks/legacy/tempest-devstack-ironic-pxe_ipmitool-pyghmi-src/post.yaml
-    timeout: 10800
-    required-projects:
-      - openstack-infra/devstack-gate
-      - openstack/ironic
-      - openstack/ironic-lib
-      - openstack/ironic-python-agent
-      - openstack/ironic-tempest-plugin
-      - openstack/pyghmi
-      - openstack/python-ironicclient
-      - openstack/tempest
-      - openstack/virtualbmc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/AUTHORS new/pyghmi-1.1.0/AUTHORS
--- old/pyghmi-1.0.44/AUTHORS   2018-04-10 16:30:46.000000000 +0200
+++ new/pyghmi-1.1.0/AUTHORS    2018-05-22 20:18:09.000000000 +0200
@@ -3,8 +3,10 @@
 Andreas Jaeger <a...@suse.com>
 Derek Higgins <der...@redhat.com>
 Devananda van der Veen <devananda....@gmail.com>
+Dmitry Tantsur <divius.ins...@gmail.com>
 Fabio Dassan <fdas...@lenovo.com>
 Fengqian Gao <fengqian....@intel.com>
+Ilya Etingof <etin...@gmail.com>
 James E. Blair <jebl...@redhat.com>
 Jarrod Johnon <jbjoh...@us.ibm.com>
 Jarrod Johnon <jjohns...@lenovo.com>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/ChangeLog new/pyghmi-1.1.0/ChangeLog
--- old/pyghmi-1.0.44/ChangeLog 2018-04-10 16:30:46.000000000 +0200
+++ new/pyghmi-1.1.0/ChangeLog  2018-05-22 20:18:09.000000000 +0200
@@ -1,6 +1,29 @@
 CHANGES
 =======
 
+1.1.0
+-----
+
+* Migrate from PyCrypto to Cryptography
+* Error on invalid signature
+* Fix SMM updates on newer SMM firmware versions
+* More informative message on password expiry
+* Fix duplicate adapter name handling
+* add lower-constraints
+* Handle missing properties
+* Update to newer hacking
+* Do not run functional (API) tests in the CI
+* Support '=' as a list delimiter
+* Normalize spaces in values and candidates
+* Revise the FPC fix
+* Check the status for no power permission
+* Prefer cyrptodomex if present
+* Add hostname for FPC and XCC
+* Improve performance of get\_health for XCC
+* Have logged set to 0 early
+* Switch the dsvm job to the "ipmi" hardware type
+* Get additional enclosure data
+
 1.0.44
 ------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/PKG-INFO new/pyghmi-1.1.0/PKG-INFO
--- old/pyghmi-1.0.44/PKG-INFO  2018-04-10 16:30:46.000000000 +0200
+++ new/pyghmi-1.1.0/PKG-INFO   2018-05-22 20:18:10.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: pyghmi
-Version: 1.0.44
+Version: 1.1.0
 Summary: Python General Hardware Management Initiative (IPMI and others)
 Home-page: http://github.com/openstack/pyghmi/
 Author: Jarrod Johnson
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/bin/fakebmc 
new/pyghmi-1.1.0/bin/fakebmc
--- old/pyghmi-1.0.44/bin/fakebmc       2018-04-10 16:27:36.000000000 +0200
+++ new/pyghmi-1.1.0/bin/fakebmc        2018-05-22 20:15:14.000000000 +0200
@@ -12,7 +12,7 @@
 # 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.
-__author__ = 'jjohns...@lenovo.com'
+# __author__ = 'jjohns...@lenovo.com'
 
 # this is a quick sample of how to write something that acts like a bmc
 # to play:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/bin/pyghmicons 
new/pyghmi-1.1.0/bin/pyghmicons
--- old/pyghmi-1.0.44/bin/pyghmicons    2018-04-10 16:27:36.000000000 +0200
+++ new/pyghmi-1.1.0/bin/pyghmicons     2018-05-22 20:15:14.000000000 +0200
@@ -13,12 +13,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-"""
-@author: Jarrod Johnson <jbjoh...@us.ibm.com>
-"""
-
-"""A simple little script to exemplify/test ipmi.console module
-"""
+# """
+# @author: Jarrod Johnson <jbjoh...@us.ibm.com>
+# """
+#
+# """A simple little script to exemplify/test ipmi.console module
+# """
 import fcntl
 import os
 import select
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/bin/pyghmiutil 
new/pyghmi-1.1.0/bin/pyghmiutil
--- old/pyghmi-1.0.44/bin/pyghmiutil    2018-04-10 16:27:36.000000000 +0200
+++ new/pyghmi-1.1.0/bin/pyghmiutil     2018-05-22 20:15:14.000000000 +0200
@@ -12,14 +12,14 @@
 # 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.
-"""
-@author: Jarrod Johnson <jbjoh...@us.ibm.com>
-"""
+# """
+# @author: Jarrod Johnson <jbjoh...@us.ibm.com>
+# """
 
-"""This is an example of using the library in a synchronous fashion. For now,
-it isn't conceived as a general utility to actually use, just help developers
-understand how the ipmi_command class workes.
-"""
+# """This is an example of using the library in a synchronous fashion. For now,
+# it isn't conceived as a general utility to actually use, just help developers
+# understand how the ipmi_command class workes.
+# """
 import os
 import string
 import sys
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/bin/virshbmc 
new/pyghmi-1.1.0/bin/virshbmc
--- old/pyghmi-1.0.44/bin/virshbmc      2018-04-10 16:27:36.000000000 +0200
+++ new/pyghmi-1.1.0/bin/virshbmc       2018-05-22 20:15:14.000000000 +0200
@@ -12,7 +12,7 @@
 # limitations under the License.
 
 # Written by pmartini2, but mostly a clone of fakebmc, written by jjohnson2
-__author__ = 'pmarti...@bloomberg.net'
+# __author__ = 'pmarti...@bloomberg.net'
 
 # This is a simple, but working proof of concept of using pyghmi.ipmi.bmc to
 # control a VM
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/lower-constraints.txt 
new/pyghmi-1.1.0/lower-constraints.txt
--- old/pyghmi-1.0.44/lower-constraints.txt     1970-01-01 01:00:00.000000000 
+0100
+++ new/pyghmi-1.1.0/lower-constraints.txt      2018-05-22 20:15:14.000000000 
+0200
@@ -0,0 +1,10 @@
+coverage===4.0
+cryptography===2.1
+fixtures===3.0.0
+oslotest===3.2.0
+os-testr===1.0.0
+python-subunit===1.0.0
+Sphinx===1.6.5
+testrepository===0.0.18
+testscenarios===0.4
+testtools===2.2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pyghmi-1.0.44/playbooks/legacy/tempest-devstack-ironic-pxe_ipmitool-pyghmi-src/run.yaml
 
new/pyghmi-1.1.0/playbooks/legacy/tempest-devstack-ironic-pxe_ipmitool-pyghmi-src/run.yaml
--- 
old/pyghmi-1.0.44/playbooks/legacy/tempest-devstack-ironic-pxe_ipmitool-pyghmi-src/run.yaml
 2018-04-10 16:27:58.000000000 +0200
+++ 
new/pyghmi-1.1.0/playbooks/legacy/tempest-devstack-ironic-pxe_ipmitool-pyghmi-src/run.yaml
  2018-05-22 20:15:14.000000000 +0200
@@ -53,7 +53,7 @@
     - shell:
         cmd: |
           cat << 'EOF' >> ironic-extra-vars
-            export DEVSTACK_GATE_TEMPEST_REGEX="ironic"
+            export 
DEVSTACK_GATE_TEMPEST_REGEX="ironic_tempest_plugin.tests.scenario"
 
           EOF
         chdir: '{{ ansible_user_dir }}/workspace'
@@ -96,7 +96,7 @@
           export DEVSTACK_GATE_NEUTRON=1
           export DEVSTACK_GATE_VIRT_DRIVER=ironic
           export DEVSTACK_GATE_CONFIGDRIVE=1
-          export DEVSTACK_GATE_IRONIC_DRIVER=pxe_ipmitool
+          export DEVSTACK_GATE_IRONIC_DRIVER=ipmi
           export BRANCH_OVERRIDE=default
           if [ "$BRANCH_OVERRIDE" != "default" ] ; then
               export OVERRIDE_ZUUL_BRANCH=$BRANCH_OVERRIDE
@@ -106,17 +106,6 @@
               export DEVSTACK_GATE_TLSPROXY=1
           fi
 
-          if [ "pxe_ipmitool" == "pxe_snmp" ] ; then
-              # explicitly enable pxe_snmp driver
-              export 
DEVSTACK_LOCAL_CONFIG+=$'\n'"IRONIC_ENABLED_DRIVERS=fake,pxe_snmp"
-          fi
-
-          if [ "pxe_ipmitool" == "redfish" ] ; then
-              # When deploying with redfish we need to enable the "redfish"
-              # hardware type
-              export 
DEVSTACK_LOCAL_CONFIG+=$'\n'"IRONIC_ENABLED_HARDWARE_TYPES=redfish"
-          fi
-
           if [ "partition" == "wholedisk" ] ; then
             export 
DEVSTACK_LOCAL_CONFIG+=$'\n'"IRONIC_TEMPEST_WHOLE_DISK_IMAGE=True"
             export DEVSTACK_LOCAL_CONFIG+=$'\n'"IRONIC_VM_EPHEMERAL_DISK=0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/pyghmi/exceptions.py 
new/pyghmi-1.1.0/pyghmi/exceptions.py
--- old/pyghmi-1.0.44/pyghmi/exceptions.py      2018-04-10 16:27:58.000000000 
+0200
+++ new/pyghmi-1.1.0/pyghmi/exceptions.py       2018-05-22 20:15:14.000000000 
+0200
@@ -54,3 +54,9 @@
     # Indicates when functionality is requested that is not supported by
     # current endpoint
     pass
+
+
+class BypassGenericBehavior(PyghmiException):
+    # Indicates that an OEM handler wants to abort any standards based
+    # follow up
+    pass
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/pyghmi/ipmi/command.py 
new/pyghmi-1.1.0/pyghmi/ipmi/command.py
--- old/pyghmi-1.0.44/pyghmi/ipmi/command.py    2018-04-10 16:27:58.000000000 
+0200
+++ new/pyghmi-1.1.0/pyghmi/ipmi/command.py     2018-05-22 20:15:14.000000000 
+0200
@@ -657,10 +657,15 @@
         warning, critical, or failed assessments.
         """
         summary = {'badreadings': [], 'health': const.Health.Ok}
-        for reading in self.get_sensor_data():
-            if reading.health != const.Health.Ok:
-                summary['health'] |= reading.health
-                summary['badreadings'].append(reading)
+        try:
+            self.oem_init()
+            self._oem.get_health(summary)
+            for reading in self.get_sensor_data():
+                if reading.health != const.Health.Ok:
+                    summary['health'] |= reading.health
+                    summary['badreadings'].append(reading)
+        except exc.BypassGenericBehavior:
+            pass
         return summary
 
     def get_sensor_reading(self, sensorname):
@@ -1137,6 +1142,23 @@
         if not ip == '0.0.0.0':
             self._assure_alert_policy(channel, destination)
 
+    def get_hostname(self):
+        """Get the hostname used by the BMC in various contexts
+
+        This can vary somewhat in interpretation, but generally speaking
+        this should be the name that shows up on UIs and in DHCP requests and
+        DNS registration requests, as applicable.
+
+        :return: current hostname
+        """
+        self.oem_init()
+        try:
+            return self._oem.get_hostname()
+        except exc.UnsupportedFunctionality:
+            # Use the DCMI MCI field as a fallback, since it's the closest
+            # thing in the IPMI Spec for this
+            return self.get_mci()
+
     def get_mci(self):
         """Get the Management Controller Identifier, per DCMI specification
 
@@ -1144,6 +1166,20 @@
         """
         return self._chunkwise_dcmi_fetch(9)
 
+    def set_hostname(self, hostname):
+        """Set the hostname to be used by the BMC in various contexts.
+
+        See get_hostname for details
+
+        :param hostname: The hostname to set
+        :return: Nothing
+        """
+        self.oem_init()
+        try:
+            return self._oem.set_hostname(hostname)
+        except exc.UnsupportedFunctionality:
+            return self.set_mci(hostname)
+
     def set_mci(self, mci):
         """Set the management controller identifier, per DCMI specification
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/pyghmi/ipmi/oem/generic.py 
new/pyghmi-1.1.0/pyghmi/ipmi/oem/generic.py
--- old/pyghmi-1.0.44/pyghmi/ipmi/oem/generic.py        2018-04-10 
16:27:58.000000000 +0200
+++ new/pyghmi-1.1.0/pyghmi/ipmi/oem/generic.py 2018-05-22 20:15:14.000000000 
+0200
@@ -265,6 +265,31 @@
         """
         raise exc.UnsupportedFunctionality()
 
+    def get_health(self, summary):
+        """Provide an alternative or augmented health assessment
+
+        An OEM handler can preprocess the summary and extend it with OEM
+        specific data, and then return to let generic processing occur.
+        It can also raise the pyghmi exception BypassGenericBehavior to
+        suppress the standards based routine, for enhanced performance.
+
+        :param summary: The health summary as prepared by the generic function
+        :return: Nothing, modifies the summary object
+        """
+        return
+
+    def set_hostname(self, hostname):
+        """OEM specific hook to specify name information
+
+        """
+        raise exc.UnsupportedFunctionality()
+
+    def get_hostname(self):
+        """OEM specific hook to specify name information
+
+        """
+        raise exc.UnsupportedFunctionality()
+
     def set_alert_ipv6_destination(self, ip, destination, channel):
         """Set an IPv6 alert destination
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/pyghmi/ipmi/oem/lenovo/handler.py 
new/pyghmi-1.1.0/pyghmi/ipmi/oem/lenovo/handler.py
--- old/pyghmi-1.0.44/pyghmi/ipmi/oem/lenovo/handler.py 2018-04-10 
16:27:58.000000000 +0200
+++ new/pyghmi-1.1.0/pyghmi/ipmi/oem/lenovo/handler.py  2018-05-22 
20:15:14.000000000 +0200
@@ -652,6 +652,8 @@
                                                 data=(4, i))
                 name += rsp['data'][:]
             return name.rstrip('\x00')
+        elif self.is_fpc:
+            return self.smmhandler.get_domain()
 
     def set_oem_domain_name(self, name):
         if self.has_tsm:
@@ -669,6 +671,22 @@
 
             self._restart_dns()
             return
+        elif self.is_fpc:
+            self.smmhandler.set_domain(name)
+
+    def set_hostname(self, hostname):
+        if self.is_fpc:
+            return self.smmhandler.set_hostname(hostname)
+        elif self.has_xcc:
+            return self.immhandler.set_hostname(hostname)
+        return super(OEMHandler, self).set_hostname(hostname)
+
+    def get_hostname(self):
+        if self.is_fpc:
+            return self.smmhandler.get_hostname()
+        elif self.has_xcc:
+            return self.immhandler.get_hostname()
+        return super(OEMHandler, self).get_hostname()
 
     """ Gets a remote console launcher for a Lenovo ThinkServer.
 
@@ -923,3 +941,8 @@
         if self.has_xcc:
             return self.immhandler.list_media()
         return super(OEMHandler, self).list_media()
+
+    def get_health(self, summary):
+        if self.has_xcc:
+            return self.immhandler.get_health(summary)
+        return super(OEMHandler, self).get_health(summary)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/pyghmi/ipmi/oem/lenovo/imm.py 
new/pyghmi-1.1.0/pyghmi/ipmi/oem/lenovo/imm.py
--- old/pyghmi-1.0.44/pyghmi/ipmi/oem/lenovo/imm.py     2018-04-10 
16:27:58.000000000 +0200
+++ new/pyghmi-1.1.0/pyghmi/ipmi/oem/lenovo/imm.py      2018-05-22 
20:15:14.000000000 +0200
@@ -29,6 +29,7 @@
 import pyghmi.storage as storage
 import pyghmi.util.webclient as webclient
 import random
+import re
 import socket
 import struct
 import threading
@@ -36,6 +37,32 @@
 import weakref
 
 
+numregex = re.compile('([0-9]+)')
+
+
+def naturalize_string(key):
+    """Analyzes string in a human way to enable natural sort
+
+    :param nodename: The node name to analyze
+    :returns: A structure that can be consumed by 'sorted'
+    """
+    return [int(text) if text.isdigit() else text.lower()
+            for text in re.split(numregex, key)]
+
+
+def natural_sort(iterable):
+    """Return a sort using natural sort if possible
+
+    :param iterable:
+    :return:
+    """
+    try:
+        return sorted(iterable, key=naturalize_string)
+    except TypeError:
+        # The natural sort attempt failed, fallback to ascii sort
+        return sorted(iterable)
+
+
 def fixup_uuid(uuidprop):
     baduuid = ''.join(uuidprop.split())
     uuidprefix = (baduuid[:8], baduuid[8:12], baduuid[12:16])
@@ -44,6 +71,13 @@
     return '-'.join(uuid).upper()
 
 
+def fixup_str(propstr):
+    if propstr is None:
+        return ''
+    return ''.join([chr(int(c, 16)) for c in propstr.split()]).strip(
+        ' \xff\x00')
+
+
 class FileUploader(threading.Thread):
 
     def __init__(self, webclient, url, filename, data):
@@ -168,19 +202,26 @@
                 changeset[key] = {'value': changeset[key]}
             newvalue = changeset[key]['value']
             if self.fwo[key]['is_list'] and not isinstance(newvalue, list):
-                newvalues = newvalue.split(',')
+                if '=' in newvalue:
+                    # ASU set a precedent of = delimited settings
+                    # for now, honor that delimiter as well
+                    newvalues = newvalue.split('=')
+                else:
+                    newvalues = newvalue.split(',')
             else:
                 newvalues = [newvalue]
             newnewvalues = []
             for newvalue in newvalues:
+                newv = re.sub('\s+', ' ', newvalue)
                 if (self.fwo[key]['possible'] and
                         newvalue not in self.fwo[key]['possible']):
                     candlist = []
                     for candidate in self.fwo[key]['possible']:
-                        if newvalue.lower().startswith(candidate.lower()):
+                        candid = re.sub('\s+', ' ', candidate)
+                        if newv.lower().startswith(candid.lower()):
                             newvalue = candidate
                             break
-                        if candidate.lower().startswith(newvalue.lower()):
+                        if candid.lower().startswith(newv.lower()):
                             candlist.append(candidate)
                     else:
                         if len(candlist) == 1:
@@ -316,8 +357,14 @@
                     self.datacache['lenovo_cached_adapters'] = (
                         adapterdata, util._monotonic_time())
         if adapterdata and 'items' in adapterdata:
+            anames = {}
             for adata in adapterdata['items']:
                 aname = adata[self.ADP_NAME]
+                if aname in anames:
+                    anames[aname] += 1
+                    aname = '{0} {1}'.format(aname, anames[aname])
+                else:
+                    anames[aname] = 1
                 donenames = set([])
                 for fundata in adata[self.ADP_FUN]:
                     fdata = fundata.get('firmwares', ())
@@ -370,12 +417,12 @@
 
     def get_hw_inventory(self):
         hwmap = self.hardware_inventory_map()
-        for key in hwmap:
+        for key in natural_sort(hwmap):
             yield (key, hwmap[key])
 
     def get_hw_descriptions(self):
         hwmap = self.hardware_inventory_map()
-        for key in hwmap:
+        for key in natural_sort(hwmap):
             yield key
 
     def get_component_inventory(self, compname):
@@ -425,9 +472,13 @@
         enclosureuuid = self.get_property('/v2/ibmc/smm/chassis/uuid')
         if enclosureuuid:
             bay = self.get_property('/v2/cmm/sp/7')
+            serial = self.get_property('/v2/ibmc/smm/chassis/sn')
+            model = self.get_property('/v2/ibmc/smm/chassis/mtm')
             hwmap['Enclosure'] = {
                 'UUID': fixup_uuid(enclosureuuid),
                 'Bay': bay,
+                'Model': fixup_str(model),
+                'Serial': fixup_str(serial),
             }
         adapterdata = self.get_cached_data('lenovo_cached_adapters')
         if not adapterdata:
@@ -441,11 +492,17 @@
                     self.datacache['lenovo_cached_adapters'] = (
                         adapterdata, util._monotonic_time())
         if adapterdata and 'items' in adapterdata:
+            anames = {}
             for adata in adapterdata['items']:
                 skipadapter = False
                 if not adata[self.ADP_OOB]:
                     continue
                 aname = adata[self.ADP_NAME]
+                if aname in anames:
+                    anames[aname] += 1
+                    aname = '{0} {1}'.format(aname, anames[aname])
+                else:
+                    anames[aname] = 1
                 clabel = adata[self.ADP_LABEL]
                 if clabel == 'Unknown':
                     continue
@@ -560,7 +617,7 @@
         super(XCCClient, self).__init__(ipmicmd)
         self.adp_referer = None
 
-    def get_webclient(self):
+    def get_webclient(self, login=True):
         cv = self.ipmicmd.certverify
         wc = webclient.SecureHTTPConnection(self.imm, 443, verifycallback=cv)
         try:
@@ -569,6 +626,8 @@
             if se.errno != errno.ECONNREFUSED:
                 raise
             return None
+        if not login:
+            return wc
         adata = json.dumps({'username': self.username,
                             'password': self.password
                             })
@@ -865,7 +924,7 @@
                     standalonedisks.append(
                         storage.Disk(
                             name=disk['name'], description=disk['type'],
-                            id=(cid, disk['id']),  status=disk['RAIDState'],
+                            id=(cid, disk['id']), status=disk['RAIDState'],
                             serial=disk['serialNo'], fru=disk['fruPartNo']))
         return storage.ConfigSpec(disks=standalonedisks, arrays=pools)
 
@@ -1112,6 +1171,16 @@
         if '_csrf_token' in wc.cookies:
             wc.set_header('X-XSRF-TOKEN', self.wc.cookies['_csrf_token'])
 
+    def set_hostname(self, hostname):
+        self.wc.grab_json_response('/api/dataset', {'IMM_HostName': hostname})
+        self.wc.grab_json_response('/api/dataset', {'IMM_DescName': hostname})
+        self.weblogout()
+
+    def get_hostname(self):
+        rsp = self.wc.grab_json_response('/api/dataset/sys_info')
+        self.weblogout()
+        return rsp['items'][0]['system_name']
+
     def update_firmware_backend(self, filename, data=None, progress=None,
                                 bank=None):
         self.weblogout()
@@ -1242,3 +1311,11 @@
         if bank == 'backup':
             return 'complete'
         return 'pending'
+
+    def get_health(self, summary):
+        wc = self.get_webclient(False)
+        rsp = wc.grab_json_response('/api/providers/imm_active_events')
+        if 'items' in rsp and len(rsp['items']) == 0:
+            # The XCC reports healthy, no need to interrogate
+            raise pygexc.BypassGenericBehavior()
+        # Will use the generic handling for unhealthy systems
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/pyghmi/ipmi/oem/lenovo/nextscale.py 
new/pyghmi-1.1.0/pyghmi/ipmi/oem/lenovo/nextscale.py
--- old/pyghmi-1.0.44/pyghmi/ipmi/oem/lenovo/nextscale.py       2018-04-10 
16:27:58.000000000 +0200
+++ new/pyghmi-1.1.0/pyghmi/ipmi/oem/lenovo/nextscale.py        2018-05-22 
20:15:14.000000000 +0200
@@ -94,21 +94,29 @@
         if ie.ipmicode == 0xd5:  # no node present
             return (pygconst.Health.Ok, ['Absent'])
         raise
-    perminfo = ord(rsp['data'][1])
     health = pygconst.Health.Ok
     states = []
     if len(rsp['data']) == 4:  # different gens handled rc differently
         rsp['data'] = b'\x00' + bytes(rsp['data'])
+    elif len(rsp['data']) == 6:  # New FPC format
+        rsp['data'] = rsp['data'][:2] + rsp['data'][3:]
+    perminfo = ord(rsp['data'][1])
     if sz == 6:  # FPC
         permfail = ('\x02', '\x03')
     elif sz == 2:  # SMM
         permfail = ('\x02',)
-    if rsp['data'][4] in permfail:
-        states.append('Insufficient Power')
-        health = pygconst.Health.Failed
+    if perminfo & 0x20:
+        if rsp['data'][4] in permfail:
+            states.append('Insufficient Power')
+            health = pygconst.Health.Failed
+        elif rsp['data'][3:5] != '\x00\x00':
+            states.append('No Power Permission')
+            health = pygconst.Health.Failed
     if perminfo & 0x40:
         states.append('Node Fault')
         health = pygconst.Health.Failed
+    if rsp['data'][3:5] == '\x00\x00':
+        states.append('Absent')
     return (health, states)
 
 
@@ -233,6 +241,7 @@
 
 
 class SMMClient(object):
+
     def __init__(self, ipmicmd):
         self.ipmicmd = weakref.proxy(ipmicmd)
         self.smm = ipmicmd.bmc
@@ -269,15 +278,74 @@
         for data in authdata.findall('authResult'):
             if int(data.text) != 0:
                 raise Exception("Firmware update already in progress")
+        for data in authdata.findall('forwardUrl'):
+            if 'renew' in data.text:
+                raise Exception("Account password has expired on remote "
+                                "device")
         self.st1 = None
         self.st2 = None
         for data in authdata.findall('st1'):
             self.st1 = data.text
         for data in authdata.findall('st2'):
             self.st2 = data.text
+        if not self.st2:
+            # This firmware puts tokens in the html file, parse that
+            wc.request('GET', '/index.html')
+            rsp = wc.getresponse()
+            if rsp.status != 200:
+                raise Exception(rsp.read())
+            indexhtml = rsp.read()
+            for line in indexhtml.split('\n'):
+                if '"ST1"' in line:
+                    self.st1 = line.split()[-1].replace(
+                        '"', '').replace(',', '')
+                if '"ST2"' in line:
+                    self.st2 = line.split()[-1].replace(
+                        '"', '').replace(',', '')
         wc.set_header('ST2', self.st2)
         return wc
 
+    def set_hostname(self, hostname):
+        self.wc.request('POST', '/data', 'set=hostname:' + hostname)
+        rsp = self.wc.getresponse()
+        if rsp.status != 200:
+            raise Exception(rsp.read())
+        rsp.read()
+        self.logout()
+
+    def get_hostname(self):
+        currinfo = self.get_netinfo()
+        self.logout()
+        for data in currinfo.find('netConfig').findall('hostname'):
+            return data.text
+
+    def get_netinfo(self):
+        self.wc.request('POST', '/data', 'get=hostname')
+        rsp = self.wc.getresponse()
+        data = rsp.read()
+        if rsp.status == 400:
+            self.wc.request('POST', '/data?get=hostname', '')
+            rsp = self.wc.getresponse()
+            data = rsp.read()
+        if rsp.status != 200:
+            raise Exception(data)
+        currinfo = fromstring(data)
+        return currinfo
+
+    def set_domain(self, domain):
+        self.wc.request('POST', '/data', 'set=dnsDomain:' + domain)
+        rsp = self.wc.getresponse()
+        if rsp.status != 200:
+            raise Exception(rsp.read())
+        rsp.read()
+        self.logout()
+
+    def get_domain(self):
+        currinfo = self.get_netinfo()
+        self.logout()
+        for data in currinfo.find('netConfig').findall('dnsDomain'):
+            return data.text
+
     def get_ntp_enabled(self, variant):
         self.wc.request('POST', '/data', 'get=ntpOpMode')
         rsp = self.wc.getresponse()
@@ -332,6 +400,9 @@
                     break
         progress({'phase': 'upload', 'progress': 0.0})
         url = self.wc  # this is just to get self.st1 initted
+        self.wc.request('POST', '/data', 'set=fwType:10')  # SMM firmware
+        rsp = self.wc.getresponse()
+        rsp.read()
         url = '/fwupload/fwupload.esp?ST1={0}'.format(self.st1)
         self.wc.upload(url, filename, data, formname='fileUpload',
                        otherfields={'preConfig': 'on'})
@@ -355,6 +426,8 @@
             if rsp.status != 200:
                 raise Exception('Error applying firmware')
             progdata = fromstring(progdata)
+            if progdata.findall('fwUpdate')[0].text == 'invalid signature':
+                raise Exception('Firmware signature invalid')
             percent = float(progdata.findall('fwProgress')[0].text)
 
             progress({'phase': 'apply',
@@ -370,6 +443,6 @@
 
     @property
     def wc(self):
-        if not self._wc:
+        if not self._wc or self._wc.broken:
             self._wc = self.get_webclient()
         return self._wc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/pyghmi/ipmi/private/constants.py 
new/pyghmi-1.1.0/pyghmi/ipmi/private/constants.py
--- old/pyghmi-1.0.44/pyghmi/ipmi/private/constants.py  2018-04-10 
16:27:36.000000000 +0200
+++ new/pyghmi-1.1.0/pyghmi/ipmi/private/constants.py   2018-05-22 
20:15:14.000000000 +0200
@@ -1285,7 +1285,7 @@
             'deassertion_severity': const.Health.Ok,
         },
     },
-    0x21:  {  # slot/connector
+    0x21: {  # slot/connector
         0x0: {
             'desc': 'Fault',
             'severity': const.Health.Critical,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/pyghmi/ipmi/private/session.py 
new/pyghmi-1.1.0/pyghmi/ipmi/private/session.py
--- old/pyghmi-1.0.44/pyghmi/ipmi/private/session.py    2018-04-10 
16:27:58.000000000 +0200
+++ new/pyghmi-1.1.0/pyghmi/ipmi/private/session.py     2018-05-22 
20:15:14.000000000 +0200
@@ -27,7 +27,9 @@
 import struct
 import threading
 
-from Crypto.Cipher import AES
+
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives.ciphers import algorithms, Cipher, modes
 
 import pyghmi.exceptions as exc
 from pyghmi.ipmi.private import constants
@@ -302,6 +304,10 @@
     # can do something like reassign our threading and select modules
     socketchecking = None
 
+    # Maintain single Cryptography backend for all IPMI sessions (seems to be
+    # thread-safe)
+    _crypto_backend = default_backend()
+
     @classmethod
     def _cleanup(cls):
         for sesskey in list(cls.bmc_handlers):
@@ -471,6 +477,7 @@
                     self.iterwaiters.append(onlogon)
             return
         self.broken = False
+        self.logged = 0
         self.privlevel = 4
         self.maxtimeout = 3  # be aggressive about giving up on initial packet
         self.incommand = False
@@ -868,10 +875,15 @@
                 iv = os.urandom(16)
                 message += list(struct.unpack("16B", iv))
                 payloadtocrypt = _aespad(payload)
-                crypter = AES.new(self.aeskey, AES.MODE_CBC, iv)
-                crypted = crypter.encrypt(struct.pack("%dB" %
-                                                      len(payloadtocrypt),
-                                                      *payloadtocrypt))
+                crypter = Cipher(
+                    algorithm=algorithms.AES(self.aeskey),
+                    mode=modes.CBC(iv),
+                    backend=self._crypto_backend
+                )
+                encryptor = crypter.encryptor()
+                plaintext = struct.pack("%dB" % len(payloadtocrypt),
+                                        *payloadtocrypt)
+                crypted = encryptor.update(plaintext) + encryptor.finalize()
                 crypted = list(struct.unpack("%dB" % len(crypted), crypted))
                 message += crypted
             else:  # no confidetiality algorithm
@@ -1374,10 +1386,15 @@
             payload = data[16:16 + psize]
             if encrypted:
                 iv = data[16:32]
-                decrypter = AES.new(self.aeskey, AES.MODE_CBC, bytes(iv))
-                decrypted = decrypter.decrypt(
-                    struct.pack("%dB" % len(payload[16:]),
-                                *payload[16:]))
+                crypter = Cipher(
+                    algorithm=algorithms.AES(self.aeskey),
+                    mode=modes.CBC(bytes(iv)),
+                    backend=self._crypto_backend
+                )
+                decryptor = crypter.decryptor()
+                ciphertext = struct.pack("%dB" % len(payload[16:]),
+                                         *payload[16:])
+                decrypted = decryptor.update(ciphertext) + decryptor.finalize()
                 payload = struct.unpack("%dB" % len(decrypted), decrypted)
                 padsize = payload[-1] + 1
                 payload = list(payload[:-padsize])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/pyghmi/util/webclient.py 
new/pyghmi-1.1.0/pyghmi/util/webclient.py
--- old/pyghmi-1.0.44/pyghmi/util/webclient.py  2018-04-10 16:27:58.000000000 
+0200
+++ new/pyghmi-1.1.0/pyghmi/util/webclient.py   2018-05-22 20:15:14.000000000 
+0200
@@ -69,6 +69,7 @@
                  **kwargs):
         if 'timeout' not in kwargs:
             kwargs['timeout'] = 60
+        self.broken = False
         self.thehost = host
         self.theport = port
         httplib.HTTPConnection.__init__(self, host, port, strict, **kwargs)
@@ -107,12 +108,16 @@
                                                  bincert)
 
     def getresponse(self):
-        rsp = super(SecureHTTPConnection, self).getresponse()
-        for hdr in rsp.msg.headers:
-            if hdr.startswith('Set-Cookie:'):
-                c = Cookie.BaseCookie(hdr[11:])
-                for k in c:
-                    self.cookies[k] = c[k].value
+        try:
+            rsp = super(SecureHTTPConnection, self).getresponse()
+            for hdr in rsp.msg.headers:
+                if hdr.startswith('Set-Cookie:'):
+                    c = Cookie.BaseCookie(hdr[11:])
+                    for k in c:
+                        self.cookies[k] = c[k].value
+        except httplib.BadStatusLine:
+            self.broken = True
+            raise
         return rsp
 
     def grab_json_response(self, url, data=None, referer=None):
@@ -164,6 +169,8 @@
             headers = self.stdheaders.copy()
         if method == 'GET' and 'Content-Type' in headers:
             del headers['Content-Type']
+        if method == 'POST' and body and 'Content-Type' not in headers:
+            headers['Content-Type'] = 'application/x-www-form-urlencoded'
         if self.cookies:
             cookies = []
             for ckey in self.cookies:
@@ -175,5 +182,9 @@
                 headers['Cookie'] += '; ' + '; '.join(cookies)
         if referer:
             headers['Referer'] = referer
-        return super(SecureHTTPConnection, self).request(method, url, body,
-                                                         headers)
+        try:
+            return super(SecureHTTPConnection, self).request(method, url, body,
+                                                             headers)
+        except httplib.CannotSendRequest:
+            self.broken = True
+            raise
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/pyghmi.egg-info/PKG-INFO 
new/pyghmi-1.1.0/pyghmi.egg-info/PKG-INFO
--- old/pyghmi-1.0.44/pyghmi.egg-info/PKG-INFO  2018-04-10 16:30:46.000000000 
+0200
+++ new/pyghmi-1.1.0/pyghmi.egg-info/PKG-INFO   2018-05-22 20:18:09.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: pyghmi
-Version: 1.0.44
+Version: 1.1.0
 Summary: Python General Hardware Management Initiative (IPMI and others)
 Home-page: http://github.com/openstack/pyghmi/
 Author: Jarrod Johnson
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/pyghmi.egg-info/SOURCES.txt 
new/pyghmi-1.1.0/pyghmi.egg-info/SOURCES.txt
--- old/pyghmi-1.0.44/pyghmi.egg-info/SOURCES.txt       2018-04-10 
16:30:46.000000000 +0200
+++ new/pyghmi-1.1.0/pyghmi.egg-info/SOURCES.txt        2018-05-22 
20:18:10.000000000 +0200
@@ -7,6 +7,7 @@
 README
 README.md
 buildrpm
+lower-constraints.txt
 python-pyghmi.spec
 requirements.txt
 setup.cfg
@@ -73,4 +74,5 @@
 pyghmi/tests/unit/ipmi/__init__.py
 pyghmi/tests/unit/ipmi/test_sdr.py
 pyghmi/util/__init__.py
-pyghmi/util/webclient.py
\ No newline at end of file
+pyghmi/util/webclient.py
+zuul.d/project.yaml
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/pyghmi.egg-info/pbr.json 
new/pyghmi-1.1.0/pyghmi.egg-info/pbr.json
--- old/pyghmi-1.0.44/pyghmi.egg-info/pbr.json  2018-04-10 16:30:46.000000000 
+0200
+++ new/pyghmi-1.1.0/pyghmi.egg-info/pbr.json   2018-05-22 20:18:09.000000000 
+0200
@@ -1 +1 @@
-{"git_version": "ffd9c55", "is_release": true}
\ No newline at end of file
+{"git_version": "2df9280", "is_release": true}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/pyghmi.egg-info/requires.txt 
new/pyghmi-1.1.0/pyghmi.egg-info/requires.txt
--- old/pyghmi-1.0.44/pyghmi.egg-info/requires.txt      2018-04-10 
16:30:46.000000000 +0200
+++ new/pyghmi-1.1.0/pyghmi.egg-info/requires.txt       2018-05-22 
20:18:09.000000000 +0200
@@ -1 +1 @@
-pycrypto>=2.6
+cryptography!=2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/requirements.txt 
new/pyghmi-1.1.0/requirements.txt
--- old/pyghmi-1.0.44/requirements.txt  2018-04-10 16:27:36.000000000 +0200
+++ new/pyghmi-1.1.0/requirements.txt   2018-05-22 20:15:14.000000000 +0200
@@ -1 +1 @@
-pycrypto>=2.6
+cryptography!=2.0  # BSD/Apache-2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/test-requirements.txt 
new/pyghmi-1.1.0/test-requirements.txt
--- old/pyghmi-1.0.44/test-requirements.txt     2018-04-10 16:27:36.000000000 
+0200
+++ new/pyghmi-1.1.0/test-requirements.txt      2018-05-22 20:15:14.000000000 
+0200
@@ -1,12 +1,10 @@
 hacking>=0.5.6
-
-coverage>=3.6
-discover
-fixtures>=0.3.14
-python-subunit
-sphinx>=1.1.2
-testrepository>=0.0.17
+coverage>=4.0
+fixtures>=3.0.0
+python-subunit>=1.0.0
+sphinx>=1.6.5
+testrepository>=0.0.18
 testscenarios>=0.4
-testtools>=0.9.32
-os-testr>=0.8.0 # Apache-2.0
-oslotest>=1.10.0 # Apache-2.0
+testtools>=2.2.0
+os-testr>=1.0.0 # Apache-2.0
+oslotest>=3.2.0 # Apache-2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/tox.ini new/pyghmi-1.1.0/tox.ini
--- old/pyghmi-1.0.44/tox.ini   2018-04-10 16:27:36.000000000 +0200
+++ new/pyghmi-1.1.0/tox.ini    2018-05-22 20:15:14.000000000 +0200
@@ -16,7 +16,7 @@
 
 [testenv:pep8]
 whitelist_externals = bash
-commands = bash -c 'pep8 pyghmi bin/*'
+commands = bash -c 'pycodestyle pyghmi bin/*'
 
 [testenv:cover]
 setenv = VIRTUAL_ENV={envdir}
@@ -29,3 +29,13 @@
 [flake8]
 exclude = .venv,.tox,dist,doc,*.egg,build
 show-source = true
+
+[pep8]
+ignore = E731,E226,E123
+
+[testenv:lower-constraints]
+basepython = python3
+deps =
+  -c{toxinidir}/lower-constraints.txt
+  -r{toxinidir}/test-requirements.txt
+  -r{toxinidir}/requirements.txt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyghmi-1.0.44/zuul.d/project.yaml 
new/pyghmi-1.1.0/zuul.d/project.yaml
--- old/pyghmi-1.0.44/zuul.d/project.yaml       1970-01-01 01:00:00.000000000 
+0100
+++ new/pyghmi-1.1.0/zuul.d/project.yaml        2018-05-22 20:15:14.000000000 
+0200
@@ -0,0 +1,7 @@
+- project:
+    check:
+      jobs:
+        - openstack-tox-lower-constraints
+    gate:
+      jobs:
+        - openstack-tox-lower-constraints


Reply via email to