-
Notifications
You must be signed in to change notification settings - Fork 423
/
_load_setup_py_data.py
168 lines (147 loc) · 5.54 KB
/
_load_setup_py_data.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
# Copyright (C) 2014 Anaconda, Inc
# SPDX-License-Identifier: BSD-3-Clause
import logging
import os
import sys
def load_setup_py_data(
setup_file,
from_recipe_dir=False,
recipe_dir=None,
work_dir=None,
permit_undefined_jinja=True,
):
_setuptools_data = {}
log = logging.getLogger(__name__)
import distutils.core
import setuptools
cd_to_work = False
path_backup = sys.path
def _change_cwd(target_dir):
cd_to_work = True
try:
cwd = os.getcwd()
except OSError:
cwd = recipe_dir or work_dir
os.chdir(target_dir)
# this is very important - or else if versioneer or otherwise is in the start folder,
# things will pick up the wrong versioneer/whatever!
sys.path.insert(0, target_dir)
return cd_to_work, cwd
if from_recipe_dir and recipe_dir:
setup_file = os.path.abspath(os.path.join(recipe_dir, setup_file))
# if the setup_file is not in the recipe dir itself, but is say specified as '../setup.py'
setup_root, _ = os.path.split(setup_file)
if os.path.abspath(setup_root) != os.path.abspath(recipe_dir):
cd_to_work, cwd = _change_cwd(setup_root)
elif os.path.exists(work_dir):
cd_to_work, cwd = _change_cwd(work_dir)
if not os.path.isabs(setup_file):
setup_file = os.path.join(work_dir, setup_file)
else:
message = (
"Did not find setup.py file in manually specified location, and source "
"not downloaded yet."
)
if permit_undefined_jinja:
log.debug(message)
return {}
else:
raise RuntimeError(message)
setup_cfg_data = {}
try:
try:
# Recommended for setuptools 61.0.0+
# (though may disappear in the future)
from setuptools.config.setupcfg import read_configuration
except ImportError:
from setuptools.config import read_configuration
except ImportError:
pass # setuptools <30.3.0 cannot read metadata / options from 'setup.cfg'
else:
setup_cfg = os.path.join(os.path.dirname(setup_file), "setup.cfg")
if os.path.isfile(setup_cfg):
# read_configuration returns a dict of dicts. Each dict (keys: 'metadata',
# 'options'), if present, provides keyword arguments for the setup function.
for kwargs in read_configuration(setup_cfg).values():
# explicit arguments to setup.cfg take priority over values in setup.py
setup_cfg_data.update(kwargs)
def setup(**kw):
_setuptools_data.update(kw)
# values in setup.cfg take priority over explicit arguments to setup.py
_setuptools_data.update(setup_cfg_data)
# Patch setuptools, distutils
setuptools_setup = setuptools.setup
distutils_setup = distutils.core.setup
numpy_setup = None
versioneer = None
if "versioneer" in sys.modules:
versioneer = sys.modules["versioneer"]
del sys.modules["versioneer"]
try:
# numpy.distutils deprecated in Python 3.12+
# see https://numpy.org/doc/stable/reference/distutils_status_migration.html
import numpy.distutils.core
numpy_setup = numpy.distutils.core.setup
numpy.distutils.core.setup = setup
except ImportError:
log.debug("Failed to import numpy for setup patch. Is numpy installed?")
setuptools.setup = distutils.core.setup = setup
ns = {
"__name__": "__main__",
"__doc__": None,
"__file__": setup_file,
}
if os.path.isfile(setup_file):
with open(setup_file) as f:
code = compile(f.read(), setup_file, "exec", dont_inherit=1)
exec(code, ns, ns)
else:
if not permit_undefined_jinja:
raise TypeError("%s is not a file that can be read" % setup_file) # noqa: UP031
sys.modules["versioneer"] = versioneer
distutils.core.setup = distutils_setup
setuptools.setup = setuptools_setup
if numpy_setup:
numpy.distutils.core.setup = numpy_setup
if cd_to_work:
os.chdir(cwd)
# remove our workdir from sys.path
sys.path = path_backup
return _setuptools_data
if __name__ == "__main__":
import argparse
import json
parser = argparse.ArgumentParser(description="run setup.py file to obtain metadata")
parser.add_argument(
"work_dir",
help=(
"path to work dir, where we'll write the output data "
"json, and potentially also where setup.py should be found"
),
)
parser.add_argument("setup_file", help="path or filename of setup.py file")
parser.add_argument(
"--from-recipe-dir",
help="look for setup.py file in recipe dir (as opposed to work dir)",
default=False,
action="store_true",
)
parser.add_argument(
"--recipe-dir",
help="(optional) path to recipe dir, where setup.py should be found",
)
parser.add_argument(
"--permit-undefined-jinja",
help="look for setup.py file in recipe dir (as opposed to work dir)",
default=False,
action="store_true",
)
args = parser.parse_args()
# we get back a dict of the setup data
data = load_setup_py_data(**args.__dict__)
with open(
os.path.join(args.work_dir, "conda_build_loaded_setup_py.json"), "w"
) as f:
# this is lossy. Anything that can't be serialized is either forced to None or
# removed completely.
json.dump(data, f, skipkeys=True, default=lambda x: None)