aboutsummaryrefslogtreecommitdiff
path: root/setup.py
diff options
context:
space:
mode:
Diffstat (limited to 'setup.py')
-rwxr-xr-xsetup.py206
1 files changed, 2 insertions, 204 deletions
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)