blob: c90fb0191b4fdc62f925688f80d037cc1c963f9f [file] [log] [blame]
# Copyright (C) 2010-2021 Vincent Pelletier <plr.vincent@gmail.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# 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 find_packages
from setuptools import setup
from setuptools import Command
from codecs import open
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 = (
'620cec4dbe4868202949294157da5adb75c9fbb4f04266146fc833eef85f90fb'
)
cmdclass = versioneer.get_cmdclass()
class upload(Command):
"""
Declaw "setup.py upload".
"""
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
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')
if not url.endswith('.7z'):
raise ValueError('unexpected extension: %r' % (url, ))
build_dir = os.path.join(os.path.dirname(__file__), 'build')
download_cache_path = os.path.join(build_dir, 'download-cache')
if not os.path.exists(download_cache_path):
os.makedirs(download_cache_path)
url_basename = urlsplit(url).path.rsplit('/', 1)[-1]
archive_path = os.path.join(download_cache_path, url_basename)
if not os.path.exists(archive_path):
for suffix in ('', '.asc'):
with open(archive_path + suffix, 'wb') as archive_file:
archive_file.write(urlopen(url + suffix).read())
# py2 does not have subprocess.DEVNULL.
with open(os.devnull, 'wb') as devnull:
# to build/update trustedkeys-libusb.kbx:
# gpg --no-default-keyring --keyring trustedkeys-libusb.kbx --receive-keys ...
subprocess.check_call(
[
'gpgv',
'--keyring', 'trustedkeys-libusb.kbx',
archive_path + '.asc', archive_path,
],
# gnupg will not shut its pie hole.
stderr=devnull,
close_fds=True,
)
# This check is for the maintainer to notice a new release, and
# to retrospectively confirm that a release was done with files
# from a certain archive (and not just any signed release).
# It is *not* to check file authenticity (for this, we have gpg).
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,
)
)
for arch_path, out_dir in (
('VS2019/MS32/dll/libusb-1.0.dll', os.path.join(build_dir, 'win32')),
('VS2019/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()
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=cmdclass,
author='Vincent Pelletier',
author_email='plr.vincent@gmail.com',
url='http://github.com/vpelletier/python-libusb1',
license='LGPLv2.1+',
platforms=['any'],
py_modules=['libusb1'],
packages=find_packages(),
package_data={
"usb1": ["libusb-1.0.dll"],
},
entry_points={
'pyinstaller40': [
'hook-dirs=usb1.__pyinstaller:get_hook_dirs',
'tests=usb1.__pyinstaller:get_PyInstaller_tests']
},
classifiers=[
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)',
'Operating System :: OS Independent',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Topic :: Software Development :: Libraries',
'Topic :: System :: Hardware :: Hardware Drivers',
],
setup_requires=(
['wheel']
if 'bdist_wheel' in sys.argv else
[]
),
use_2to3=True,
test_suite='usb1.testUSB1',
)