diff options
Diffstat (limited to 'setup.py')
-rwxr-xr-x | setup.py | 206 |
1 files changed, 2 insertions, 204 deletions
@@ -1,208 +1,6 @@ | |||
1 | #!/usr/bin/env python | 1 | #!/usr/bin/env python |
2 | 2 | ||
3 | import os | 3 | import setuptools |
4 | import math | ||
5 | import shutil | ||
6 | import subprocess | ||
7 | from distutils import log | ||
8 | from distutils.core import Command | ||
9 | from setuptools.command.test import test | ||
10 | from distutils.errors import DistutilsError | ||
11 | from setuptools import setup, find_packages | ||
12 | 4 | ||
13 | 5 | ||
14 | class Release(Command): | 6 | setuptools.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 | |||
33 | class 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 | |||
104 | class 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 | |||
164 | setup( | ||
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 | ) | ||