Skip to content

Commit b167bef

Browse files
committed
Migrate to setup.cfg
1 parent 6532c1f commit b167bef

File tree

8 files changed

+196
-314
lines changed

8 files changed

+196
-314
lines changed

MANIFEST.in

-4
This file was deleted.

Makefile

+12-76
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,18 @@
44
PYTHON=python
55
PIP=pip
66
PYTEST=py.test
7-
COVERAGE=coverage
87
TWINE=twine
98
PYFLAGS=
109
DEST_DIR=/
1110

12-
# Horrid hack to ensure setuptools is installed in our python environment. This
13-
# is necessary with Python 3.3's venvs which don't install it by default.
14-
ifeq ($(shell python -c "import setuptools" 2>&1),)
15-
SETUPTOOLS:=
16-
else
17-
SETUPTOOLS:=$(shell wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | $(PYTHON))
18-
endif
19-
2011
# Calculate the base names of the distribution, the location of all source,
2112
# documentation, packaging, icon, and executable script files
2213
NAME:=$(shell $(PYTHON) $(PYFLAGS) setup.py --name)
2314
VER:=$(shell $(PYTHON) $(PYFLAGS) setup.py --version)
24-
ifeq ($(shell lsb_release -si),Ubuntu)
25-
DEB_SUFFIX:=ubuntu1
26-
else
27-
DEB_SUFFIX:=
28-
endif
29-
DEB_ARCH:=$(shell dpkg --print-architecture)
3015
PYVER:=$(shell $(PYTHON) $(PYFLAGS) -c "import sys; print('py%d.%d' % sys.version_info[:2])")
3116
PY_SOURCES:=$(shell \
3217
$(PYTHON) $(PYFLAGS) setup.py egg_info >/dev/null 2>&1 && \
3318
grep -v "\.egg-info" $(NAME).egg-info/SOURCES.txt)
34-
DEB_SOURCES:=debian/changelog \
35-
debian/control \
36-
debian/copyright \
37-
debian/rules \
38-
debian/docs \
39-
$(wildcard debian/*.init) \
40-
$(wildcard debian/*.default) \
41-
$(wildcard debian/*.manpages) \
42-
$(wildcard debian/*.docs) \
43-
$(wildcard debian/*.doc-base) \
44-
$(wildcard debian/*.desktop)
4519
DOC_SOURCES:=docs/conf.py \
4620
$(wildcard docs/*.png) \
4721
$(wildcard docs/*.svg) \
@@ -56,17 +30,6 @@ SUBDIRS:=
5630
DIST_WHEEL=dist/$(NAME)-$(VER)-py2.py3-none-any.whl
5731
DIST_TAR=dist/$(NAME)-$(VER).tar.gz
5832
DIST_ZIP=dist/$(NAME)-$(VER).zip
59-
DIST_DEB=dist/python-$(NAME)_$(VER)$(DEB_SUFFIX)_all.deb \
60-
dist/python3-$(NAME)_$(VER)$(DEB_SUFFIX)_all.deb \
61-
dist/python-$(NAME)-doc_$(VER)$(DEB_SUFFIX)_all.deb \
62-
dist/$(NAME)_$(VER)$(DEB_SUFFIX)_$(DEB_ARCH).build \
63-
dist/$(NAME)_$(VER)$(DEB_SUFFIX)_$(DEB_ARCH).buildinfo \
64-
dist/$(NAME)_$(VER)$(DEB_SUFFIX)_$(DEB_ARCH).changes
65-
DIST_DSC=dist/$(NAME)_$(VER)$(DEB_SUFFIX).tar.xz \
66-
dist/$(NAME)_$(VER)$(DEB_SUFFIX).dsc \
67-
dist/$(NAME)_$(VER)$(DEB_SUFFIX)_source.build \
68-
dist/$(NAME)_$(VER)$(DEB_SUFFIX)_source.buildinfo \
69-
dist/$(NAME)_$(VER)$(DEB_SUFFIX)_source.changes
7033

7134

7235
# Default target
@@ -76,10 +39,9 @@ all:
7639
@echo "make test - Run tests"
7740
@echo "make doc - Generate HTML and PDF documentation"
7841
@echo "make source - Create source package"
79-
@echo "make egg - Generate a PyPI egg package"
42+
@echo "make wheel - Generate a PyPI wheel package"
8043
@echo "make zip - Generate a source zip package"
8144
@echo "make tar - Generate a source tar package"
82-
@echo "make deb - Generate Debian packages"
8345
@echo "make dist - Generate all packages"
8446
@echo "make clean - Get rid of all generated files"
8547
@echo "make release - Create and tag a new release"
@@ -102,9 +64,7 @@ zip: $(DIST_ZIP)
10264

10365
tar: $(DIST_TAR)
10466

105-
deb: $(DIST_DEB) $(DIST_DSC)
106-
107-
dist: $(DIST_WHEEL) $(DIST_DEB) $(DIST_DSC) $(DIST_TAR) $(DIST_ZIP)
67+
dist: $(DIST_WHEEL) $(DIST_TAR) $(DIST_ZIP)
10868

10969
develop:
11070
@# These have to be done separately to avoid a cockup...
@@ -113,18 +73,17 @@ develop:
11373
$(PIP) install -e .[doc,test]
11474

11575
test:
116-
$(COVERAGE) run --rcfile coverage.cfg -m $(PYTEST) tests -v -r sx
117-
$(COVERAGE) report --rcfile coverage.cfg
76+
$(PYTEST) tests
11877

11978
clean:
120-
dh_clean
121-
rm -fr dist/ $(NAME).egg-info/ tags
79+
rm -fr dist/ build/ .pytest_cache/ .mypy_cache/ $(NAME).egg-info/ tags .coverage
12280
for dir in $(SUBDIRS); do \
12381
$(MAKE) -C $$dir clean; \
12482
done
83+
find $(CURDIR) -name "*.pyc" -delete
12584

12685
tags: $(PY_SOURCES)
127-
ctags -R --exclude="build/*" --exclude="debian/*" --exclude="docs/*" --languages="Python"
86+
ctags -R --exclude="build/*" --exclude="docs/*" --languages="Python"
12887

12988
$(SUBDIRS):
13089
$(MAKE) -C $@
@@ -138,37 +97,14 @@ $(DIST_ZIP): $(PY_SOURCES) $(SUBDIRS)
13897
$(DIST_WHEEL): $(PY_SOURCES) $(SUBDIRS)
13998
$(PYTHON) $(PYFLAGS) setup.py bdist_wheel --universal
14099

141-
$(DIST_DEB): $(PY_SOURCES) $(SUBDIRS) $(DEB_SOURCES) $(DIST_TAR)
142-
cp $(DIST_TAR) ../$(NAME)_$(VER).orig.tar.gz
143-
debuild -b
144-
mkdir -p dist/
145-
for f in $(DIST_DEB); do cp ../$${f##*/} dist/; done
146-
147-
$(DIST_DSC): $(PY_SOURCES) $(SUBDIRS) $(DEB_SOURCES) $(DIST_TAR)
148-
cp $(DIST_TAR) ../$(NAME)_$(VER).orig.tar.gz
149-
debuild -S
150-
mkdir -p dist/
151-
for f in $(DIST_DSC); do cp ../$${f##*/} dist/; done
152-
153-
copyrights: $(PY_SOURCES) $(DOC_SOURCES)
154-
./copyrights
155-
156-
changelog: $(PY_SOURCES) $(DOC_SOURCES) $(DEB_SOURCES)
100+
release:
157101
$(MAKE) clean
158-
# ensure there are no current uncommitted changes
159102
test -z "$(shell git status --porcelain)"
160-
# update the debian changelog with new release information
161-
dch --newversion $(VER)$(DEB_SUFFIX)
162-
# commit the changes and add a new tag
163-
git commit debian/changelog -m "Updated changelog for release $(VER)"
164-
165-
release: $(DIST_DEB) $(DIST_DSC) $(DIST_TAR) $(DIST_WHEEL)
166103
git tag -s v$(VER) -m "Release v$(VER)"
167-
git push --tags
168-
# build a source archive and upload to PyPI
104+
git push origin v$(VER)
105+
106+
upload: $(DIST_TAR) $(DIST_WHEEL)
107+
$(TWINE) check $(DIST_TAR) $(DIST_WHEEL)
169108
$(TWINE) upload $(DIST_TAR) $(DIST_WHEEL)
170-
# build the deb source archive and upload to Raspbian
171-
dput raspberrypi dist/$(NAME)_$(VER)$(DEB_SUFFIX)_source.changes
172-
dput raspberrypi dist/$(NAME)_$(VER)$(DEB_SUFFIX)_$(DEB_ARCH).changes
173109

174-
.PHONY: all install develop test doc source egg wheel zip tar deb dist clean tags release upload $(SUBDIRS)
110+
.PHONY: all install develop test doc source wheel zip tar dist clean tags release upload $(SUBDIRS)

copyrights

+33-23
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@ derives the authorship and copyright years information from the git history
66
of the project; hence, this script must be run within a git repository.
77
"""
88

9+
from __future__ import annotations
10+
911
import os
1012
import sys
1113
assert sys.version_info >= (3, 6), 'Script requires Python 3.6+'
1214
import tempfile
15+
import typing as t
1316
from argparse import ArgumentParser, Namespace
1417
from configparser import ConfigParser
1518
from operator import attrgetter
@@ -18,14 +21,13 @@ from datetime import datetime
1821
from subprocess import Popen, PIPE, DEVNULL
1922
from pathlib import Path
2023
from fnmatch import fnmatch
21-
from typing import NamedTuple, Iterator, List, Tuple, Set, Union, Optional
2224

2325

2426
SPDX_PREFIX = 'SPDX-License-Identifier:'
2527
COPYRIGHT_PREFIX = 'Copyright (c)'
2628

2729

28-
def main(args: List[str] = None):
30+
def main(args: t.List[str] = None):
2931
if args is None:
3032
args = sys.argv[1:]
3133
config = get_config(args)
@@ -41,7 +43,7 @@ def main(args: List[str] = None):
4143
target.write(chunk)
4244

4345

44-
def get_config(args: List[str]) -> Namespace:
46+
def get_config(args: t.List[str]) -> Namespace:
4547
config = ConfigParser(
4648
defaults={
4749
'include': '**/*',
@@ -52,10 +54,10 @@ def get_config(args: List[str]) -> Namespace:
5254
'spdx_prefix': SPDX_PREFIX,
5355
'copy_prefix': COPYRIGHT_PREFIX,
5456
},
55-
delimiters=('=',), default_section='settings',
57+
delimiters=('=',), default_section='copyrights:settings',
5658
empty_lines_in_values=False, interpolation=None,
5759
converters={'list': lambda s: s.strip().splitlines() })
58-
config.read('copyrights.cfg')
60+
config.read('setup.cfg')
5961
sect = config[config.default_section]
6062

6163
parser = ArgumentParser(description=__doc__)
@@ -113,10 +115,10 @@ def get_config(args: List[str]) -> Namespace:
113115
return ns
114116

115117

116-
class Copyright(NamedTuple):
118+
class Copyright(t.NamedTuple):
117119
author: str
118120
email: str
119-
years: Set[int]
121+
years: t.Set[int]
120122

121123
def __str__(self):
122124
if len(self.years) > 1:
@@ -126,8 +128,8 @@ class Copyright(NamedTuple):
126128
return f'{years} {self.author} <{self.email}>'
127129

128130

129-
def get_copyrights(include: Set[str], exclude: Set[str])\
130-
-> Iterator[Tuple[Path, List[Copyright]]]:
131+
def get_copyrights(include: t.Set[str], exclude: t.Set[str])\
132+
-> t.Iterator[t.Tuple[Path, t.Container[Copyright]]]:
131133
sorted_blame = sorted(
132134
get_contributions(include, exclude),
133135
key=lambda c: (c.path, c.author, c.email)
@@ -147,15 +149,15 @@ def get_copyrights(include: Set[str], exclude: Set[str])\
147149
yield path, copyrights
148150

149151

150-
class Contribution(NamedTuple):
152+
class Contribution(t.NamedTuple):
151153
author: str
152154
email: str
153155
year: int
154156
path: Path
155157

156158

157-
def get_contributions(include: Set[str], exclude: Set[str])\
158-
-> Iterator[Contribution]:
159+
def get_contributions(include: t.Set[str], exclude: t.Set[str])\
160+
-> t.Iterator[Contribution]:
159161
for path in get_source_paths(include, exclude):
160162
blame = Popen(
161163
['git', 'blame', '--line-porcelain', 'HEAD', '--', str(path)],
@@ -186,7 +188,8 @@ def get_contributions(include: Set[str], exclude: Set[str])\
186188
assert blame.returncode == 0
187189

188190

189-
def get_source_paths(include: Set[str], exclude: Set[str]) -> Iterator[Path]:
191+
def get_source_paths(include: t.Set[str], exclude: t.Set[str])\
192+
-> t.Iterator[Path]:
190193
ls_tree = Popen(
191194
['git', 'ls-tree', '-r', '--name-only', 'HEAD'],
192195
stdout=PIPE, stderr=DEVNULL, universal_newlines=True)
@@ -203,9 +206,9 @@ def get_source_paths(include: Set[str], exclude: Set[str]) -> Iterator[Path]:
203206
assert ls_tree.returncode == 0
204207

205208

206-
class License(NamedTuple):
207-
ident: Optional[str]
208-
text: List[str]
209+
class License(t.NamedTuple):
210+
ident: t.Optional[str]
211+
text: t.List[str]
209212

210213

211214
def get_license(path: Path, *, spdx_prefix: str = SPDX_PREFIX) -> License:
@@ -253,20 +256,26 @@ class CopyWriter:
253256
'.sql': '--',
254257
}
255258

256-
def __init__(self, license='LICENSE.txt', preamble=(),
257-
spdx_prefix=SPDX_PREFIX, copy_prefix=COPYRIGHT_PREFIX):
259+
def __init__(self, license: Path=Path('LICENSE.txt'),
260+
preamble: t.List[str]=None,
261+
spdx_prefix: str=SPDX_PREFIX,
262+
copy_prefix: str=COPYRIGHT_PREFIX):
263+
if preamble is None:
264+
preamble = []
258265
self.license = get_license(license, spdx_prefix=spdx_prefix)
259266
self.preamble = preamble
260267
self.spdx_prefix = spdx_prefix
261268
self.copy_prefix = copy_prefix
262269

263270
@classmethod
264-
def from_config(cls, config):
271+
def from_config(cls, config: Namespace) -> CopyWriter:
265272
return cls(
266273
config.license, config.preamble,
267274
config.spdx_prefix, config.copy_prefix)
268275

269-
def transform(self, source, copyrights, *, comment_prefix=None):
276+
def transform(self, source: t.TextIO,
277+
copyrights: t.List[Copyright], *,
278+
comment_prefix: str=None) -> t.Iterator[str]:
270279
if comment_prefix is None:
271280
comment_prefix = self.COMMENTS[Path(source.name).suffix]
272281
license_start = self.license.text[0]
@@ -279,7 +288,7 @@ class CopyWriter:
279288
yield line
280289
empty = False
281290
elif linenum < 3 and (
282-
'set fileencoding=' in line or '-*- coding:' in line):
291+
'fileencoding=' in line or '-*- coding:' in line):
283292
yield line
284293
empty = False
285294
elif line.rstrip() == comment_prefix:
@@ -313,7 +322,8 @@ class CopyWriter:
313322
elif state == 'body':
314323
yield line
315324

316-
def _generate_header(self, copyrights, comment_prefix, empty):
325+
def _generate_header(self, copyrights: t.Iterable[Copyright],
326+
comment_prefix: str, empty: bool) -> t.Iterator[str]:
317327
if not empty:
318328
yield comment_prefix + '\n'
319329
for line in self.preamble:
@@ -356,7 +366,7 @@ class AtomicReplaceFile:
356366
If ``None`` (the default), the temporary file will be opened in binary
357367
mode. Otherwise, this specifies the encoding to use with text mode.
358368
"""
359-
def __init__(self, path: Union[str, Path], encoding: str = None):
369+
def __init__(self, path: t.Union[str, Path], encoding: str = None):
360370
if isinstance(path, str):
361371
path = Path(path)
362372
self._path = path

copyrights.cfg

-11
This file was deleted.

coverage.cfg

-18
This file was deleted.

0 commit comments

Comments
 (0)