Skip to content
This repository was archived by the owner on Jul 18, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
language: python
dist: xenial
python:
  - "2.7"
  - "3.4"
  - "3.5"
  - "3.6"
  - "3.7"
sudo: true
install:
  - pip install -r test-requirements.txt
  - pip install -r requirements.txt
script:
  - nosetests -v
16 changes: 13 additions & 3 deletions pyxcli/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
from pyxcli.response import XCLIResponse
from pyxcli.helpers.exceptool import chained

try:
basestring
except NameError:
basestring = str

xlog = getLogger(XCLI_DEFAULT_LOGGER)


Expand Down Expand Up @@ -261,7 +266,7 @@ def _dump_xcli(self, obj):
return str(obj)

def _build_command(self, cmd, params, options, remote_target=None):
root = etree.Element("command", id=str(self._cmdindex.next()),
root = etree.Element("command", id=str(next(self._cmdindex)),
type=cmd, close_on_return="no")
if remote_target:
root.attrib["remote_target"] = remote_target
Expand All @@ -273,8 +278,13 @@ def _build_command(self, cmd, params, options, remote_target=None):
root.append(etree.Element("argument", name=self._dump_xcli(k),
value=self._dump_xcli(v)))
data = etree.tostring(root)
anon = data.replace(options["password"],
"XXX") if "password" in options else data

if("password" in options):
data = data.decode()
data.replace(options["password"], "XXX")
data.encode()

anon = data
xlog.debug("SEND %s" % (anon))
return data

Expand Down
4 changes: 2 additions & 2 deletions pyxcli/events/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

import json
from socket import getfqdn
from bunch import Bunch
from munch import Munch
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why Munch?
A Replacement like this requires extensive testing.
What's the benefit of this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe that Bunch is still supported, and it is incompatible with Python 3.x. All of my tests failed with Bunch in Python 3. It appears that Infinidat forked Bunch and created Munch.

https://github.com/Infinidat/munch

from logging import getLogger
from pyxcli import XCLI_DEFAULT_LOGGER
from pyxcli.events.platform_info import get_platform_details
Expand Down Expand Up @@ -86,7 +86,7 @@ def send_event(self, action, properties, event_severity=EVENT_SEVERITY):
raise TypeError('properties is not dict')

# prepare event
event_bunch = Bunch(
event_bunch = Munch(
Product=self.product_name,
Version=self.product_version,
Server=self.server_name,
Expand Down
9 changes: 7 additions & 2 deletions pyxcli/helpers/xml_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
from contextlib import contextmanager
from xml.parsers.expat import ExpatError

try:
basestring
except NameError:
basestring = str

Element = cet.Element
tostring = cet.tostring

Expand Down Expand Up @@ -189,7 +194,7 @@ class TerminationDetectingXMLParser(object):

def __init__(self):
self.tree_builder = _TerminationDetectingTreeBuilder()
self.xml_tree_builder = et.XMLTreeBuilder(target=self.tree_builder)
self.xml_tree_builder = et.XMLParser(target=self.tree_builder)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

XMLParser will also require extensive testing. I know that TreeBuilder is old, but what's the benefit?

Copy link
Author

@dslapelis dslapelis Jan 31, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

XMLTreeBuilder did not appear to exist in Python 3. XMLParser should be used instead; I can add the backwards compatibility try/except stated in the documentation http://effbot.org/elementtree/elementtree-xmlparser.htm


def feed(self, chunk):
with _translateExceptions(chunk):
Expand All @@ -202,4 +207,4 @@ def close(self):

@property
def root_element_closed(self):
return self.tree_builder.root_element_closed
return self.tree_builder.root_element_closed
4 changes: 2 additions & 2 deletions pyxcli/mirroring/mirrored_entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
##############################################################################

from logging import getLogger
from bunch import Bunch
from munch import Munch
from pyxcli import XCLI_DEFAULT_LOGGER

CG = "cg"
Expand Down Expand Up @@ -60,7 +60,7 @@ def get_mirror_resources_by_name_map(self, scope=None):
for xcli_mirror in self.xcli_client.cmd.mirror_list(scope='CG'):
name = MirroredEntities.get_mirrored_object_name(xcli_mirror)
cgs_mirrors_by_name[name] = xcli_mirror
res = Bunch(volumes=volumes_mirrors_by_name, cgs=cgs_mirrors_by_name)
res = Munch(volumes=volumes_mirrors_by_name, cgs=cgs_mirrors_by_name)
return res

def get_cg_mirrors(self):
Expand Down
25 changes: 18 additions & 7 deletions pyxcli/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,20 @@

"""

from bunch import Bunch
from munch import Munch
from pyxcli.helpers import xml_util as etree
import base64
import codecs

try:
basestring
except NameError:
basestring = str

try:
long
except NameError:
long = int

class XCLIResponse(object):
RETURN_PATH = "return"
Expand All @@ -38,7 +49,8 @@ def instantiate(cls, cmdroot, encoding):
compressed = cmdroot.find("compressed_return")
if compressed is not None:
text = compressed.attrib["value"]
raw = text.decode(encoding).decode("zlib")
raw = base64.b64decode(text)
raw = (codecs.decode(raw, "zlib")).decode('ascii')
cmdroot.append(etree.fromstring("<return>%s</return>" % (raw,)))
cmdroot.remove(compressed)

Expand Down Expand Up @@ -105,7 +117,7 @@ def __len__(self):
def __getitem__(self, item):
if isinstance(item, basestring):
return self.all(item)
elif isinstance(item, (int, long)):
elif isinstance(item, (int,long)):

return list(self.all())[item]
else:
Expand All @@ -128,11 +140,10 @@ def _populate_bunch_with_element(element):
"""
if 'value' in element.attrib:
return element.get('value')
current_bunch = Bunch()
current_bunch = Munch()

if element.get('id'):
current_bunch['nextra_element_id'] = element.get('id')
for subelement in element.getchildren():
current_bunch[subelement.tag] = _populate_bunch_with_element(
subelement)
return current_bunch
current_bunch[subelement.tag] = _populate_bunch_with_element(subelement)
return current_bunch
12 changes: 9 additions & 3 deletions pyxcli/transports.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
from pyxcli.errors import CorruptResponse
from pyxcli.errors import BaseScsiException

try:
basestring
except NameError:
basestring = str

xlog = getLogger(XCLI_DEFAULT_LOGGER)


Expand Down Expand Up @@ -223,7 +228,8 @@ def send(self, data, timeout=None):

while data:
chunk = data[:self.MAX_IO_CHUNK]
sent = self.sock.send(chunk)
byte_chunk = chunk.encode()
sent = self.sock.send(byte_chunk)
data = data[sent:]

parser = TerminationDetectingXMLParser()
Expand All @@ -233,7 +239,7 @@ def send(self, data, timeout=None):
chunk = self.sock.recv(self.MAX_IO_CHUNK)
if not chunk:
break
raw += chunk
raw += chunk.decode()
parser.feed(chunk)
return parser.close()
except XMLException as ex:
Expand Down Expand Up @@ -353,4 +359,4 @@ def send(self, *args):
self.transport.close()
self.transport = ClosedTransport
xlog.debug("MultiEndpointTransport: sending over %s failed",
self.transport)
self.transport)
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
bunch
munch