build: move to PEP 517

The build backend remains setuptools (for now).

Additionally, setuptools_scm is adopted, in place of our previous ad-hoc
handling of extracting version information from git.  This plugin also
provides some interesting extra features, like automatic inclusion of
all versioned data files; now MANIFEST.in only needs to specify the very
few files to exclude from the source distribution.

On the other hand, the DIST_NAME and DIST_PACKAGE environment variables
are currently not being used.  Their main purpose is somewhat fulfilled
with platform.platform(); and by not using them the new build setup can
be completely declarative, requiring users to run no custom code or ours
when building or installing liquidctl.

As the build backend is setuptools, setup.cfg is used for metadata and
other backend configuration, per the current setuptools docs.[^1]  This
also means that we have yet not moved to PEP 621 ("Storing project
metadata in pyproject.toml").[^2]

To build the sdist and universal wheel, use python-build.[^3] Locally,
pip is still a suitable way to install, and --editable mode is still
supported. But when re-packing for Linux or other distributions,
consider python-installer.[^4][^5][^6]

[^1]: https://setuptools.pypa.io/en/latest/build_meta.html
[^2]: https://www.python.org/dev/peps/pep-0621/
[^3]: https://github.com/pypa/build
[^4]: https://github.com/pradyunsg/installer
[^5]: https://lists.archlinux.org/pipermail/arch-dev-public/2022-February/030737.html
[^6]: https://wiki.archlinux.org/title/Python_package_guidelines#Standards_based_(PEP_517)
This commit is contained in:
Jonas Malaco 2022-02-23 19:14:53 -03:00
parent 67e8893e80
commit 3d05977353
10 changed files with 125 additions and 173 deletions

View File

@ -33,23 +33,22 @@ jobs:
if: matrix.os == 'macos-latest'
run: |
brew install libusb
- name: Install Python dependencies
- name: Install build and test tools
run: |
python -m pip install --upgrade pip
python setup.py egg_info
pip install -r liquidctl.egg-info/requires.txt
python -m pip install --upgrade pip pytest
- name: Install the package and its dependencies
run: |
python -m pip install .
- name: Run unit tests and module doctests
run: |
pip install pytest
XDG_RUNTIME_DIR=.tests_rundir pytest
- name: Install and run the resulting executable
XDG_RUNTIME_DIR=.tests_rundir python -m pytest
- name: Run the resulting executable
run: |
pip install .
liquidctl list --verbose --debug
- name: Lint with flake8
run: |
pip install flake8
python -m pip install flake8
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 . --extend-exclude vtest,vinstall --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=120 --statistics
flake8 . --extend-exclude vtest,vinstall --count --exit-zero --max-complexity=10 --max-line-length=120 --statistics

11
.gitignore vendored
View File

@ -1,7 +1,6 @@
*.egg-info
*.egg-info/
.krakenduty-poc
__pycache__
build
dist
liquidctl/extraversion.py
.coverage
__pycache__/
build/
dist/
liquidctl/_version.py

View File

@ -1,9 +1,2 @@
include CHANGELOG.md
include LICENSE.txt
include liquidctl.8
include pytest.ini
recursive-include docs *
recursive-include extra *
recursive-include tests *
global-exclude *.pyc
exclude appveyor.yml
recursive-exclude .github *

View File

@ -30,16 +30,14 @@ install:
# libusb
- cmd: appveyor DownloadFile https://github.com/libusb/libusb/releases/download/v%LIBUSB_VERSION%/libusb-%LIBUSB_VERSION%.7z -FileName libusb.7z
- cmd: 7z x libusb.7z
# python build and package tools
- cmd: C:\Python310-x64\python -m pip install --upgrade pip setuptools --ignore-installed
# remaining dependencies
- cmd: C:\Python310-x64\python setup.py install
# install pytest
- cmd: C:\Python310-x64\python -m pip install pytest
# build and test tools
- cmd: C:\Python310-x64\python -m pip install --upgrade pip pytest
# copy the libusb DLLs
- cmd: copy VS2019\MS64\Release\dll\* C:\Windows\System32\
# project and dependencies
- cmd: C:\Python310-x64\python -m pip install .
build: off
test_script:
# copy the libusb DLLs and run the unit and doctests
- cmd: copy VS2019\MS64\Release\dll\* C:\Windows\System32\
- cmd: C:\Python310-x64\python -m pytest

View File

@ -36,9 +36,10 @@ Then install locally and:
## Source distribution
- [ ] Generate the source distribution:
`python setup.py sdist`
- [ ] Check that all necessary files are in `dist/liquidctl-$VERSION.tar.gz` and that the generated `extraversion.py` makes sense
- [ ] Build the source distribution and wheel:
`python -m build`
- [ ] Check that all necessary files are in the `dist/liquidctl-$VERSION.tar.gz` sdist
- [ ] Check the `dist/liquidctl-$VERSION.whl` wheel
- [ ] Tag HEAD with changelog and PGP signature:
`git tag -as "v$VERSION"`
- [ ] Push HEAD and vVERSION tag:

View File

@ -84,6 +84,7 @@ from liquidctl.error import NotSupportedByDevice, NotSupportedByDriver, UnsafeFe
from liquidctl.util import color_from_str
from liquidctl.version import __version__
# conversion from CLI arg to internal option; as options as forwarded to bused
# and drivers, they must:
# - have no default value in the CLI level (not forwarded unless explicitly set);
@ -297,23 +298,6 @@ def _make_opts(args):
return opts
def _gen_version():
extra = None
try:
from liquidctl.extraversion import __extraversion__
if __extraversion__['editable']:
extra = ['editable']
elif __extraversion__['dist_name'] and __extraversion__['dist_package']:
extra = [__extraversion__['dist_name'], __extraversion__['dist_package']]
else:
extra = [__extraversion__['commit'][:12]]
if __extraversion__['dirty']:
extra[0] += '-dirty'
except:
return f'liquidctl v{__version__}'
return f'liquidctl v{__version__} ({"; ".join(extra)})'
def _log_requirements():
_LOGGER.debug('python: %s', sys.version)
if sys.hexversion >= 0x03080000:
@ -372,7 +356,7 @@ def main():
args = docopt(__doc__)
if args['--version']:
print(_gen_version())
print(f'liquidctl v{__version__} ({platform.platform()})')
sys.exit(0)
if args['--debug']:
@ -411,7 +395,7 @@ def main():
log_handler.setFormatter(log_fmtter)
logging.basicConfig(level=log_level, handlers=[log_handler])
_LOGGER.debug('%s', _gen_version())
_LOGGER.debug('liquidctl: %s', __version__)
_LOGGER.debug('platform: %s', platform.platform())
_log_requirements()

View File

@ -1 +1,32 @@
__version__ = '1.8.1'
# uses the psf/black style
def _get_version_relaxed():
# try to get the version written by setuptools_scm during the build
try:
from liquidctl._version import version
return version
except ModuleNotFoundError:
pass
# if that fails, try to compute the version directly
from setuptools_scm import get_version
# first assuming that we are on a git checkout
try:
return get_version()
except LookupError:
pass
# and then, if that also fails, assuming that we are on a tarball
return get_version(parentdir_prefix_version="liquidctl-") + "-guessed"
try:
__version__ = _get_version_relaxed()
except:
# if everything fails, or if we couldn't import get_version(), use a
# placeholder value that's obviously invalid
__version__ = "0.0.0-unknown"

View File

@ -1,3 +1,15 @@
[build-system]
requires = [
"setuptools >= 45",
"setuptools_scm[toml] >= 6.2",
"wheel",
]
build-backend = "setuptools.build_meta"
[tool.setuptools_scm]
write_to = "liquidctl/_version.py"
version_scheme = "post-release"
[tool.pytest.ini_options]
addopts = "--doctest-modules -ra"
@ -40,7 +52,7 @@ extend-exclude = '''
| (^/liquidctl/keyval\.py$)
| (^/liquidctl/pmbus\.py$)
| (^/liquidctl/util\.py$)
| (^/liquidctl/version\.py$)
| (^/liquidctl/_version\.py$)
| (^/setup\.py$)
| (^/tests/_testutils\.py$)
| (^/tests/test_api\.py$)

50
setup.cfg Normal file
View File

@ -0,0 +1,50 @@
[metadata]
name = liquidctl
url = https://github.com/liquidctl/liquidctl
description = Cross-platform tool and drivers for liquid coolers and other devices
author = Jonas Malaco
author_email = jonas@protocubo.io
classifiers =
Development Status :: 5 - Production/Stable
Intended Audience :: Developers
Intended Audience :: End Users/Desktop
License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Operating System :: OS Independent
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Topic :: System :: Hardware :: Hardware Drivers
keywords =
cli
corsair
cross-platform
driver
evga
fan-controller
gigabyte
hue2
kraken
led-controller
liquid-cooler
nzxt
power-supply
smart-device
project_urls:
Documentation = https://github.com/liquidctl/liquidctl/blob/main/README.md
Changelog = https://github.com/liquidctl/liquidctl/blob/main/CHANGELOG.md
[options]
packages = find:
pythons_requires = >=3.7
setup_requires = setuptools_scm
install_requires =
colorlog
docopt
hidapi
pyusb
smbus; sys_platform == "linux"
[options.entry_points]
console_scripts =
liquidctl = liquidctl.cli:main

115
setup.py
View File

@ -1,115 +0,0 @@
import os
import subprocess
import sys
import setuptools
from setuptools.command.develop import develop
def get_static_version():
"""Read manually attributed version number.
Note: the version number only changes when releases are made."""
with open('liquidctl/version.py', 'r') as fv:
vals = {}
exec(fv.read(), vals)
return vals['__version__']
def make_pypi_long_description(doc_url):
"""Generate custom long description for PyPI."""
with open('README.md', 'r', encoding='utf-8') as fh:
continuation = ('For which devices are supported, installation instructions, '
'a guide to the CLI and device specific details, check the '
'complete [Documentation]({}).').format(doc_url)
long_description = (fh.read().split('<!-- stop here for PyPI -->', 1)[0]
+ continuation)
return long_description
def get_git_version():
"""Check that `git` is accessible and return its version."""
try:
return subprocess.check_output(['git', '--version']).strip().decode()
except:
return None
def make_extraversion(editable=False):
"""Compile extra version information for use at runtime.
Additional information will include:
- values of DIST_NAME and DIST_PACKAGE environment variables
- whether the installation is running in develop/editable mode
- git HEAD commit hash and whether the tree is dirty
"""
extra = {}
extra['dist_name'] = os.getenv('DIST_NAME')
extra['dist_package'] = os.getenv('DIST_PACKAGE')
extra['editable'] = editable
if get_git_version() and os.path.isdir('.git'):
rev_parse = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip().decode()
describe = subprocess.check_output(['git', 'describe', '--always', '--dirty']).strip().decode()
extra['commit'] = rev_parse
extra['dirty'] = describe.endswith('-dirty')
with open('liquidctl/extraversion.py', 'w') as fv:
fv.write('__extraversion__ = {!r}'.format(extra))
class custom_develop(develop):
def run(self):
make_extraversion(editable=True)
super().run()
HOME = 'https://github.com/liquidctl/liquidctl'
VERSION = get_static_version()
SUPPORTED_URL = '{}/tree/v{}#supported-devices'.format(HOME, VERSION)
DOC_URL = '{}/tree/v{}#liquidctl--liquid-cooler-control'.format(HOME, VERSION)
CHANGES_URL = '{}/blob/v{}/CHANGELOG.md'.format(HOME, VERSION)
make_extraversion()
install_requires = ['docopt', 'pyusb', 'hidapi', 'colorlog']
if sys.platform == 'linux':
install_requires.append('smbus')
setuptools.setup(
name='liquidctl',
cmdclass={'develop': custom_develop},
version=VERSION,
author='Jonas Malaco',
author_email='jonas@protocubo.io',
description='Cross-platform tool and drivers for liquid coolers and other devices',
long_description=make_pypi_long_description(DOC_URL),
long_description_content_type='text/markdown',
url=HOME,
packages=setuptools.find_packages(),
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: End Users/Desktop',
'Intended Audience :: Developers',
'Topic :: System :: Hardware :: Hardware Drivers',
'Operating System :: OS Independent',
'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
],
keywords='cross-platform cli driver corsair evga nzxt liquid-cooler fan-controller '
'power-supply led-controller kraken smart-device hue2 gigabyte',
project_urls={
'Supported devices': SUPPORTED_URL,
'Documentation': DOC_URL,
'Changelog': CHANGES_URL,
},
install_requires=install_requires,
python_requires='>=3.7',
entry_points={
'console_scripts': [
'liquidctl=liquidctl.cli:main',
],
},
)