Skip to content
This repository has been archived by the owner on Jan 10, 2023. It is now read-only.

Fix Python 3.6.0 #5

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
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
70 changes: 63 additions & 7 deletions usbinfo/darwin.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,65 @@

import copy
import platform
import re
import subprocess

from .posix import get_mounts

# platform.mac_ver()'s first tuple element encodes the OS X version,
# such as 10.11.3.
OSX_VERSION_STR = platform.mac_ver()[0]
OSX_VERSION_MAJOR_INT, \
OSX_VERSION_MINOR_INT, \
OSX_VERSION_MICRO_INT = [int(part) for part in OSX_VERSION_STR.split('.')]

OSX_VERSION_INFO = [int(part) for part in OSX_VERSION_STR.split('.')]
OSX_VERSION_MAJOR_INT = OSX_VERSION_INFO[0]
OSX_VERSION_MINOR_INT = OSX_VERSION_INFO[1]
OSX_VERSION_MICRO_INT = 0

if len(OSX_VERSION_INFO) >= 3:
OSX_VERSION_MICRO_INT = OSX_VERSION_INFO[2]


sanitize_pattern = re.compile(r'^(\s*?\<string\>)(.*?)(\<\/string\>.*?)$')

def _sanitize_xml(data):
Copy link
Contributor

Choose a reason for hiding this comment

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

It might be worth investigating doing all of this in an XML library. This function is assuming that ioreg will always return data in a specific format.

"""Takes an plist (xml) and checks <string> defintions for control characters.

If a control character is found, the string is converted to hexidecimal.
For ST-Link devices, this properly displays the serial number, which
is eroneously encoded as binary data, which causes the plistlib XML parser
to crash.

Returns the same document, with any mis-encoded <string> values converted
to ascii hex."""
Copy link
Contributor

Choose a reason for hiding this comment

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

We should follow the indentation style for other docstrings.

output = []

data = data.decode('utf-8')
Copy link
Contributor

Choose a reason for hiding this comment

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

You are mutating data at the caller here. You could just encode it ad the for loop itself.


for i, line in enumerate(data.split('\n')):
Copy link
Contributor

Choose a reason for hiding this comment

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

No need to enumerate if you're not using the index.

Copy link
Contributor

Choose a reason for hiding this comment

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

You can also use splitlines().

chunk = line
Copy link
Contributor

Choose a reason for hiding this comment

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

Temporary assignment not necessary.

match = re.match(sanitize_pattern, chunk)
if match:
start = match.group(1)
middle = match.group(2)
end = match.group(3)
needs_patch = False
# Inspect the line and see if it has invalid characters.
byte_list = bytearray([ord(byte) for byte in middle])
for byte in byte_list:
if byte < 32:
needs_patch = True
if needs_patch:
Copy link
Contributor

Choose a reason for hiding this comment

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

Could this all be reduced to just

if any([ord(byte) not in range(32, 128) for byte in middle]):
    ...

middle = ''.join(['%02X' % byte for byte in byte_list])
new_line = '{start}{middle}{end}'.format(start=start,
middle=middle,
end=end)
output.append(new_line)
else:
output.append(line)
else:
output.append(line)
output = '\n'.join([line for line in output])
Copy link
Contributor

Choose a reason for hiding this comment

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

This can simply be:

return '\n'.join(output)


return output.encode('utf-8')
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't this redundant?


def _ioreg_usb_devices(nodename=None):
"""Returns a list of USB device tree from ioreg"""
Expand All @@ -38,9 +86,17 @@ def _ioreg(nodename):
"""Run ioreg command on specific node name"""
cmd = ['ioreg', '-a', '-l', '-r', '-n', nodename]
output = subprocess.check_output(cmd)
# ST-Link devices (and possibly others?) erroneously store binary data
# in the <string> serial number, which causes plistlib to blow up.
# This will convert that to hex and preserve contents otherwise.

Choose a reason for hiding this comment

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

Please add this comment to the function definition.

output = _sanitize_xml(output)
plist_data = []
if output:
return plistlib.readPlistFromString(output)
return []
try:
plist_data = plistlib.readPlistFromString(output)
except AttributeError as e:
plist_data = plistlib.loads(output)
jeffherman marked this conversation as resolved.
Show resolved Hide resolved
return plist_data

if nodename is None:
xhci = _ioreg('AppleUSBXHCI')
Expand Down Expand Up @@ -97,7 +153,7 @@ def _disk_partition(node):
info = {}

for child in node.get('IORegistryEntryChildren', []):
for class_name, handler in ioclass_handlers.iteritems():
for class_name, handler in iter(ioclass_handlers.items()):
jeffherman marked this conversation as resolved.
Show resolved Hide resolved
if child.get('IOObjectClass') == class_name:
info.update(handler(child))
info.update(_extra_if_info(child))
Expand Down