Skip to content

Commit

Permalink
Hooks: Clean up the USB hook logic.
Browse files Browse the repository at this point in the history
* Normalize logic: however libraries are discovered, they are
accumulated into the 'binaries' list. At the end of the hook, they
are validated and transformed into the structure that the hook engine
requires.

* Put Cygwin logic through the same code path that regular filesystem
library discovery uses, just with a different set of candidate
filenames.

* Update the comments to be more descriptive, add some small grammar
fixes.

* Delete spurious whitespace in response to PR feedback.
  • Loading branch information
Charles Nicholson committed Mar 11, 2018
1 parent d80513b commit cefc3e5
Showing 1 changed file with 40 additions and 45 deletions.
85 changes: 40 additions & 45 deletions PyInstaller/hooks/hook-usb.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@

import ctypes.util
import os
import usb.core
import usb.backend

from PyInstaller.depend.utils import _resolveCtypesImports
from PyInstaller.compat import is_cygwin, getenv
Expand All @@ -23,69 +21,66 @@
# https://github.com/walac/pyusb/blob/master/docs/faq.rst
# https://github.com/walac/pyusb/blob/master/docs/tutorial.rst

binaries=[]
binaries = []

# loading usb.core.find in this script crashes Ubuntu 14.04LTS,

# Running usb.core.find() in this script crashes Ubuntu 14.04LTS,
# let users circumvent pyusb discovery with an environment variable.
skip_pyusb_discovery = \
bool(getenv('PYINSTALLER_USB_HOOK_SKIP_PYUSB_DISCOVERY'))

# first try to use pyusb library locator

# Try to use pyusb's library locator.
if not skip_pyusb_discovery:
import usb.core
import usb.backend
try:
# get the backend symbols before find
pyusb_backend_dir = set(dir(usb.backend))

backend_contents_before_discovery = set(dir(usb.backend))
# perform find, which will load a usb library if found
usb.core.find()

# get the backend symbols which have been added (loaded)
backends = set(dir(usb.backend)) - pyusb_backend_dir

# for each of the loaded backends, see if they have a library
binaries = []
backends = set(dir(usb.backend)) - backend_contents_before_discovery
# gather the libraries from the loaded backends
backend_lib_basenames = []
for usblib in [getattr(usb.backend, be)._lib for be in backends]:
if usblib is not None:
binaries = [(usblib._name, '')]

# OSX returns the full path, Linux only the filename.
# save the basename and reconstruct the path after gathering.
backend_lib_basenames.append(os.path.basename(usblib._name))
# try to resolve the library names to absolute paths.
binaries = _resolveCtypesImports(backend_lib_basenames)
except (ValueError, usb.core.USBError) as exc:
logger.warning("%s", exc)


# if nothing found, try to use our custom mechanism
# If pyusb didn't find a backend, manually search for usb libraries.
if not binaries:
# Try to resolve your libusb libraries in the following order:
#
# libusb-1.0, libusb-0.1, openusb
#
# NOTE: Mind updating run-time hook when adding further libs.
libusb_candidates = (
# libusb10
'usb-1.0', 'usb', 'libusb-1.0',
# libusb01
'usb-0.1', 'libusb0',
# openusb
'openusb',
)

# NOTE: Update these lists when adding further libs.
if is_cygwin:
libusb_candidates = ['cygusb-1.0-0.dll', 'cygusb0.dll']
else:
libusb_candidates = [
# libusb10
'usb-1.0', 'usb', 'libusb-1.0',
# libusb01
'usb-0.1', 'libusb0',
# openusb
'openusb',
]

backend_library_basenames = []
for candidate in libusb_candidates:
libname = ctypes.util.find_library(candidate)
if libname is not None:
break
backend_library_basenames.append(os.path.basename(libname))
if backend_library_basenames:
binaries = _resolveCtypesImports(backend_library_basenames)

if libname is not None:
# Use basename here because Python returns full library path
# on Mac OSX when using ctypes.util.find_library.
bins = [os.path.basename(libname)]
binaries = _resolveCtypesImports(bins)
elif is_cygwin:
bins = ['cygusb-1.0-0.dll', 'cygusb0.dll']
binaries = _resolveCtypesImports(bins)[:1] # use only the first one
else:
binaries = []

if binaries:
# `_resolveCtypesImports` returns a 3-tuple, but `binaries` are only
# 2-tuples, so remove the last element:
assert len(binaries[0]) == 3
binaries = [(binaries[0][1], '')]
# Validate and normalize the first found usb library.
if binaries:
# `_resolveCtypesImports` returns a 3-tuple, but `binaries` are only
# 2-tuples, so remove the last element:
assert len(binaries[0]) == 3
binaries = [(binaries[0][1], '')]

0 comments on commit cefc3e5

Please sign in to comment.