Commit 7d26503c authored by juga  's avatar juga
Browse files

fix: Move to declarative setup.cfg

Also:
- Update versioneer
- And include other source distribution files in MANIFEST.in
- Add project URLs
- Add formatter and linter dependencies and configurations.
- tox: Remove travis, fix python environments
- tox: Remove extra coverage options and add them in .coveragerc.
parent de2154d4
[run]
omit = */__init__.py
source = sbws
sbws/_version.py export-subst
include *.md
include *.rst
include *.ini
recursive-include docs *
prune docs/build
recursive-include docs Makefile make.bat
recursive-include sbws *.ini
recursive-include tests *
recursive-exclude **/__pycache__ *
include versioneer.py
recursive-exclude * *.py[co]
prune docs/build
[tool.black]
line-length = 79
target-version = ['py36', 'py37', 'py38']
exclude = '''
/(
docs
| .*__init__\.py
| .*_version\.py
)/
'''
[tool.isort]
line_length = 79
# Compatibility with black
# profile = black # does not seem to work
multi_line_output = 3
include_trailing_comma = true
force_grid_wrap = 0
use_parentheses = true
ensure_newline_before_comments = true
src_paths = "sbws,tests"
skip = "versioneer.py,docs,sbws/_version.py,sbws/__init__.py"
......@@ -6,7 +6,7 @@
# that just contains the computed version number.
# This file is released into the public domain. Generated by
# versioneer-0.18 (https://github.com/warner/python-versioneer)
# versioneer-0.19 (https://github.com/python-versioneer/python-versioneer)
"""Git implementation of _version.py."""
......@@ -57,7 +57,7 @@ HANDLERS = {}
def register_vcs_handler(vcs, method): # decorator
"""Decorator to mark a method as the handler for a particular VCS."""
"""Create decorator to mark a method as the handler of a VCS."""
def decorate(f):
"""Store f in HANDLERS[vcs][method]."""
if vcs not in HANDLERS:
......@@ -93,9 +93,7 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False,
if verbose:
print("unable to find command, tried %s" % (commands,))
return None, None
stdout = p.communicate()[0].strip()
if sys.version_info[0] >= 3:
stdout = stdout.decode()
stdout = p.communicate()[0].strip().decode()
if p.returncode != 0:
if verbose:
print("unable to run %s (error)" % dispcmd)
......@@ -165,6 +163,10 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose):
raise NotThisMethod("no keywords at all, weird")
date = keywords.get("date")
if date is not None:
# Use only the last line. Previous lines may contain GPG signature
# information.
date = date.splitlines()[-1]
# git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant
# datestamp. However we prefer "%ci" (which expands to an "ISO-8601
# -like" string, which we must then edit to make compliant), because
......@@ -300,6 +302,9 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
# commit date: see ISO-8601 comment in git_versions_from_keywords()
date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"],
cwd=root)[0].strip()
# Use only the last line. Previous lines may contain GPG signature
# information.
date = date.splitlines()[-1]
pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1)
return pieces
......@@ -338,18 +343,18 @@ def render_pep440(pieces):
def render_pep440_pre(pieces):
"""TAG[.post.devDISTANCE] -- No -dirty.
"""TAG[.post0.devDISTANCE] -- No -dirty.
Exceptions:
1: no tags. 0.post.devDISTANCE
1: no tags. 0.post0.devDISTANCE
"""
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"]:
rendered += ".post.dev%d" % pieces["distance"]
rendered += ".post0.dev%d" % pieces["distance"]
else:
# exception #1
rendered = "0.post.dev%d" % pieces["distance"]
rendered = "0.post0.dev%d" % pieces["distance"]
return rendered
......@@ -385,7 +390,7 @@ def render_pep440_old(pieces):
The ".dev0" means dirty.
Eexceptions:
Exceptions:
1: no tags. 0.postDISTANCE[.dev0]
"""
if pieces["closest-tag"]:
......
[metadata]
name = sbws
description = Simple Bandwidth Scanner
author = Matt Traudt, juga
author_email = {pastly, juga}@torproject.org
license = CC0
url = gitlab.torproject.org/tpo/network-health/sbws
keywords = tor onion bandwidth measurements scanner relay circuit
classifiers =
Development Status :: 4 - Beta
Environment :: Console
Intended Audience :: Developers
Intended Audience :: System Administrators
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX :: Linux
Programming Language :: Python :: 3
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
long_description = file: README.md
license_files = LICENSE.md
project_urls =
Documentation = sbws.readthedocs.org
Source = gitlab.torproject.org/tpo/network-health/sbws
Tracker = gitlab.torproject.org/tpo/network-health/sbws/-/issues
[options]
packages = find:
include_package_data = True
# See stable releases at https://www.python.org/downloads/
python_requires = >= 3.6
install_requires =
stem >= 1.7.0
; # Now versioneer is also needed as dependency
versioneer
requests[socks]
[options.extras_require]
test =
black
coverage
flake8
flake8-docstrings
freezegun
isort
; pylint ; when we ever fix all the errors it throughs
pytest
tox
sphinx
doc =
sphinx
pylint
recommonmark
dev =
flake8
flake8-docstrings
isort
vulture
[options.entry_points]
console_scripts =
sbws = sbws.sbws:main
[tool:pytest]
log_cli=true
log_cli_level=DEBUG
[flake8]
max-line-length = 79
# D103 Missing docstring
# D400: First line should end with a period (not 't')
# D401: First line should be in imperative mood
# Compatibility with black
# W503 line break before binary operator
# E203 whitespace before ':'
extend-ignore = E203, W503, D1, D2, D4
exclude = docs/*,sbws/_version.py,sbws/__init__.py,versioneer.py
[coverage:run]
# Do not give error on empty __init__ files
omit = */__init__.py
source = sbws
[aliases]
# Define setup.py command aliases here
test = pytest
# See the docstring in versioneer.py for instructions. Note that you must
# re-run 'versioneer.py setup' after changing this section, and commit the
# resulting files.
......@@ -15,7 +104,3 @@ versionfile_build = sbws/_version.py
tag_prefix = v
# String at the start of all unpacked tarball filenames.
parentdir_prefix = sbws-
[tool:pytest]
log_cli=true
log_cli_level=DEBUG
#!/usr/bin/env python3
# Always prefer setuptools over distutils
from setuptools import setup, find_packages
# To use a consistent encoding
from codecs import open
import os
# To generate the version at build time based on
# git describe --tags --dirty --always
"""The setup script."""
import setuptools
import versioneer
here = os.path.abspath(os.path.dirname(__file__))
def long_description():
with open(os.path.join(here, 'README.md'), encoding='utf-8') as f:
return f.read()
def get_package_data():
# Example that grabs all *.ini files in the cwd and all files in foo/bar
# other_files = ['*.ini']
# for r, _, fs in os.walk(os.path.join(here, 'foo', 'bar')):
# for f in fs:
# other_files.append(os.path.join(r, f))
# return other_files
return [
'config.default.ini',
'config.log.default.ini',
]
def get_data_files():
pass
setup(
name='sbws',
version=versioneer.get_version(),
cmdclass=versioneer.get_cmdclass(),
description='Simple Bandwidth Scanner',
long_description=long_description(),
long_description_content_type="text/markdown",
author='Matt Traudt, juga',
author_email='{pastly, juga}@torproject.org',
license='CC0',
url="https://gitweb.torproject.org/sbws.git",
classifiers=[
'Development Status :: 4 - Beta',
"Environment :: Console",
'Intended Audience :: Developers',
'Intended Audience :: System Administrators',
'Operating System :: OS Independent',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Topic :: System :: Networking',
],
packages=find_packages(),
include_package_data=True,
package_data={
'sbws': get_package_data(),
},
data_files=get_data_files(),
keywords='tor onion bandwidth measurements scanner relay circuit',
python_requires='>=3.5',
entry_points={
'console_scripts': [
'sbws = sbws.sbws:main',
]
},
install_requires=[
'stem>=1.7.0',
'requests[socks]',
],
extras_require={
# vulture: find unused code
'dev': ['flake8', 'vulture'],
'test': ['tox', 'pytest', 'coverage', 'freezegun'],
# recommonmark: to make sphinx render markdown
'doc': ['sphinx', 'recommonmark', 'pylint'],
},
setuptools.setup(
version=versioneer.get_version(), cmdclass=versioneer.get_cmdclass()
)
......@@ -12,6 +12,7 @@ wget -O/dev/null http://127.0.0.1:28888/sbws.bin
sbws -c tests/integration/sbws_testnet.ini scanner
sbws -c tests/integration/sbws_testnet.ini generate
# Run integration tests
coverage run -a --rcfile=.coveragerc --source=sbws -m pytest -s tests/integration -vv
python -m coverage run --append --module pytest -svv tests/integration
sbws -c tests/integration/sbws_testnet.ini cleanup
tests/integration/stop_chutney.sh
[tox]
skip_missing_interpreters = True
envlist = py{36, 37, 38, 39, 310}, inst, setup, integration, lint, stats, doc
envlist =
py{36, 37, 38, 39, 310}
inst,
setup,
black,
isort,
flake8,
doc,
stats
[travis]
python =
3.6: py36, inst, setup, unit, integration, lint, doc
3.7: py37, inst, setup, unit, integration, lint, doc
3.8: py38, inst, setup, unit, integration, lint, doc
3.9: py39, inst, setup, unit, integration, lint, doc
nightly: pynightly, inst, setup, unit, integration, lint, doc
; [testenv]
# install_command can be removed when --process-dependency-links is not
# needed anymore, and this section commented
# install_command = pip install {opts} {packages}
[testenv]
; Installing with deps errors with versioneer
; deps = .[test]
skip_install = True
commands =
pip install .[test]
; Use python -m to use the binary from the virtualenv if it is also
; installed in the system. Do not use {envbindir} since it would require
; to install it in tox virtualenv
python -m coverage run --append --module pytest -svv tests/unit
# test that it can be installed with custom commands and clean env
[testenv:inst]
skip_install = True
commands =
# this will fail until --process-dependency-links is not needed
# it needs to be commented since error code will be still 1
- pip install .
ignore_errors = True
recreate = True
......@@ -32,42 +34,48 @@ skip_install = True
commands = python setup.py install
recreate = True
[testenv]
deps = .[test]
commands =
coverage run -a --rcfile={toxinidir}/.coveragerc --source=sbws -m pytest \
-s {toxinidir}/tests/unit -vv
[testenv:integration]
ignore_errors = True
deps = .[test]
whitelist_externals =
bash
commands =
# For some reason .[test] is not copying config.* files
pip install .
bash -c tests/integration/run.sh {envtmpdir}/chutney
[testenv:lint]
[testenv:black]
skip_install = True
deps =
black
commands =
black --check --diff sbws tests
[testenv:isort]
skip_install = True
deps =
isort
commands =
isort --check-only --diff sbws tests
[testenv:flake8]
skip_install = True
deps = .[dev]
commands = flake8 sbws scripts tests
deps = flake8-docstrings
commands =
flake8 sbws tests
[testenv:clean]
skip_install = True
changedir={toxinidir}
deps = coverage
command = coverage erase
changedir = {toxinidir}
commands = python -m coverage erase
[testenv:stats]
skip_install = True
changedir={toxinidir}
deps = .[test]
deps = coverage
commands=
# nothing to combine while not using several python versions
# coverage combine
coverage report
coverage html
; nothing to combine while not using several python versions
; python -m coverage combine
python -m coverage report
python -m coverage html
[testenv:doc]
deps = .[doc]
......@@ -75,11 +83,11 @@ whitelist_externals = make
changedir = docs
commands =
make html
# this requires build the pdf images
# make latexpdf
make man
; this requires build the pdf images
; make latexpdf
; make man
# this requires Internet, it should not be in envlist
; this requires Internet, it should not be in envlist
[testenv:doclinks]
deps = .[doc]
whitelist_externals = make
......
# Version: 0.18
# Version: 0.19
"""The Versioneer - like a rocketeer, but for versions.
......@@ -7,16 +7,12 @@ The Versioneer
==============
* like a rocketeer, but for versions!
* https://github.com/warner/python-versioneer
* https://github.com/python-versioneer/python-versioneer
* Brian Warner
* License: Public Domain
* Compatible With: python2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, and pypy
* [![Latest Version]
(https://pypip.in/version/versioneer/badge.svg?style=flat)
](https://pypi.python.org/pypi/versioneer/)
* [![Build Status]
(https://travis-ci.org/warner/python-versioneer.png?branch=master)
](https://travis-ci.org/warner/python-versioneer)
* Compatible with: Python 3.6, 3.7, 3.8, 3.9 and pypy3
* [![Latest Version][pypi-image]][pypi-url]
* [![Build Status][travis-image]][travis-url]
This is a tool for managing a recorded version number in distutils-based
python projects. The goal is to remove the tedious and error-prone "update
......@@ -27,9 +23,10 @@ system, and maybe making new tarballs.
## Quick Install
* `pip install versioneer` to somewhere to your $PATH
* add a `[versioneer]` section to your setup.cfg (see below)
* `pip install versioneer` to somewhere in your $PATH
* add a `[versioneer]` section to your setup.cfg (see [Install](INSTALL.md))
* run `versioneer install` in your source tree, commit the results
* Verify version information with `python setup.py version`
## Version Identifiers
......@@ -61,7 +58,7 @@ version 1.3). Many VCS systems can report a description that captures this,
for example `git describe --tags --dirty --always` reports things like
"0.7-1-g574ab98-dirty" to indicate that the checkout is one revision past the
0.7 tag, has a unique revision id of "574ab98", and is "dirty" (it has
uncommitted changes.
uncommitted changes).
The version identifier is used for multiple purposes:
......@@ -166,7 +163,7 @@ which may help identify what went wrong).
Some situations are known to cause problems for Versioneer. This details the
most significant ones. More can be found on Github
[issues page](https://github.com/warner/python-versioneer/issues).
[issues page](https://github.com/python-versioneer/python-versioneer/issues).
### Subprojects
......@@ -180,7 +177,7 @@ two common reasons why `setup.py` might not be in the root:
`setup.cfg`, and `tox.ini`. Projects like these produce multiple PyPI
distributions (and upload multiple independently-installable tarballs).
* Source trees whose main purpose is to contain a C library, but which also
provide bindings to Python (and perhaps other langauges) in subdirectories.
provide bindings to Python (and perhaps other languages) in subdirectories.
Versioneer will look for `.git` in parent directories, and most operations
should get the right version string. However `pip` and `setuptools` have bugs
......@@ -194,9 +191,9 @@ work too.
Pip-8.1.1 is known to have this problem, but hopefully it will get fixed in
some later version.
[Bug #38](https://github.com/warner/python-versioneer/issues/38) is tracking
[Bug #38](https://github.com/python-versioneer/python-versioneer/issues/38) is tracking
this issue. The discussion in
[PR #61](https://github.com/warner/python-versioneer/pull/61) describes the
[PR #61](https://github.com/python-versioneer/python-versioneer/pull/61) describes the
issue from the Versioneer side in more detail.
[pip PR#3176](https://github.com/pypa/pip/pull/3176) and
[pip PR#3615](https://github.com/pypa/pip/pull/3615) contain work to improve
......@@ -224,22 +221,10 @@ regenerated while a different version is checked out. Many setup.py commands
cause egg_info to be rebuilt (including `sdist`, `wheel`, and installing into
a different virtualenv), so this can be surprising.
[Bug #83](https://github.com/warner/python-versioneer/issues/83) describes
[Bug #83](https://github.com/python-versioneer/python-versioneer/issues/83) describes
this one, but upgrading to a newer version of setuptools should probably
resolve it.
### Unicode version strings
While Versioneer works (and is continually tested) with both Python 2 and
Python 3, it is not entirely consistent with bytes-vs-unicode distinctions.
Newer releases probably generate unicode version strings on py2. It's not
clear that this is wrong, but it may be surprising for applications when then
write these strings to a network connection or include them in bytes-oriented
APIs like cryptographic checksums.
[Bug #71](https://github.com/warner/python-versioneer/issues/71) investigates
this question.
## Updating Versioneer
......@@ -265,6 +250,12 @@ installation by editing setup.py . Alternatively, it might go the other
direction and include code from all supported VCS systems, reducing the
number of intermediate scripts.
## Similar projects
* [setuptools_scm](https://github.com/pypa/setuptools_scm/) - a non-vendored build-time
dependency
* [minver](https://github.com/jbweston/miniver) - a lightweight reimplementation of
versioneer
## License
......@@ -274,13 +265,15 @@ Specifically, both are released under the Creative Commons "Public Domain
Dedication" license (CC0-1.0), as described in
https://creativecommons.org/publicdomain/zero/1.0/ .
[pypi-image]: https://img.shields.io/pypi/v/versioneer.svg
[pypi-url]: https://pypi.python.org/pypi/versioneer/
[travis-image]:
https://img.shields.io/travis/com/python-versioneer/python-versioneer.svg
[travis-url]: https://travis-ci.com/github/python-versioneer/python-versioneer
"""
from __future__ import print_function
try:
import configparser
except ImportError:
import ConfigParser as configparser
import configparser
import errno
import json
import os
......@@ -339,9 +332,9 @@ def get_config_from_root(root):
# configparser.NoOptionError (if it lacks "VCS="). See the docstring at
# the top of versioneer.py for instructions on writing your setup.cfg .
setup_cfg = os.path.join(root, "setup.cfg")
parser = configparser.SafeConfigParser()
parser = configparser.ConfigParser()
with open(setup_cfg, "r") as f:
parser.readfp(f)
parser.read_file(f)
VCS = parser.get("versioneer", "VCS") # mandatory
def get(parser, name):
......@@ -371,7 +364,7 @@ HANDLERS = {}
def register_vcs_handler(vcs, method): # decorator
"""Decorator to mark a method as the handler for a particular VCS."""
"""Create decorator to mark a method as the handler of a VCS."""
def decorate(f):
"""Store f in HANDLERS[vcs][method]."""
if vcs not in HANDLERS:
......@@ -407,9 +400,7 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False,
if verbose:
print("unable to find command, tried %s" % (commands,))
return None, None
stdout = p.communicate()[0].strip()
if sys.version_info[0] >= 3:
stdout = stdout.decode()
stdout = p.communicate()[0].strip().decode()
if p.returncode != 0:
if verbose:
print("unable to run %s (error)" % dispcmd)
......@@ -418,7 +409,7 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False,
return stdout, p.returncode
LONG_VERSION_PY['git'] = '''
LONG_VERSION_PY['git'] = r'''
# This file helps to compute a version number in source trees obtained from
# git-archive tarball (such as those provided by githubs download-from-tag
# feature). Distribution tarballs (built by setup.py sdist) and build
......@@ -426,7 +417,7 @@ LONG_VERSION_PY['git'] = '''
# that just contains the computed version number.
# This file is released into the public domain. Generated by
# versioneer-0.18 (https://github.com/warner/python-versioneer)
# versioneer-0.19 (https://github.com/python-versioneer/python-versioneer)
"""Git implementation of _version.py."""
......@@ -477,7 +468,7 @@ HANDLERS = {}
def register_vcs_handler(vcs, method): # decorator
"""Decorator to mark a method as the handler for a particular VCS."""
"""Create decorator to mark a method as the handler of a VCS."""
def decorate(f):
"""Store f in HANDLERS[vcs][method]."""
if vcs not in HANDLERS:
......@@ -513,9 +504,7 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False,
if verbose:
print("unable to find command, tried %%s" %% (commands,))
return None, None
stdout = p.communicate()[0].strip()
if sys.version_info[0] >= 3:
stdout = stdout.decode()
stdout = p.communicate()[0].strip().decode()
if p.returncode != 0:
if verbose:
print("unable to run %%s (error)" %% dispcmd)
......@@ -585,6 +574,10 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose):
raise NotThisMethod("no keywords at all, weird")
date = keywords.get("date")
if date is not None: