-
Notifications
You must be signed in to change notification settings - Fork 3
/
setup.py
225 lines (194 loc) · 8.58 KB
/
setup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
AUTHOR = "Sri Kadimisetty"
AUTHOR_EMAIL = "[email protected]"
NAME = "action-hero"
VERSION = "0.7.0"
DESCRIPTION = "Make powerful CLIs with argparse actions that pack a punch! "
URL = "https://github.com/kadimisetty/action-hero"
LICENSE = "MIT"
PYTHON_REQUIRES = ">=3.5.0"
README_FILENAME = "README.md"
INSTALL_REQUIRES = ["requests", "pyyaml"]
CLASSIFIERS = [
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Software Development :: Libraries",
"Topic :: Terminals",
"Natural Language :: English",
]
# INSTRUCTIONS
# ------------
# 1. Setup setup.py values in uppercase above the fold
# 2. Use command `$ python setup.py make` to clean/build/check/publish
# ---------------- STAY ABOVE THE FOLD ------------------>o--------------------
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ Stay above the fold. For under, swim dangerous sharks ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ above-the-fold v0.0.1 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ What are you doing down here? ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ Didn't I just warn you about dangerous sharks? ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ Have you even seen Jaws! or Jaws 2!! or Jaws 3D!!! or Jaws Revenge!!!! ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ If you insist on going anyway — you're gonna need a bigger boat ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
# CONTENTS BELOW THE FOLD
# -----------------------
# 1. Helpers to extract long description from README.
# 2. Custom setuptools.Command `make` to clean/build/check/publish.
# 3. setup.py filled in with values specified above the fold.
import os # noqa: E402 # pylint: disable=C0413
import pathlib # noqa: E402 # pylint: disable=C0413
import shutil # noqa: E402 # pylint: disable=C0413
import sys # noqa: E402 # pylint: disable=C0413
from setuptools import find_packages # noqa: E402 # pylint: disable=C0413
from setuptools import setup # noqa: E402 # pylint: disable=C0413
from setuptools import Command # noqa: E402 # pylint: disable=C0413
def get_long_description(readme_filename=README_FILENAME):
"""Return contents of long description from contents of filename"""
with open(readme_filename, "r", encoding="utf-8") as readme:
return readme.read()
def get_long_description_content_type(filename=README_FILENAME):
"""Return content-type of long description from content-type of filename"""
suffix = pathlib.Path(filename).suffix
content_types = {"md": "text/markdown", "rst": "text/x-rst"}
return content_types.get(suffix, "text/plain")
class MakeCommand(Command):
"""Add command `make` to upload to PyPi
setuptools runs the function `run` which will in turn, with confirmation,
do clean, build, check and publish.
Credits:
- http://code.nabla.net/doc/setuptools/api/setuptools/ \
setuptools.Command.html
- https://setuptools.readthedocs.io/en/latest/setuptools.html? \
highlight=Command#adding-commands
- Inspired by @kennethreitz/setup.py
"""
description = "clean/build/check/publish project to PyPi"
user_options = []
def initialize_options(self):
"""Set default values for all the options supported by command"""
def finalize_options(self):
"""Set final values for all the options supported by command"""
@staticmethod
def display(update, state="normal"):
"""Print given update"""
state_symbols = {
"normal": "·",
"ended": "\N{check mark}",
"error": "!",
}
if state == "error":
print(
"setup.py "
+ "\x1b[1;31;40m"
+ "{}".format(state_symbols[state])
+ "\x1b[0m [Yn]:"
+ " {}".format(update)
)
else:
print("setup.py {} {}".format(state_symbols[state], update))
def run(self):
"""Runs the Command"""
for stage in ["clean", "build", "check", "publish"]:
# Run stage with confirmation
prompt = (
# "\x1b[5;30;42m "
"\x1b[1;37;44m "
+ "{}? ".format(stage).rjust(9)
+ "\x1b[0m [Yn]: "
)
if input(prompt) in "yY":
getattr(self, stage)()
else:
self.display("skipping {}".format(stage))
sys.exit()
def publish(self):
"""Publish to PyPi"""
task = "publishing to PyPi with twine"
self.display(task)
if os.system("twine upload dist/*") == 0:
self.display("finished " + task, state="ended")
else:
self.display(
"failed " + task + ". Please fix. Exiting…", state="error"
)
sys.exit()
def check(self):
"""Check with twine"""
task = "checking with twine"
self.display(task)
if os.system("twine check dist/*") == 0:
self.display("finished " + task, state="ended")
else:
self.display(
"failed " + task + ". Please fix. Exiting…", state="error"
)
sys.exit()
def build(self):
"""Build"""
task = "building source and wheel distribution"
try:
self.display(task, state="normal")
os.system("{0} setup.py sdist bdist_wheel".format(sys.executable))
self.display("finished " + task, state="ended")
except OSError:
self.display(
"failed " + task + ". Please fix. Exiting…", state="error"
)
sys.exit()
def clean(self):
"""Remove previous builds"""
task = "removing previous builds"
try:
self.display(task, state="normal")
shutil.rmtree("dist")
self.display("finished " + task, state="ended")
except FileNotFoundError:
self.display("no previous builds found.", state="error")
except OSError:
self.display(
"failed " + task + ". Please fix. Exiting…", state="error"
)
sys.exit()
setup(
name=NAME,
version=VERSION,
description=DESCRIPTION,
long_description=get_long_description(),
long_description_content_type=get_long_description_content_type(),
author=AUTHOR,
author_email=AUTHOR_EMAIL,
python_requires=PYTHON_REQUIRES,
url=URL,
license=LICENSE,
packages=find_packages(exclude=["tests"]),
include_package_data=True,
install_requires=INSTALL_REQUIRES,
classifiers=CLASSIFIERS,
cmdclass={"make": MakeCommand},
)