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
|
import os, sys, imp
import tempfile, binascii
def _get_hashed_filename(cfile):
with open(cfile,'r') as fid:
content = fid.read()
# from cffi's Verifier()
key = '\x00'.join([sys.version[:3], content])
key += 'cpyext-gc-support-2' # this branch requires recompilation!
if sys.version_info >= (3,):
key = key.encode('utf-8')
k1 = hex(binascii.crc32(key[0::2]) & 0xffffffff)
k1 = k1.lstrip('0x').rstrip('L')
k2 = hex(binascii.crc32(key[1::2]) & 0xffffffff)
k2 = k2.lstrip('0').rstrip('L')
try:
username = os.environ['USER'] #linux, et al
except KeyError:
try:
username = os.environ['USERNAME'] #windows
except KeyError:
username = os.getuid()
return tempfile.gettempdir() + os.path.sep + 'testcapi_%s_%s%s' % (
username, k1, k2)
def get_hashed_dir(cfile):
hashed_fn = _get_hashed_filename(cfile)
try:
with open(hashed_fn) as f:
dirname = f.read(1024)
except IOError:
dirname = ''
tmpdir = tempfile.gettempdir()
if (not dirname or '/' in dirname or '\\' in dirname or '\x00' in dirname
or not os.path.isdir(os.path.join(tmpdir, dirname))):
dirname = binascii.hexlify(os.urandom(8))
if not isinstance(dirname, str): # Python 3
dirname = dirname.decode('ascii')
dirname = 'testcapi_' + dirname
output_dir = os.path.join(tmpdir, dirname)
try:
os.mkdir(output_dir)
except OSError:
pass
return output_dir
def _get_c_extension_suffix():
for ext, mod, typ in imp.get_suffixes():
if typ == imp.C_EXTENSION:
return ext
def compile_shared(csource, modulename, output_dir):
"""Compile '_testcapi.c' or '_ctypes_test.c' into an extension module,
and import it.
"""
thisdir = os.path.dirname(__file__)
assert output_dir is not None
from distutils.ccompiler import new_compiler
compiler = new_compiler()
compiler.output_dir = output_dir
# Compile .c file
include_dir = os.path.join(thisdir, '..', 'include')
if sys.platform == 'win32':
ccflags = ['-D_CRT_SECURE_NO_WARNINGS']
else:
ccflags = ['-fPIC', '-Wimplicit-function-declaration']
res = compiler.compile([os.path.join(thisdir, csource)],
include_dirs=[include_dir],
extra_preargs=ccflags)
object_filename = res[0]
# set link options
output_filename = modulename + _get_c_extension_suffix()
if sys.platform == 'win32':
# XXX pyconfig.h uses a pragma to link to the import library,
# which is currently python27.lib
library = os.path.join(thisdir, '..', 'libs', 'python27')
if not os.path.exists(library + '.lib'):
# For a local translation or nightly build
library = os.path.join(thisdir, '..', 'pypy', 'goal', 'python27')
assert os.path.exists(library + '.lib'),'Could not find import library "%s"' % library
libraries = [library, 'oleaut32']
extra_ldargs = ['/MANIFEST', # needed for VC10
'/EXPORT:init' + modulename]
else:
libraries = []
extra_ldargs = []
# link the dynamic library
compiler.link_shared_object(
[object_filename],
output_filename,
libraries=libraries,
extra_preargs=extra_ldargs)
# Now import the newly created library, it will replace the original
# module in sys.modules
fp, filename, description = imp.find_module(modulename, path=[output_dir])
with fp:
imp.load_module(modulename, fp, filename, description)
# If everything went fine up to now, write the name of this new
# directory to 'hashed_fn', for future processes (and to avoid a
# growing number of temporary directories that are not completely
# obvious to clean up on Windows)
hashed_fn = _get_hashed_filename(os.path.join(thisdir, csource))
try:
with open(hashed_fn, 'w') as f:
f.write(os.path.basename(output_dir))
except IOError:
pass
|