- Notifications
You must be signed in to change notification settings - Fork 2.9k
/
Copy pathsetup.py
162 lines (134 loc) · 5.49 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
#!/usr/bin/env python
from __future__ importannotations
importglob
importos
importos.path
importsys
fromtypingimportTYPE_CHECKING, Any
ifsys.version_info< (3, 9, 0): # noqa: UP036, RUF100
sys.stderr.write("ERROR: You need Python 3.9 or later to use mypy.\n")
exit(1)
# we'll import stuff from the source tree, let's ensure is on the sys path
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
# This requires setuptools when building; setuptools is not needed
# when installing from a wheel file (though it is still needed for
# alternative forms of installing, as suggested by README.md).
fromsetuptoolsimportExtension, setup
fromsetuptools.command.build_pyimportbuild_py
frommypy.versionimport__version__asversion
ifTYPE_CHECKING:
fromtyping_extensionsimportTypeGuard
defis_list_of_setuptools_extension(items: list[Any]) ->TypeGuard[list[Extension]]:
returnall(isinstance(item, Extension) foriteminitems)
deffind_package_data(base: str, globs: list[str], root: str="mypy") ->list[str]:
"""Find all interesting data files, for setup(package_data=)
Arguments:
root: The directory to search in.
globs: A list of glob patterns to accept files.
"""
rv_dirs= [rootforroot, dirs, filesinos.walk(base)]
rv= []
forrv_dirinrv_dirs:
files= []
forpatinglobs:
files+=glob.glob(os.path.join(rv_dir, pat))
ifnotfiles:
continue
rv.extend([os.path.relpath(f, root) forfinfiles])
returnrv
classCustomPythonBuild(build_py):
defpin_version(self) ->None:
path=os.path.join(self.build_lib, "mypy")
self.mkpath(path)
withopen(os.path.join(path, "version.py"), "w") asstream:
stream.write(f'__version__ = "{version}"\n')
defrun(self) ->None:
self.execute(self.pin_version, ())
build_py.run(self)
cmdclass= {"build_py": CustomPythonBuild}
USE_MYPYC=False
# To compile with mypyc, a mypyc checkout must be present on the PYTHONPATH
iflen(sys.argv) >1and"--use-mypyc"insys.argv:
sys.argv.remove("--use-mypyc")
USE_MYPYC=True
ifos.getenv("MYPY_USE_MYPYC", None) =="1":
USE_MYPYC=True
ifUSE_MYPYC:
MYPYC_BLACKLIST=tuple(
os.path.join("mypy", x)
forxin (
# Need to be runnable as scripts
"__main__.py",
"pyinfo.py",
os.path.join("dmypy", "__main__.py"),
# Uses __getattr__/__setattr__
"split_namespace.py",
# Lies to mypy about code reachability
"bogus_type.py",
# We don't populate __file__ properly at the top level or something?
# Also I think there would be problems with how we generate version.py.
"version.py",
# Skip these to reduce the size of the build
"stubtest.py",
"stubgenc.py",
"stubdoc.py",
)
) + (
# Don't want to grab this accidentally
os.path.join("mypyc", "lib-rt", "setup.py"),
# Uses __file__ at top level https://github.com/mypyc/mypyc/issues/700
os.path.join("mypyc", "__main__.py"),
)
everything= [os.path.join("mypy", x) forxinfind_package_data("mypy", ["*.py"])] + [
os.path.join("mypyc", x) forxinfind_package_data("mypyc", ["*.py"], root="mypyc")
]
# Start with all the .py files
all_real_pys= [
xforxineverythingifnotx.startswith(os.path.join("mypy", "typeshed") +os.sep)
]
# Strip out anything in our blacklist
mypyc_targets= [xforxinall_real_pysifxnotinMYPYC_BLACKLIST]
# Strip out any test code
mypyc_targets= [
x
forxinmypyc_targets
ifnotx.startswith(
(
os.path.join("mypy", "test") +os.sep,
os.path.join("mypyc", "test") +os.sep,
os.path.join("mypyc", "doc") +os.sep,
os.path.join("mypyc", "test-data") +os.sep,
)
)
]
# ... and add back in the one test module we need
mypyc_targets.append(os.path.join("mypy", "test", "visitors.py"))
# The targets come out of file system apis in an unspecified
# order. Sort them so that the mypyc output is deterministic.
mypyc_targets.sort()
use_other_mypyc=os.getenv("ALTERNATE_MYPYC_PATH", None)
ifuse_other_mypyc:
# This bit is super unfortunate: we want to use a different
# mypy/mypyc version, but we've already imported parts, so we
# remove the modules that we've imported already, which will
# let the right versions be imported by mypyc.
delsys.modules["mypy"]
delsys.modules["mypy.version"]
delsys.modules["mypy.git"]
sys.path.insert(0, use_other_mypyc)
frommypyc.buildimportmypycify
opt_level=os.getenv("MYPYC_OPT_LEVEL", "3")
debug_level=os.getenv("MYPYC_DEBUG_LEVEL", "1")
force_multifile=os.getenv("MYPYC_MULTI_FILE", "") =="1"
ext_modules=mypycify(
mypyc_targets+ ["--config-file=mypy_bootstrap.ini"],
opt_level=opt_level,
debug_level=debug_level,
# Use multi-file compilation mode on windows because without it
# our Appveyor builds run out of memory sometimes.
multi_file=sys.platform=="win32"orforce_multifile,
)
else:
ext_modules= []
assertis_list_of_setuptools_extension(ext_modules), "Expected mypycify to use setuptools"
setup(version=version, ext_modules=ext_modules, cmdclass=cmdclass)