Skip to content
This repository was archived by the owner on Sep 14, 2023. It is now read-only.

Commit 1d2118b

Browse files
committed
packaging: minimize setup.py
Remove all code added to setup.py that was added for building purposes, but which proved to cause weird errors while trying to install the package: SpecifierSet object has no attribute split
1 parent 255dee6 commit 1d2118b

File tree

1 file changed

+2
-326
lines changed

1 file changed

+2
-326
lines changed

setup.py

Lines changed: 2 additions & 326 deletions
Original file line numberDiff line numberDiff line change
@@ -1,330 +1,6 @@
1-
#!/usr/bin/env python
2-
# -*- coding: utf-8 -*-
3-
1+
# !/usr/bin/env python
42
import setuptools
53

6-
HAS_DIST_INFO_CMD = False
7-
try:
8-
import setuptools.command.dist_info
9-
10-
HAS_DIST_INFO_CMD = True
11-
except ImportError:
12-
"""Setuptools version is too old."""
13-
14-
15-
ALL_STRING_TYPES = tuple(map(type, ("", b"", u"")))
16-
MIN_NATIVE_SETUPTOOLS_VERSION = 34, 4, 0
17-
"""Minimal setuptools having good read_configuration implementation."""
18-
19-
RUNTIME_SETUPTOOLS_VERSION = tuple(map(int, setuptools.__version__.split(".")))
20-
"""Setuptools imported now."""
21-
22-
READ_CONFIG_SHIM_NEEDED = RUNTIME_SETUPTOOLS_VERSION < MIN_NATIVE_SETUPTOOLS_VERSION
23-
24-
25-
def str_if_nested_or_str(s):
26-
"""Turn input into a native string if possible."""
27-
if isinstance(s, ALL_STRING_TYPES):
28-
return str(s)
29-
if isinstance(s, (list, tuple)):
30-
return type(s)(map(str_if_nested_or_str, s))
31-
if isinstance(s, (dict,)):
32-
return stringify_dict_contents(s)
33-
return s
34-
35-
36-
def stringify_dict_contents(dct):
37-
"""Turn dict keys and values into native strings."""
38-
return {str_if_nested_or_str(k): str_if_nested_or_str(v) for k, v in dct.items()}
39-
40-
41-
if not READ_CONFIG_SHIM_NEEDED:
42-
from setuptools.config import read_configuration, ConfigOptionsHandler
43-
import setuptools.config
44-
import setuptools.dist
45-
46-
# Set default value for 'use_scm_version'
47-
setattr(setuptools.dist.Distribution, "use_scm_version", False)
48-
49-
# Attach bool parser to 'use_scm_version' option
50-
class ShimConfigOptionsHandler(ConfigOptionsHandler):
51-
"""Extension class for ConfigOptionsHandler."""
52-
53-
@property
54-
def parsers(self):
55-
"""Return an option mapping with default data type parsers."""
56-
_orig_parsers = super(ShimConfigOptionsHandler, self).parsers
57-
return dict(use_scm_version=self._parse_bool, **_orig_parsers)
58-
59-
def parse_section_packages__find(self, section_options):
60-
find_kwargs = super(
61-
ShimConfigOptionsHandler, self
62-
).parse_section_packages__find(section_options)
63-
return stringify_dict_contents(find_kwargs)
64-
65-
setuptools.config.ConfigOptionsHandler = ShimConfigOptionsHandler
66-
else:
67-
"""This is a shim for setuptools<required."""
68-
import functools
69-
import io
70-
import json
71-
import sys
72-
import warnings
73-
74-
try:
75-
import setuptools.config
76-
77-
def filter_out_unknown_section(i):
78-
def chi(self, *args, **kwargs):
79-
i(self, *args, **kwargs)
80-
self.sections = {
81-
s: v for s, v in self.sections.items() if s != "packages.find"
82-
}
83-
84-
return chi
85-
86-
setuptools.config.ConfigHandler.__init__ = filter_out_unknown_section(
87-
setuptools.config.ConfigHandler.__init__
88-
)
89-
except ImportError:
90-
pass
91-
92-
def ignore_unknown_options(s):
93-
@functools.wraps(s)
94-
def sw(**attrs):
95-
try:
96-
ignore_warning_regex = (
97-
r"Unknown distribution option: "
98-
r"'(license_file|project_urls|python_requires)'"
99-
)
100-
warnings.filterwarnings(
101-
"ignore",
102-
message=ignore_warning_regex,
103-
category=UserWarning,
104-
module="distutils.dist",
105-
)
106-
return s(**attrs)
107-
finally:
108-
warnings.resetwarnings()
109-
110-
return sw
111-
112-
def parse_predicates(python_requires):
113-
import itertools
114-
import operator
115-
116-
sorted_operators_map = tuple(
117-
sorted(
118-
{
119-
">": operator.gt,
120-
"<": operator.lt,
121-
">=": operator.ge,
122-
"<=": operator.le,
123-
"==": operator.eq,
124-
"!=": operator.ne,
125-
"": operator.eq,
126-
}.items(),
127-
key=lambda i: len(i[0]),
128-
reverse=True,
129-
)
130-
)
131-
132-
def is_decimal(s):
133-
return type(u"")(s).isdecimal()
134-
135-
conditions = map(str.strip, python_requires.split(","))
136-
for c in conditions:
137-
for op_sign, op_func in sorted_operators_map:
138-
if not c.startswith(op_sign):
139-
continue
140-
raw_ver = itertools.takewhile(
141-
is_decimal, c[len(op_sign) :].strip().split(".")
142-
)
143-
ver = tuple(map(int, raw_ver))
144-
yield op_func, ver
145-
break
146-
147-
def validate_required_python_or_fail(python_requires=None):
148-
if python_requires is None:
149-
return
150-
151-
python_version = sys.version_info
152-
preds = parse_predicates(python_requires)
153-
for op, v in preds:
154-
py_ver_slug = python_version[: max(len(v), 3)]
155-
condition_matches = op(py_ver_slug, v)
156-
if not condition_matches:
157-
raise RuntimeError(
158-
"requires Python '{}' but the running Python is {}".format(
159-
python_requires, ".".join(map(str, python_version[:3]))
160-
)
161-
)
162-
163-
def verify_required_python_runtime(s):
164-
@functools.wraps(s)
165-
def sw(**attrs):
166-
try:
167-
validate_required_python_or_fail(attrs.get("python_requires"))
168-
except RuntimeError as re:
169-
sys.exit("{} {!s}".format(attrs["name"], re))
170-
return s(**attrs)
171-
172-
return sw
173-
174-
setuptools.setup = ignore_unknown_options(setuptools.setup)
175-
setuptools.setup = verify_required_python_runtime(setuptools.setup)
176-
177-
try:
178-
from configparser import ConfigParser, NoSectionError
179-
except ImportError:
180-
from ConfigParser import ConfigParser, NoSectionError
181-
182-
ConfigParser.read_file = ConfigParser.readfp
183-
184-
def maybe_read_files(d):
185-
"""Read files if the string starts with `file:` marker."""
186-
FILE_FUNC_MARKER = "file:"
187-
188-
d = d.strip()
189-
if not d.startswith(FILE_FUNC_MARKER):
190-
return d
191-
descs = []
192-
for fname in map(str.strip, str(d[len(FILE_FUNC_MARKER) :]).split(",")):
193-
with io.open(fname, encoding="utf-8") as f:
194-
descs.append(f.read())
195-
return "".join(descs)
196-
197-
def cfg_val_to_list(v):
198-
"""Turn config val to list and filter out empty lines."""
199-
return list(filter(bool, map(str.strip, str(v).strip().splitlines())))
200-
201-
def cfg_val_to_dict(v):
202-
"""Turn config val to dict and filter out empty lines."""
203-
return dict(
204-
map(
205-
lambda l: list(map(str.strip, l.split("=", 1))),
206-
filter(bool, map(str.strip, str(v).strip().splitlines())),
207-
)
208-
)
209-
210-
def cfg_val_to_primitive(v):
211-
"""Parse primitive config val to appropriate data type."""
212-
return json.loads(v.strip().lower())
213-
214-
def read_configuration(filepath):
215-
"""Read metadata and options from setup.cfg located at filepath."""
216-
cfg = ConfigParser()
217-
with io.open(filepath, encoding="utf-8") as f:
218-
cfg.read_file(f)
219-
220-
md = dict(cfg.items("metadata"))
221-
for list_key in "classifiers", "keywords", "project_urls":
222-
try:
223-
md[list_key] = cfg_val_to_list(md[list_key])
224-
except KeyError:
225-
pass
226-
try:
227-
md["long_description"] = maybe_read_files(md["long_description"])
228-
except KeyError:
229-
pass
230-
opt = dict(cfg.items("options"))
231-
for list_key in "include_package_data", "use_scm_version", "zip_safe":
232-
try:
233-
opt[list_key] = cfg_val_to_primitive(opt[list_key])
234-
except KeyError:
235-
pass
236-
for list_key in "scripts", "install_requires", "setup_requires":
237-
try:
238-
opt[list_key] = cfg_val_to_list(opt[list_key])
239-
except KeyError:
240-
pass
241-
try:
242-
opt["package_dir"] = cfg_val_to_dict(opt["package_dir"])
243-
except KeyError:
244-
pass
245-
try:
246-
opt_package_data = dict(cfg.items("options.package_data"))
247-
if not opt_package_data.get("", "").strip():
248-
opt_package_data[""] = opt_package_data["*"]
249-
del opt_package_data["*"]
250-
except (KeyError, NoSectionError):
251-
opt_package_data = {}
252-
try:
253-
opt_extras_require = dict(cfg.items("options.extras_require"))
254-
opt["extras_require"] = {}
255-
for k, v in opt_extras_require.items():
256-
opt["extras_require"][k] = cfg_val_to_list(v)
257-
except NoSectionError:
258-
pass
259-
opt["package_data"] = {}
260-
for k, v in opt_package_data.items():
261-
opt["package_data"][k] = cfg_val_to_list(v)
262-
try:
263-
opt_exclude_package_data = dict(cfg.items("options.exclude_package_data"))
264-
if (
265-
not opt_exclude_package_data.get("", "").strip()
266-
and "*" in opt_exclude_package_data
267-
):
268-
opt_exclude_package_data[""] = opt_exclude_package_data["*"]
269-
del opt_exclude_package_data["*"]
270-
except NoSectionError:
271-
pass
272-
else:
273-
opt["exclude_package_data"] = {}
274-
for k, v in opt_exclude_package_data.items():
275-
opt["exclude_package_data"][k] = cfg_val_to_list(v)
276-
cur_pkgs = opt.get("packages", "").strip()
277-
if "\n" in cur_pkgs:
278-
opt["packages"] = cfg_val_to_list(opt["packages"])
279-
elif cur_pkgs.startswith("find:"):
280-
opt_packages_find = stringify_dict_contents(
281-
dict(cfg.items("options.packages.find"))
282-
)
283-
opt["packages"] = setuptools.find_packages(**opt_packages_find)
284-
return {"metadata": md, "options": opt}
285-
286-
287-
def cut_local_version_on_upload(version):
288-
"""Generate a PEP440 local version if uploading to PyPI."""
289-
import os
290-
import setuptools_scm.version # only present during setup time
291-
292-
IS_PYPI_UPLOAD = os.getenv("PYPI_UPLOAD") == "true" # set in tox.ini
293-
return (
294-
""
295-
if IS_PYPI_UPLOAD
296-
else setuptools_scm.version.get_local_node_and_date(version)
297-
)
298-
299-
300-
if HAS_DIST_INFO_CMD:
301-
302-
class patched_dist_info(setuptools.command.dist_info.dist_info):
303-
def run(self):
304-
self.egg_base = str_if_nested_or_str(self.egg_base)
305-
return setuptools.command.dist_info.dist_info.run(self)
306-
307-
308-
declarative_setup_params = read_configuration("setup.cfg")
309-
"""Declarative metadata and options as read by setuptools."""
310-
311-
312-
setup_params = {}
313-
"""Explicit metadata for passing into setuptools.setup() call."""
314-
315-
setup_params = dict(setup_params, **declarative_setup_params["metadata"])
316-
setup_params = dict(setup_params, **declarative_setup_params["options"])
317-
318-
if HAS_DIST_INFO_CMD:
319-
setup_params["cmdclass"] = {"dist_info": patched_dist_info}
320-
321-
setup_params["use_scm_version"] = {"local_scheme": cut_local_version_on_upload}
322-
323-
# Patch incorrectly decoded package_dir option
324-
# ``egg_info`` demands native strings failing with unicode under Python 2
325-
# Ref https://github.com/pypa/setuptools/issues/1136
326-
setup_params = stringify_dict_contents(setup_params)
327-
3284

3295
if __name__ == "__main__":
330-
setuptools.setup(**setup_params)
6+
setuptools.setup(use_scm_version=True)

0 commit comments

Comments
 (0)