Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-libusb1 for openSUSE:Factory checked in at 2021-01-20 18:28:17 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-libusb1 (Old) and /work/SRC/openSUSE:Factory/.python-libusb1.new.28504 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-libusb1" Wed Jan 20 18:28:17 2021 rev:3 rq:864626 version:1.9.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-libusb1/python-libusb1.changes 2019-05-16 22:09:46.886296749 +0200 +++ /work/SRC/openSUSE:Factory/.python-libusb1.new.28504/python-libusb1.changes 2021-01-20 18:28:48.571593908 +0100 @@ -1,0 +2,18 @@ +Wed Jan 20 09:43:06 UTC 2021 - John Vandenberg <[email protected]> + +- Update to v1.9.1 + * Fix installation from pypi source tarball, broken in 1.8.1 +- from v1.9 + * Drop USBPollerThread + * Deprecate libusb-lock-related USBContext API +- from v1.8.1 + * Embed libusb1 dll for easier deployment on Windows + * Cryptographically signed releases + * Use libusb_free_pollfds whenever available (libusb1>=1.0.20) + * Fix hotplug callback destruction at context teardown + * Drop remnants of python 2.6 support code +- from v1.8 + * Fix getExtra and libusb1.libusb_control_transfer_get_data + * Fix getMaxPower unit on SuperSpeed devices + +------------------------------------------------------------------- Old: ---- libusb1-1.7.1.tar.gz New: ---- libusb1-1.9.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-libusb1.spec ++++++ --- /var/tmp/diff_new_pack.eAXzXv/_old 2021-01-20 18:28:49.699594943 +0100 +++ /var/tmp/diff_new_pack.eAXzXv/_new 2021-01-20 18:28:49.703594946 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-libusb1 # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-libusb1 -Version: 1.7.1 +Version: 1.9.1 Release: 0 Summary: Python wrapper for libusb-1.0 # Relicensed from GPL to LGPLv2.1+ in May 2015 @@ -40,6 +40,8 @@ %prep %setup -q -n libusb1-%{version} +sed -i '/wheel/d' setup.py + sed -i '1{/^#!/d}' examples/*.py chmod a-x examples/*.py @@ -51,7 +53,7 @@ %python_expand %fdupes %{buildroot}%{$python_sitelib} %check -%python_exec -m usb1.testUSB1 +%python_exec -m usb1.testUSB1 -v %files %{python_files} %doc README.rst examples/ ++++++ libusb1-1.7.1.tar.gz -> libusb1-1.9.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libusb1-1.7.1/MANIFEST.in new/libusb1-1.9.1/MANIFEST.in --- old/libusb1-1.7.1/MANIFEST.in 2019-05-10 00:49:51.000000000 +0200 +++ new/libusb1-1.9.1/MANIFEST.in 2020-11-29 08:39:10.000000000 +0100 @@ -3,7 +3,7 @@ include COPYING.LESSER include examples/README include examples/*.py -include testUSB1.py +include usb1/testUSB1.py include stdeb.cfg include versioneer.py include usb1/_version.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libusb1-1.7.1/PKG-INFO new/libusb1-1.9.1/PKG-INFO --- old/libusb1-1.7.1/PKG-INFO 2019-05-10 00:52:33.000000000 +0200 +++ new/libusb1-1.9.1/PKG-INFO 2020-12-09 14:48:08.651121600 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: libusb1 -Version: 1.7.1 +Version: 1.9.1 Summary: Pure-python wrapper for libusb-1.0 Home-page: http://github.com/vpelletier/python-libusb1 Author: Vincent Pelletier @@ -452,6 +452,34 @@ Fix an occasional segfault when closing a transfer from inside its callback function. + 1.8 + --- + + Fix getExtra and libusb1.libusb_control_transfer_get_data . + Fix getMaxPower unit on SuperSpeed devices. + + 1.8.1 + ----- + + Release process rework: + + - embed libusb1 dll for easier deployment on Windows + - cryptographically signed releases + + Use libusb_free_pollfds whenever available (libusb1>=1.0.20). + Fix hotplug callback destruction at context teardown. + Drop remnants of python 2.6 support code. + + 1.9 + --- + + Drop USBPollerThread and deprecate libusb-lock-related USBContext API. + + 1.9.1 + ----- + + Fix installation from pypi source tarball, broken in 1.8.1 . + .. _CPython: http://www.python.org/ .. _pypy: http://pypy.org/ @@ -473,9 +501,6 @@ Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+) Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python :: 2.4 -Classifier: Programming Language :: Python :: 2.5 -Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libusb1-1.7.1/README.rst new/libusb1-1.9.1/README.rst --- old/libusb1-1.7.1/README.rst 2019-05-10 00:49:51.000000000 +0200 +++ new/libusb1-1.9.1/README.rst 2020-12-09 14:47:58.000000000 +0100 @@ -442,6 +442,34 @@ Fix an occasional segfault when closing a transfer from inside its callback function. +1.8 +--- + +Fix getExtra and libusb1.libusb_control_transfer_get_data . +Fix getMaxPower unit on SuperSpeed devices. + +1.8.1 +----- + +Release process rework: + +- embed libusb1 dll for easier deployment on Windows +- cryptographically signed releases + +Use libusb_free_pollfds whenever available (libusb1>=1.0.20). +Fix hotplug callback destruction at context teardown. +Drop remnants of python 2.6 support code. + +1.9 +--- + +Drop USBPollerThread and deprecate libusb-lock-related USBContext API. + +1.9.1 +----- + +Fix installation from pypi source tarball, broken in 1.8.1 . + .. _CPython: http://www.python.org/ .. _pypy: http://pypy.org/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libusb1-1.7.1/examples/hotplug_advanced.py new/libusb1-1.9.1/examples/hotplug_advanced.py --- old/libusb1-1.7.1/examples/hotplug_advanced.py 2019-05-10 00:49:51.000000000 +0200 +++ new/libusb1-1.9.1/examples/hotplug_advanced.py 2020-11-29 08:39:10.000000000 +0100 @@ -227,7 +227,7 @@ ) try: mode() - except NoHotplugSupport, exc: + except NoHotplugSupport as exc: print(exc.value) sys.exit(1) except (KeyboardInterrupt, SystemExit): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libusb1-1.7.1/libusb1.egg-info/PKG-INFO new/libusb1-1.9.1/libusb1.egg-info/PKG-INFO --- old/libusb1-1.7.1/libusb1.egg-info/PKG-INFO 2019-05-10 00:52:33.000000000 +0200 +++ new/libusb1-1.9.1/libusb1.egg-info/PKG-INFO 2020-12-09 14:48:08.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: libusb1 -Version: 1.7.1 +Version: 1.9.1 Summary: Pure-python wrapper for libusb-1.0 Home-page: http://github.com/vpelletier/python-libusb1 Author: Vincent Pelletier @@ -452,6 +452,34 @@ Fix an occasional segfault when closing a transfer from inside its callback function. + 1.8 + --- + + Fix getExtra and libusb1.libusb_control_transfer_get_data . + Fix getMaxPower unit on SuperSpeed devices. + + 1.8.1 + ----- + + Release process rework: + + - embed libusb1 dll for easier deployment on Windows + - cryptographically signed releases + + Use libusb_free_pollfds whenever available (libusb1>=1.0.20). + Fix hotplug callback destruction at context teardown. + Drop remnants of python 2.6 support code. + + 1.9 + --- + + Drop USBPollerThread and deprecate libusb-lock-related USBContext API. + + 1.9.1 + ----- + + Fix installation from pypi source tarball, broken in 1.8.1 . + .. _CPython: http://www.python.org/ .. _pypy: http://pypy.org/ @@ -473,9 +501,6 @@ Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+) Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python :: 2.4 -Classifier: Programming Language :: Python :: 2.5 -Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libusb1-1.7.1/setup.py new/libusb1-1.9.1/setup.py --- old/libusb1-1.7.1/setup.py 2019-05-10 00:49:51.000000000 +0200 +++ new/libusb1-1.9.1/setup.py 2020-12-09 14:47:58.000000000 +0100 @@ -13,30 +13,141 @@ # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +from __future__ import print_function from setuptools import setup +from setuptools import Command +import setuptools.command.install from codecs import open +import errno +import hashlib import os +import subprocess import sys import versioneer +try: + from urllib.request import urlopen + from urllib.parse import urlsplit + from html.parser import HTMLParser +except ImportError: + # BBB: python 2.7 + from urllib2 import urlopen + from urlparse import urlsplit + from HTMLParser import HTMLParser + +if os.getenv('I_KNOW_HOW_TO_RELEASE_PYTHON_LIBUSB1') != '1' and any( + x in sys.argv for x in ('sdist', 'upload') +): + print('Use setup.sh to build') + sys.exit(1) + +CURRENT_WINDOWS_7Z_SHA256 = ( + 'd3087e7d09ec4e463f5f4b394dcfec0b90e835545318af1a75575de59d2dfaac' +) + +cmdclass = versioneer.get_cmdclass() +class install(setuptools.command.install.install): + def run(self): + # XXX: setuptools.command.install.install is an old-style class on + # python2.7 :( + setuptools.command.install.install.run(self) + if os.getenv('LIBUSB_BINARY'): + self.copy_file( + os.getenv('LIBUSB_BINARY'), + os.path.join(self.install_lib, 'usb1'), + ) +cmdclass['install'] = install + +class upload(Command): + def run(self): + print('This project uses signed releases. See KEYS for instructions.') + print('Hint:') + print(' twine upload dist/<release file> dist/<release file>.asc') + sys.exit(1) +cmdclass['upload'] = upload + +class update_libusb(Command): + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + class WindowsBinariesArchiveLinkFinder(HTMLParser): + found = None + __a_href = None + def handle_starttag(self, tag, attrs): + if tag == 'a': + assert self.__a_href is None, repr(self.__a_href) + self.__a_href = dict(attrs).get('href') + + def handle_endtag(self, tag): + if tag == 'a': + self.__a_href = None + + def handle_data(self, data): + if self.__a_href is not None and data == 'Latest Windows Binaries': + assert self.found is None, repr(self.found) + self.found = self.__a_href + + def run(self): + finder = self.WindowsBinariesArchiveLinkFinder() + finder.feed(urlopen('https://libusb.info/').read().decode('utf-8')) + finder.close() + url = finder.found + if url is None: + raise ValueError('Failed to locate current windows binary release') + build_dir = os.path.join(os.path.dirname(__file__), 'build') + download_cache_path = os.path.join(build_dir, 'download-cache') + archive_path = os.path.join( + download_cache_path, + urlsplit(url).path.rsplit('/', 1)[-1], + ) + if not os.path.exists(archive_path): + os.makedirs(download_cache_path) + with open(archive_path, 'wb') as archive_file: + archive_file.write(urlopen(url).read()) + with open(archive_path, 'rb') as archive_file: + archive_sha256 = hashlib.sha256(archive_file.read()).hexdigest() + if archive_sha256 != CURRENT_WINDOWS_7Z_SHA256: + raise ValueError( + 'Windows release sha56 mismatch: %r fetched with a sha256 of %r' % ( + url, + archive_sha256, + ) + ) + # py2 does not have subprocess.DEVNULL. + with open(os.devnull, 'wb') as devnull: + for arch_path, out_dir in ( + ('MS32/dll/libusb-1.0.dll', os.path.join(build_dir, 'win32')), + ('MS64/dll/libusb-1.0.dll', os.path.join(build_dir, 'win_amd64')), + ): + subprocess.check_call( + [ + '7z', 'e', '-aoa', + '-o' + out_dir, + archive_path, + arch_path, + ], + # 7z will not shut its pie hole. + stdout=devnull, + close_fds=True, + ) +cmdclass['update_libusb'] = update_libusb long_description = open( os.path.join(os.path.dirname(__file__), 'README.rst'), encoding='utf8', ).read() -try: - next -except NameError: - # "next" builtin missing < 2.6 - next = lambda x: x.next() - setup( name='libusb1', description=next(x for x in long_description.splitlines() if x.strip()), long_description='.. contents::\n\n' + long_description, keywords='usb libusb', version=versioneer.get_version(), - cmdclass=versioneer.get_cmdclass(), + cmdclass=cmdclass, author='Vincent Pelletier', author_email='[email protected]', url='http://github.com/vpelletier/python-libusb1', @@ -48,9 +159,6 @@ 'Intended Audience :: Developers', 'License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)', 'Operating System :: OS Independent', - 'Programming Language :: Python :: 2.4', - 'Programming Language :: Python :: 2.5', - 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.4', @@ -62,5 +170,9 @@ 'Topic :: Software Development :: Libraries', 'Topic :: System :: Hardware :: Hardware Drivers', ], - use_2to3=sys.version_info >= (3, ), + setup_requires=[ + 'wheel', + ], + use_2to3=True, + test_suite='usb1.testUSB1', ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libusb1-1.7.1/stdeb.cfg new/libusb1-1.9.1/stdeb.cfg --- old/libusb1-1.7.1/stdeb.cfg 2016-08-22 01:20:50.000000000 +0200 +++ new/libusb1-1.9.1/stdeb.cfg 2020-11-29 08:39:10.000000000 +0100 @@ -1,4 +1,4 @@ [DEFAULT] -Source=python-libusb1 -Package=python-libusb1 +Source=python-usb1 +Package=python-usb1 Depends=libusb-1.0-0 | libusb2debian diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libusb1-1.7.1/usb1/__init__.py new/libusb1-1.9.1/usb1/__init__.py --- old/libusb1-1.7.1/usb1/__init__.py 2019-05-10 00:49:51.000000000 +0200 +++ new/libusb1-1.9.1/usb1/__init__.py 2020-12-05 03:36:31.000000000 +0100 @@ -53,24 +53,18 @@ import sys import threading import warnings -import weakref +from weakref import WeakSet import collections import functools import contextlib import inspect from . import libusb1 -if sys.version_info[:2] >= (2, 6): # pylint: disable=wrong-import-order,ungrouped-imports - if sys.platform == 'win32': - from ctypes import get_last_error as get_errno - else: - from ctypes import get_errno -# pylint: enable=wrong-import-order,ungrouped-imports +if sys.platform == 'win32': + from ctypes import get_last_error as get_errno else: - def get_errno(): - raise NotImplementedError( - 'Your python version does not support errno/last_error' - ) + from ctypes import get_errno +# pylint: enable=wrong-import-order,ungrouped-imports __all__ = [ 'USBContext', 'USBDeviceHandle', 'USBDevice', 'hasCapability', @@ -133,15 +127,10 @@ __raiseUSBError(value) return value -try: - namedtuple = collections.namedtuple -except AttributeError: - Version = tuple -else: - Version = namedtuple( - 'Version', - ['major', 'minor', 'micro', 'nano', 'rc', 'describe'], - ) +Version = collections.namedtuple( + 'Version', + ['major', 'minor', 'micro', 'nano', 'rc', 'describe'], +) if sys.version_info[0] == 3: BYTE = bytes([0]) @@ -216,29 +205,6 @@ CONTROL_SETUP = BYTE * CONTROL_SETUP_SIZE # pylint: enable=undefined-variable -__libc_name = find_library('c') -if __libc_name is None: - # Of course, will leak memory. - # Should we warn user ? How ? - _free = lambda x: None -else: - _free = getattr(cdll, __libc_name).free -del __libc_name - -try: - WeakSet = weakref.WeakSet -except AttributeError: - # Python < 2.7: tiny wrapper around WeakKeyDictionary - class WeakSet(object): - def __init__(self): - self.__dict = weakref.WeakKeyDictionary() - - def add(self, item): - self.__dict[item] = None - - def pop(self): - return self.__dict.popitem()[0] - # Default string length # From a comment in libusb-1.0: "Some devices choke on size > 255" STRING_LENGTH = 255 @@ -945,111 +911,6 @@ # Deprecated: to drop return self.__transfer.isSubmitted() -# BBB -class USBPollerThread(threading.Thread): - """ - Implements libusb1 documentation about threaded, asynchronous - applications. - In short, instanciate this class once (...per USBContext instance), call - start() on the instance, and do whatever you need. - This thread will be used to execute transfer completion callbacks, and you - are free to use libusb1's synchronous API in another thread, and can forget - about libusb1 file descriptors. - - See http://libusb.sourceforge.net/api-1.0/mtasync.html . - """ - _can_run = True - - def __init__(self, context, poller, exc_callback=None): - """ - Create a poller thread for given context. - Warning: it will not check if another poller instance was already - present for that context, and will replace it. - - poller - (same as USBPoller.__init__ "poller" parameter) - - exc_callback (callable) - Called with a libusb_error value as single parameter when event - handling fails. - If not given, an USBError will be raised, interrupting the thread. - """ - super(USBPollerThread, self).__init__() - warnings.warn( - 'USBPollerThread causes long stalls when used with poll (it was ' - 'intended for epoll), and is generally misleading. Consider ' - 'calling looping over context.handleEvents() in a thread instead.', - DeprecationWarning, - ) - self.daemon = True - self.__context = context - self.__poller = poller - self.__fd_set = set() - if exc_callback is not None: - self.exceptionHandler = exc_callback - - def stop(self): - """ - Stop & join thread. - - Allows stopping event thread before context gets closed. - """ - self._can_run = False - self.join() - - # pylint: disable=method-hidden - @staticmethod - def exceptionHandler(exc): - raise exc - # pylint: enable=method-hidden - - def run(self): - # We expect quite some spinning in below loop, so move any unneeded - # operation out of it. - context = self.__context - poll = self.__poller.poll - try_lock_events = context.tryLockEvents - lock_event_waiters = context.lockEventWaiters - wait_for_event = context.waitForEvent - unlock_event_waiters = context.unlockEventWaiters - event_handling_ok = context.eventHandlingOK - unlock_events = context.unlockEvents - handle_events_locked = context.handleEventsLocked - event_handler_active = context.eventHandlerActive - getNextTimeout = context.getNextTimeout - exceptionHandler = self.exceptionHandler - fd_set = self.__fd_set - context.setPollFDNotifiers(self._registerFD, self._unregisterFD) - for fd, events in context.getPollFDList(): - self._registerFD(fd, events, None) - try: - while fd_set and self._can_run: - if try_lock_events(): - lock_event_waiters() - while event_handler_active(): - wait_for_event() - unlock_event_waiters() - else: - try: - while event_handling_ok(): - if poll(getNextTimeout()): - try: - handle_events_locked() - except USBError: - exceptionHandler(sys.exc_info()[1]) - finally: - unlock_events() - finally: - context.setPollFDNotifiers(None, None) - - def _registerFD(self, fd, events, _): - self.__poller.register(fd, events) - self.__fd_set.add(fd) - - def _unregisterFD(self, fd, _): - self.__fd_set.discard(fd) - self.__poller.unregister(fd) - class USBPoller(object): """ Class allowing integration of USB event polling in a file-descriptor @@ -1172,7 +1033,6 @@ # pylint: enable=undefined-variable __set = set __KeyError = KeyError - __sys = sys def __init__(self, context, handle, device): """ @@ -1337,8 +1197,8 @@ Reinitialise current device. Attempts to restore current configuration & alt settings. If this fails, will result in a device disconnect & reconnect, so you - have to close current device and rediscover it (notified by a - ERROR_NOT_FOUND error code). + have to close current device and rediscover it (notified by an + USBErrorNotFound exception). """ mayRaiseUSBError(libusb1.libusb_reset_device(self.__handle)) @@ -1657,7 +1517,7 @@ return result class USBConfiguration(object): - def __init__(self, context, config): + def __init__(self, context, config, device_speed): """ You should not instanciate this class directly. Call USBDevice methods to get instances of this class. @@ -1666,6 +1526,7 @@ raise TypeError('Unexpected descriptor type.') self.__config = config self.__context = context + self.__device_speed = device_speed def getNumInterfaces(self): return self.__config.bNumInterfaces @@ -1683,11 +1544,13 @@ def getMaxPower(self): """ - Returns device's power consumption in mW. - Beware of unit: USB descriptor uses 2mW increments, this method - converts it to mW units. + Returns device's power consumption in mA. + + USB descriptor is expressed in units of 2 mA when the device is operating in high-speed mode + and in units of 8 mA when the device is operating in super-speed mode. This function scales + the descriptor value appropriately. """ - return self.__config.MaxPower * 2 + return self.__config.MaxPower * (8 if self.__device_speed == SPEED_SUPER else 2) def getExtra(self): """ @@ -1907,6 +1770,9 @@ continue mayRaiseUSBError(result) append(config.contents) + self.__bus_number = libusb1.libusb_get_bus_number(device_p) + self.__port_number = libusb1.libusb_get_port_number(device_p) + self.__device_address = libusb1.libusb_get_device_address(device_p) def __del__(self): self.close() @@ -1945,13 +1811,13 @@ def __getitem__(self, index): return USBConfiguration( - self.__context, self.__configuration_descriptor_list[index]) + self.__context, self.__configuration_descriptor_list[index], self.getDeviceSpeed()) def __key(self): return ( - id(self.__context), self.getBusNumber(), - self.getDeviceAddress(), self.getVendorID(), - self.getProductID(), + id(self.__context), self.__bus_number, + self.__device_address, self.device_descriptor.idVendor, + self.device_descriptor.idProduct, ) def __hash__(self): @@ -1970,7 +1836,7 @@ def iterConfigurations(self): context = self.__context for config in self.__configuration_descriptor_list: - yield USBConfiguration(context, config) + yield USBConfiguration(context, config, self.getDeviceSpeed()) # BBB iterConfiguations = iterConfigurations @@ -1985,13 +1851,13 @@ """ Get device's bus number. """ - return libusb1.libusb_get_bus_number(self.device_p) + return self.__bus_number def getPortNumber(self): """ Get device's port number. """ - return libusb1.libusb_get_port_number(self.device_p) + return self.__port_number def getPortNumberList(self): """ @@ -2010,7 +1876,7 @@ """ Get device's address on its bus. """ - return libusb1.libusb_get_device_address(self.device_p) + return self.__device_address def getbcdUSB(self): """ @@ -2296,7 +2162,8 @@ def _exit(self): context_p = self.__context_p if context_p: - for handle in self.__hotplug_callback_dict.keys(): + while self.__hotplug_callback_dict: + handle = next(iter(self.__hotplug_callback_dict)) self.hotplugDeregisterCallback(handle) pop = self.__close_set.pop while True: @@ -2426,7 +2293,7 @@ )) fd_index += 1 finally: - _free(pollfd_p_p) + libusb1.libusb_free_pollfds(pollfd_p_p) return result @_validContext @@ -2520,30 +2387,37 @@ @_validContext def tryLockEvents(self): - """ - See libusb_try_lock_events doc. - """ + warnings.warn( + 'You may not be able to unlock in the event of USBContext exit. ' + 'Consider looping over handleEvents() in a thread.', + DeprecationWarning, + ) return libusb1.libusb_try_lock_events(self.__context_p) @_validContext def lockEvents(self): - """ - See libusb_lock_events doc. - """ + warnings.warn( + 'You may not be able to unlock in the event of USBContext exit. ' + 'Consider looping over handleEvents() in a thread.', + DeprecationWarning, + ) libusb1.libusb_lock_events(self.__context_p) @_validContext def lockEventWaiters(self): - """ - See libusb_lock_event_waiters doc. - """ + warnings.warn( + 'You may not be able to unlock in the event of USBContext exit. ' + 'Consider looping over handleEvents() in a thread.', + DeprecationWarning, + ) libusb1.libusb_lock_event_waiters(self.__context_p) @_validContext def waitForEvent(self, tv=0): - """ - See libusb_wait_for_event doc. - """ + warnings.warn( + 'Consider looping over handleEvents() in a thread.', + DeprecationWarning, + ) if tv is None: tv = 0 tv_s = int(tv) @@ -2552,30 +2426,38 @@ @_validContext def unlockEventWaiters(self): - """ - See libusb_unlock_event_waiters doc. - """ + warnings.warn( + 'This method will lock in the event of USBContext exit, ' + 'preventing libusb lock release. ' + 'Consider looping over handleEvents() in a thread.', + DeprecationWarning, + ) libusb1.libusb_unlock_event_waiters(self.__context_p) @_validContext def eventHandlingOK(self): - """ - See libusb_event_handling_ok doc. - """ + warnings.warn( + 'Consider looping over handleEvents() in a thread.', + DeprecationWarning, + ) return libusb1.libusb_event_handling_ok(self.__context_p) @_validContext def unlockEvents(self): - """ - See libusb_unlock_events doc. - """ + warnings.warn( + 'This method will lock in the event of USBContext exit, ' + 'preventing libusb lock release. ' + 'Consider looping over handleEvents() in a thread.', + DeprecationWarning, + ) libusb1.libusb_unlock_events(self.__context_p) @_validContext def handleEventsLocked(self): - """ - See libusb_handle_events_locked doc. - """ + warnings.warn( + 'Consider looping over handleEvents() in a thread.', + DeprecationWarning, + ) # XXX: does tv parameter need to be exposed ? mayRaiseUSBError(libusb1.libusb_handle_events_locked( self.__context_p, _zero_tv_p, @@ -2583,9 +2465,10 @@ @_validContext def eventHandlerActive(self): - """ - See libusb_event_handler_active doc. - """ + warnings.warn( + 'Consider looping over handleEvents() in a thread.', + DeprecationWarning, + ) return libusb1.libusb_event_handler_active(self.__context_p) @staticmethod diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libusb1-1.7.1/usb1/_version.py new/libusb1-1.9.1/usb1/_version.py --- old/libusb1-1.7.1/usb1/_version.py 2019-05-10 00:52:33.000000000 +0200 +++ new/libusb1-1.9.1/usb1/_version.py 2020-12-09 14:48:08.655121600 +0100 @@ -9,11 +9,11 @@ version_json = ''' { - "date": "2019-05-09T22:49:01+0000", + "date": "2020-12-09T13:47:19+0000", "dirty": false, "error": null, - "full-revisionid": "4826b68986cf75e7ffb0e7a5ba739eecbddc3cc1", - "version": "1.7.1" + "full-revisionid": "aa6bc1220d9a9bf43745917d3f263426d6624777", + "version": "1.9.1" } ''' # END VERSION_JSON diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libusb1-1.7.1/usb1/libusb1.py new/libusb1-1.9.1/usb1/libusb1.py --- old/libusb1-1.7.1/usb1/libusb1.py 2019-05-10 00:49:51.000000000 +0200 +++ new/libusb1-1.9.1/usb1/libusb1.py 2020-11-29 10:11:16.000000000 +0100 @@ -24,25 +24,14 @@ Declares all constants, data structures and exported symbols. Locates and loads libusb1 dynamic library. """ -from ctypes import Structure, LittleEndianStructure, \ - CFUNCTYPE, POINTER, addressof, sizeof, cast, \ - c_short, c_int, c_uint, c_size_t, c_long, \ - c_uint8, c_uint16, c_uint32, \ - c_void_p, c_char_p, py_object, pointer, c_char -try: - from ctypes import c_ssize_t -except ImportError: - from ctypes import c_longlong - # c_ssize_t is new in Python 2.7 - if sizeof(c_int) == sizeof(c_size_t): - c_ssize_t = c_int - elif sizeof(c_long) == sizeof(c_size_t): - c_ssize_t = c_long - elif sizeof(c_longlong) == sizeof(c_size_t): - c_ssize_t = c_longlong - else: - raise ValueError('Unsupported arch: sizeof(c_size_t) = %r' % ( - sizeof(c_size_t), )) +from ctypes import ( + Structure, LittleEndianStructure, + CFUNCTYPE, POINTER, addressof, sizeof, cast, + c_short, c_int, c_uint, c_size_t, c_long, + c_uint8, c_uint16, c_uint32, + c_void_p, c_char_p, py_object, pointer, c_char, + c_ssize_t, CDLL +) import ctypes.util import platform import os.path @@ -140,13 +129,6 @@ return '%s [%s]' % (libusb_error.get(self.value, 'Unknown error'), self.value) -if sys.version_info[0] == 3: - _string_item_to_int = lambda x: x - _empty_char_p = bytes() -else: - _string_item_to_int = ord - _empty_char_p = '' - c_uchar = c_uint8 c_int_p = POINTER(c_int) @@ -165,12 +147,14 @@ else: dll_loader = ctypes.CDLL suffix = system == 'Darwin' and '.dylib' or '.so' - loader_kw = {} - if sys.version_info[:2] >= (2, 6): - loader_kw['use_errno'] = True - loader_kw['use_last_error'] = True + filename = 'libusb-1.0' + suffix + # If this is a binary wheel, use the integrated libusb unconditionally. + # To use the libusb from the Python installation or the OS, install from sdist: + # > pip install --no-binary :all: libusb1 + if os.path.exists(os.path.join(os.path.dirname(__file__), filename)): + filename = os.path.join(os.path.dirname(__file__), filename) try: - return dll_loader('libusb-1.0' + suffix, **loader_kw) + return dll_loader(filename, use_errno=True, use_last_error=True) except OSError: libusb_path = None base_name = 'usb-1.0' @@ -194,7 +178,7 @@ libusb_path = ctypes.util.find_library(base_name) if libusb_path is None: raise - return dll_loader(libusb_path, **loader_kw) + return dll_loader(libusb_path, use_errno=True, use_last_error=True) libusb = _loadLibrary() @@ -737,7 +721,7 @@ try: libusb_get_version = libusb.libusb_get_version except AttributeError: - _dummy_version = libusb_version(0, 0, 0, 0, _empty_char_p, _empty_char_p) + _dummy_version = libusb_version(0, 0, 0, 0, b'', b'') _dummy_version_p = pointer(_dummy_version) def libusb_get_version(): return _dummy_version_p @@ -963,7 +947,7 @@ def libusb_control_transfer_get_data(transfer_p): transfer = transfer_p.contents - return buffer_at(transfer.buffer.value, transfer.length)[ + return buffer_at(transfer.buffer, transfer.length)[ LIBUSB_CONTROL_SETUP_SIZE:] def libusb_control_transfer_get_setup(transfer_p): @@ -1103,10 +1087,10 @@ result = [] extra_length = descriptor.extra_length if extra_length: - extra = buffer_at(descriptor.extra.value, extra_length) + extra = buffer_at(descriptor.extra, extra_length) append = result.append while extra: - length = _string_item_to_int(extra[0]) + length = extra[0] if not 0 < length <= len(extra): raise ValueError( 'Extra descriptor %i is incomplete/invalid' % ( @@ -1271,6 +1255,16 @@ libusb_pollfd_added_cb_p, libusb_pollfd_removed_cb_p, py_object] libusb_set_pollfd_notifiers.restype = None +try: + #void libusb_get_pollfds(const struct libusb_pollfd **); + libusb_free_pollfds = libusb.libusb_free_pollfds + libusb_free_pollfds.argtypes = [libusb_pollfd_p_p] + libusb_free_pollfds.restype = None +except AttributeError: + # Not a safe replacement in general, but the versions of libusb that lack + # libusb_free_pollfds() only provide that function on *nix, where + # Python's free() and libusb's free() are ~always the same anyways. + libusb_free_pollfds = CDLL(None).free #typedef int libusb_hotplug_callback_handle; libusb_hotplug_callback_handle = c_int diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libusb1-1.7.1/usb1/testUSB1.py new/libusb1-1.9.1/usb1/testUSB1.py --- old/libusb1-1.7.1/usb1/testUSB1.py 2019-05-10 00:49:51.000000000 +0200 +++ new/libusb1-1.9.1/usb1/testUSB1.py 2020-12-05 03:36:31.000000000 +0100 @@ -18,8 +18,6 @@ import unittest import sys import itertools -import select -import threading import usb1 import libusb1 from ctypes import pointer @@ -43,25 +41,6 @@ 'usb1.USBContext() fails - no USB bus on system ?' ) -class PollDetector(object): - def __init__(self, *args, **kw): - try: - poll = select.poll - except AttributeError: - raise unittest.SkipTest('select.poll missing') - self.__poll = poll(*args, **kw) - self.__event = threading.Event() - - def poll(self, *args, **kw): - self.__event.set() - return self.__poll.poll(*args, **kw) - - def wait(self, *args, **kw): - self.__event.wait(*args, **kw) - - def __getattr__(self, name): - return getattr(self.__poll, name) - class USBTransferTests(unittest.TestCase): @staticmethod def getTransfer(iso_packets=0): @@ -200,52 +179,7 @@ got_callback = transfer.getCallback() self.assertEqual(callback, got_callback) - def testUSBPollerThreadExit(self): - """ - USBPollerThread must exit by itself when context is destroyed. - """ - with USBContext() as context: - poll_detector = PollDetector() - try: - poller = usb1.USBPollerThread(context, poll_detector) - except OSError: - raise unittest.SkipTest('libusb without file descriptor events') - poller.start() - poll_detector.wait(1) - poller.join(1) - self.assertFalse(poller.is_alive()) - - def testUSBPollerThreadException(self): - """ - USBPollerThread exception handling. - """ - class FakeEventPoll(PollDetector): - # pylint: disable=method-hidden - def poll(self, *args, **kw): - self.poll = super(FakeEventPoll, self).poll - return ['dummy'] - # pylint: enable=method-hidden - with USBContext() as context: - def fakeHandleEventsLocked(): - raise usb1.USBError(0) - context.handleEventsLocked = fakeHandleEventsLocked - exception_event = threading.Event() - exception_list = [] - def exceptionHandler(exc): - exception_list.append(exc) - exception_event.set() - try: - poller = usb1.USBPollerThread( - context, FakeEventPoll(), exceptionHandler) - except OSError: - raise unittest.SkipTest('libusb without file descriptor events') - poller.start() - exception_event.wait(1) - self.assertTrue(exception_list, exception_list) - self.assertTrue(poller.is_alive()) - - @staticmethod - def testDescriptors(): + def _testDescriptors(self, get_extra=False): """ Test descriptor walk. Needs any usb device, which won't be opened. @@ -253,6 +187,7 @@ with USBContext() as context: device_list = context.getDeviceList(skip_on_error=True) found = False + seen_extra = False for device in device_list: device.getBusNumber() device.getPortNumber() @@ -262,12 +197,26 @@ for endpoint in settings: pass for configuration in device.iterConfigurations(): + if get_extra and len(configuration.getExtra()) > 0: + seen_extra = True for interface in configuration: for settings in interface: + if get_extra and len(settings.getExtra()) > 0: + seen_extra = True for endpoint in settings: + if get_extra and len(endpoint.getExtra()) > 0: + seen_extra = True found = True if not found: raise unittest.SkipTest('descriptor walk test did not complete') + if get_extra and not seen_extra: + raise unittest.SkipTest('did not see any extra descriptors') + + def testDescriptors(self): + self._testDescriptors() + + def testDescriptorsWithExtra(self): + self._testDescriptors(get_extra=True) def testDefaultEnumScope(self): """
