aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Crute <mike@crute.us>2020-06-09 01:07:31 +0000
committerMike Crute <mike@crute.us>2020-06-09 02:25:32 +0000
commitf6714a399003e660d310172391dfb762ea306b00 (patch)
tree9eaae019ca5dcbb7b6e23ac775e066fa990a3084
parente42c95b978a83a1ba48020b6d84218f2f17b5db4 (diff)
downloadpydora-f6714a399003e660d310172391dfb762ea306b00.tar.bz2
pydora-f6714a399003e660d310172391dfb762ea306b00.tar.xz
pydora-f6714a399003e660d310172391dfb762ea306b00.zip
Convert build system to tox
This is the current modern way to build, package, and test python code.
-rw-r--r--.github/workflows/build.yml6
-rw-r--r--.github/workflows/release.yml23
-rw-r--r--.gitignore3
-rw-r--r--CONTRIBUTING.rst2
-rw-r--r--pandora/__init__.py1
-rw-r--r--setup.cfg82
-rwxr-xr-xsetup.py206
7 files changed, 114 insertions, 209 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 0f63125..f3833be 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -13,6 +13,7 @@ jobs:
13 os: 13 os:
14 - ubuntu-latest 14 - ubuntu-latest
15 - macos-latest 15 - macos-latest
16
16 python-version: 17 python-version:
17 - 3.5 18 - 3.5
18 - 3.6 19 - 3.6
@@ -26,5 +27,6 @@ jobs:
26 with: 27 with:
27 python-version: ${{ matrix.python-version }} 28 python-version: ${{ matrix.python-version }}
28 29
29 - run: pip install -U pip setuptools wheel mock nose pytest 30 - run: |
30 - run: python setup.py release 31 pip install tox
32 tox -e tests,release
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..f47c613
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,23 @@
1name: release
2
3on:
4 push:
5 tags:
6 - 'release-*'
7
8jobs:
9 build:
10 runs-on: ubuntu-latest
11
12 steps:
13 - uses: actions/checkout@v2
14
15 - uses: actions/setup-python@v2
16 with:
17 python-version: 3.8
18
19 - env:
20 TWINE_PASSWORD: ${{ secrets.PYPI_API_KEY }}
21 run: |
22 pip install tox
23 tox -e tests,release,upload
diff --git a/.gitignore b/.gitignore
index 720ed08..8e383bc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,9 +2,8 @@
2.coverage/ 2.coverage/
3.eggs/ 3.eggs/
4.py3/ 4.py3/
5.sandbox_name 5.tox/
6build/ 6build/
7coverage.xml
8dist/ 7dist/
9htmlcov/ 8htmlcov/
10pydora.egg-info/ 9pydora.egg-info/
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 7e95437..2671c63 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -16,5 +16,5 @@ your changes. To have the best experience contributing, please:
16All code is reviewed before acceptance and changes may be requested to better 16All code is reviewed before acceptance and changes may be requested to better
17follow the conventions of the existing API. 17follow the conventions of the existing API.
18 18
19The build system runs ``python setup.py release`` on all supported Python 19The build system runs ``tox -e tests,release`` on all supported Python
20versions. You can, and should, run this on your pull request before submitting. 20versions. You can, and should, run this on your pull request before submitting.
diff --git a/pandora/__init__.py b/pandora/__init__.py
index e69de29..159d48b 100644
--- a/pandora/__init__.py
+++ b/pandora/__init__.py
@@ -0,0 +1 @@
__version__ = "2.0.1"
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..a6c5c6d
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,82 @@
1[metadata]
2name = pydora
3version = attr: pandora.__version__
4description = Python wrapper for Pandora API
5long_description = file: README.rst
6author = Mike Crute
7author_email = mike@crute.us
8url = https://github.com/mcrute/pydora
9classifiers =
10 Development Status :: 5 - Production/Stable
11 Environment :: Console
12 Intended Audience :: Developers
13 Intended Audience :: End Users/Desktop
14 License :: OSI Approved :: MIT License
15 Operating System :: OS Independent
16 Programming Language :: Python :: 3
17 Programming Language :: Python :: 3.5
18 Programming Language :: Python :: 3.6
19 Programming Language :: Python :: 3.7
20 Programming Language :: Python :: 3.8
21 Programming Language :: Python :: 3 :: Only
22 Topic :: Internet :: WWW/HTTP
23 Topic :: Multimedia :: Sound/Audio :: Players
24
25[options]
26packages = find:
27python_requires = >=3.5
28
29install_requires =
30 requests >=2, <3
31 blowfish >=0.6.1, <1.0
32
33[options.packages.find]
34exclude =
35 tests
36 tests.*
37
38[options.entry_points]
39distutils.commands =
40 pydora = pydora.player:main
41 pydora-configure = pydora.configure:main
42
43[testenv:format]
44deps =
45 black
46
47commands =
48 black -l 79 -t py35 pandora/ pydora/ tests/ setup.py
49
50[testenv:tests]
51deps =
52 pytest
53 black
54 flake8 >=3.3
55 coverage >=4.1, <5
56
57commands =
58 black --check -l 79 -t py35 pandora/ pydora/ tests/ setup.py
59 flake8 --statistics --ignore=E231 pandora/ pydora/ tests/ setup.py
60 coverage run --source='pandora/,pydora/' -m pytest
61 coverage report --fail-under 100 -m --include='pandora/*'
62 coverage report -m --include='pydora/*'
63 coverage html --include='pandora/*,pydora/*'
64
65[testenv:release]
66deps =
67 wheel
68
69commands =
70 python setup.py sdist bdist_wheel
71
72[testenv:upload]
73skip_install = true
74
75deps =
76 twine
77
78passenv =
79 TWINE_PASSWORD
80
81commands =
82 twine upload -u __token__ --non-interactive --skip-existing dist/*
diff --git a/setup.py b/setup.py
index d7344c5..f5a3845 100755
--- a/setup.py
+++ b/setup.py
@@ -1,208 +1,6 @@
1#!/usr/bin/env python 1#!/usr/bin/env python
2 2
3import os 3import setuptools
4import math
5import shutil
6import subprocess
7from distutils import log
8from distutils.core import Command
9from setuptools.command.test import test
10from distutils.errors import DistutilsError
11from setuptools import setup, find_packages
12 4
13 5
14class Release(Command): 6setuptools.setup()
15
16 user_options = []
17 description = "build and test package with linting"
18
19 def initialize_options(self):
20 pass
21
22 def finalize_options(self):
23 pass
24
25 def run(self):
26 self.run_command("test")
27
28 # Flake8 should examine tests too
29 self.distribution.packages = find_packages()
30 self.run_command("flake8")
31
32
33class TestsWithCoverage(test):
34
35 description = "run unit tests with coverage"
36
37 coverage_goal = 100
38 missed_branches_goal = 0
39 partial_branches_goal = 0
40
41 def initialize_options(self):
42 super().initialize_options()
43 self.missed_coverage_goals = False
44
45 def enforce_coverage_goals(self, rel_path, analysis):
46 # There is no coverage goal for the player package, just the API
47 if os.path.split(rel_path)[0] == "pydora":
48 return
49
50 coverage_percent = math.ceil(analysis.numbers.pc_covered)
51 if coverage_percent != self.coverage_goal:
52 self.missed_coverage_goals = True
53 self.announce(
54 "Coverage: {!r} coverage is {}%, goal is {}%".format(
55 rel_path, coverage_percent, self.coverage_goal
56 ),
57 log.ERROR,
58 )
59
60 missed_branches = analysis.numbers.n_missing_branches
61 if missed_branches != self.missed_branches_goal:
62 self.missed_coverage_goals = True
63 self.announce(
64 "Coverage: {!r} missed branch count is {}, goal is {}".format(
65 rel_path, missed_branches, self.missed_branches_goal
66 ),
67 log.ERROR,
68 )
69
70 partially_covered_branches = analysis.numbers.n_partial_branches
71 if partially_covered_branches != self.partial_branches_goal:
72 self.missed_coverage_goals = True
73 self.announce(
74 "Coverage: {!r} partial branch count is {}, goal is {}".format(
75 rel_path,
76 partially_covered_branches,
77 self.partial_branches_goal,
78 ),
79 log.ERROR,
80 )
81
82 def run(self):
83 from coverage import Coverage
84
85 cov = Coverage(source=self.distribution.packages, branch=True)
86
87 cov.start()
88 super().run()
89 cov.stop()
90
91 # Save HTML report for debugging missed coverage
92 cov.html_report()
93
94 # Print coverage report to console for CI log
95 cov.report()
96
97 for rep in cov._get_file_reporters():
98 self.enforce_coverage_goals(rep.relname, cov._analyze(rep))
99
100 if self.missed_coverage_goals:
101 raise DistutilsError("Project missed coverage goals")
102
103
104class PyPiReleaseCommand(Command):
105
106 user_options = []
107 description = "build and release artifacts to pypi"
108
109 def initialize_options(self):
110 pass
111
112 def finalize_options(self):
113 pass
114
115 def venv_run(self, cmd, *args):
116 subprocess.check_call((os.path.join(".release/py3/bin", cmd),) + args)
117
118 def make_release_tree(self):
119 if not os.path.exists(".release"):
120 log.info("Creating temp release tree")
121 os.mkdir(".release")
122
123 def configure_environment(self):
124 log.info("Configuring release environment")
125 subprocess.check_call(["python3", "-m", "venv", ".release/py3"])
126 self.venv_run(
127 "pip", "install", "-U", "pip", "setuptools", "virtualenv", "twine"
128 )
129
130 def build_py3_artifact(self):
131 log.info("Building Python 3 Artifact")
132 self.venv_run(
133 "python",
134 "setup.py",
135 "release",
136 "bdist_wheel",
137 "--python-tag",
138 "py3",
139 )
140
141 def build_sdist_artifact(self):
142 log.info("Building Source Dist Artifact")
143 self.venv_run("python", "setup.py", "sdist")
144
145 def upload_artifacts(self):
146 log.info("Uploading artifacts to PyPi")
147 self.venv_run("twine", "upload", "dist/*")
148
149 def cleanup(self):
150 log.info("Cleaning up temp release tree")
151 shutil.rmtree(".release")
152
153 def run(self):
154 try:
155 self.make_release_tree()
156 self.configure_environment()
157 self.build_py3_artifact()
158 self.build_sdist_artifact()
159 self.upload_artifacts()
160 finally:
161 self.cleanup()
162
163
164setup(
165 name="pydora",
166 version="2.0.0",
167 description="Python wrapper for Pandora API",
168 long_description=open("README.rst", "r").read(),
169 author="Mike Crute",
170 author_email="mike@crute.us",
171 url="https://github.com/mcrute/pydora",
172 test_suite="tests.discover_suite",
173 packages=find_packages(exclude=["tests", "tests.*"]),
174 cmdclass={
175 "test": TestsWithCoverage,
176 "pypi_release": PyPiReleaseCommand,
177 "release": Release,
178 },
179 entry_points={
180 "console_scripts": [
181 "pydora = pydora.player:main",
182 "pydora-configure = pydora.configure:main",
183 ],
184 },
185 setup_requires=[
186 "wheel",
187 "flake8>=3.3",
188 "setuptools>=36.0.1",
189 "coverage>=4.1,<5",
190 ],
191 install_requires=["requests>=2,<3", "blowfish>=0.6.1,<1.0",],
192 python_requires=">=3.5",
193 classifiers=[
194 "Development Status :: 5 - Production/Stable",
195 "Environment :: Console",
196 "Intended Audience :: Developers",
197 "Intended Audience :: End Users/Desktop",
198 "License :: OSI Approved :: MIT License",
199 "Operating System :: OS Independent",
200 "Programming Language :: Python :: 3",
201 "Programming Language :: Python :: 3.5",
202 "Programming Language :: Python :: 3.6",
203 "Programming Language :: Python :: 3.7",
204 "Programming Language :: Python :: 3 :: Only",
205 "Topic :: Internet :: WWW/HTTP",
206 "Topic :: Multimedia :: Sound/Audio :: Players",
207 ],
208)