1
+ import importlib
1
2
import json
2
3
import os
4
+ import os .path
3
5
import sys
4
6
import sysconfig
5
7
import string
6
8
import unittest
9
+ from pathlib import Path
7
10
8
11
from test .support import is_android , is_apple_mobile , is_wasm32
9
12
13
+ BASE_PATH = Path (
14
+ __file__ , # Lib/test/test_build_details.py
15
+ '..' , # Lib/test
16
+ '..' , # Lib
17
+ '..' , # <src/install dir>
18
+ ).resolve ()
19
+ MODULE_PATH = BASE_PATH / 'Tools' / 'build' / 'generate-build-details.py'
20
+
21
+ try :
22
+ # Import "generate-build-details.py" as "generate_build_details"
23
+ spec = importlib .util .spec_from_file_location (
24
+ "generate_build_details" , MODULE_PATH
25
+ )
26
+ generate_build_details = importlib .util .module_from_spec (spec )
27
+ sys .modules ["generate_build_details" ] = generate_build_details
28
+ spec .loader .exec_module (generate_build_details )
29
+ except (FileNotFoundError , ImportError ):
30
+ generate_build_details = None
31
+
10
32
11
33
class FormatTestsBase :
12
34
@property
@@ -31,16 +53,15 @@ def key(self, name):
31
53
value = value [part ]
32
54
return value
33
55
34
- def test_parse (self ):
35
- self .data
36
-
37
56
def test_top_level_container (self ):
38
57
self .assertIsInstance (self .data , dict )
39
58
for key , value in self .data .items ():
40
59
with self .subTest (key = key ):
41
- if key in ('schema_version' , 'base_prefix' , 'base_interpreter' , 'platform' ):
60
+ if key in ('schema_version' , 'base_prefix' , 'base_interpreter' ,
61
+ 'platform' ):
42
62
self .assertIsInstance (value , str )
43
- elif key in ('language' , 'implementation' , 'abi' , 'suffixes' , 'libpython' , 'c_api' , 'arbitrary_data' ):
63
+ elif key in ('language' , 'implementation' , 'abi' , 'suffixes' ,
64
+ 'libpython' , 'c_api' , 'arbitrary_data' ):
44
65
self .assertIsInstance (value , dict )
45
66
46
67
def test_base_prefix (self ):
@@ -71,15 +92,20 @@ def test_language_version_info(self):
71
92
self .assertEqual (len (value ), sys .version_info .n_fields )
72
93
for part_name , part_value in value .items ():
73
94
with self .subTest (part = part_name ):
74
- self .assertEqual (part_value , getattr (sys .version_info , part_name ))
95
+ sys_version_value = getattr (sys .version_info , part_name )
96
+ self .assertEqual (part_value , sys_version_value )
75
97
76
98
def test_implementation (self ):
99
+ impl_ver = sys .implementation .version
77
100
for key , value in self .key ('implementation' ).items ():
78
101
with self .subTest (part = key ):
79
102
if key == 'version' :
80
- self .assertEqual (len (value ), len (sys . implementation . version ))
103
+ self .assertEqual (len (value ), len (impl_ver ))
81
104
for part_name , part_value in value .items ():
82
- self .assertEqual (getattr (sys .implementation .version , part_name ), part_value )
105
+ self .assertFalse (isinstance (sys .implementation .version , dict ))
106
+ getattr (sys .implementation .version , part_name )
107
+ sys_implementation_value = getattr (impl_ver , part_name )
108
+ self .assertEqual (sys_implementation_value , part_value )
83
109
else :
84
110
self .assertEqual (getattr (sys .implementation , key ), value )
85
111
@@ -99,15 +125,16 @@ class CPythonBuildDetailsTests(unittest.TestCase, FormatTestsBase):
99
125
def location (self ):
100
126
if sysconfig .is_python_build ():
101
127
projectdir = sysconfig .get_config_var ('projectbase' )
102
- with open (os .path .join (projectdir , 'pybuilddir.txt' )) as f :
128
+ pybuilddir = os .path .join (projectdir , 'pybuilddir.txt' )
129
+ with open (pybuilddir , encoding = 'utf-8' ) as f :
103
130
dirname = os .path .join (projectdir , f .read ())
104
131
else :
105
132
dirname = sysconfig .get_path ('stdlib' )
106
133
return os .path .join (dirname , 'build-details.json' )
107
134
108
135
@property
109
136
def contents (self ):
110
- with open (self .location , 'r' ) as f :
137
+ with open (self .location , 'r' , encoding = 'utf-8' ) as f :
111
138
return f .read ()
112
139
113
140
@needs_installed_python
@@ -147,5 +174,64 @@ def test_c_api(self):
147
174
self .assertTrue (os .path .exists (os .path .join (value ['pkgconfig_path' ], f'python-{ version } .pc' )))
148
175
149
176
177
+ @unittest .skipIf (
178
+ generate_build_details is None ,
179
+ "Failed to import generate-build-details"
180
+ )
181
+ @unittest .skipIf (os .name != 'posix' , 'Feature only implemented on POSIX right now' )
182
+ @unittest .skipIf (is_wasm32 , 'Feature not available on WebAssembly builds' )
183
+ class BuildDetailsRelativePathsTests (unittest .TestCase ):
184
+ @property
185
+ def build_details_absolute_paths (self ):
186
+ data = generate_build_details .generate_data (schema_version = '1.0' )
187
+ return json .loads (json .dumps (data ))
188
+
189
+ @property
190
+ def build_details_relative_paths (self ):
191
+ data = self .build_details_absolute_paths
192
+ generate_build_details .make_paths_relative (data , config_path = None )
193
+ return data
194
+
195
+ def test_round_trip (self ):
196
+ data_abs_path = self .build_details_absolute_paths
197
+ data_rel_path = self .build_details_relative_paths
198
+
199
+ self .assertEqual (data_abs_path ['base_prefix' ],
200
+ data_rel_path ['base_prefix' ])
201
+
202
+ base_prefix = data_abs_path ['base_prefix' ]
203
+
204
+ top_level_keys = ('base_interpreter' ,)
205
+ for key in top_level_keys :
206
+ self .assertEqual (key in data_abs_path , key in data_rel_path )
207
+ if key not in data_abs_path :
208
+ continue
209
+
210
+ abs_rel_path = os .path .join (base_prefix , data_rel_path [key ])
211
+ abs_rel_path = os .path .normpath (abs_rel_path )
212
+ self .assertEqual (data_abs_path [key ], abs_rel_path )
213
+
214
+ second_level_keys = (
215
+ ('libpython' , 'dynamic' ),
216
+ ('libpython' , 'dynamic_stableabi' ),
217
+ ('libpython' , 'static' ),
218
+ ('c_api' , 'headers' ),
219
+ ('c_api' , 'pkgconfig_path' ),
220
+
221
+ )
222
+ for part , key in second_level_keys :
223
+ self .assertEqual (part in data_abs_path , part in data_rel_path )
224
+ if part not in data_abs_path :
225
+ continue
226
+ self .assertEqual (key in data_abs_path [part ],
227
+ key in data_rel_path [part ])
228
+ if key not in data_abs_path [part ]:
229
+ continue
230
+
231
+ abs_rel_path = os .path .join (base_prefix , data_rel_path [part ][key ])
232
+ abs_rel_path = os .path .normpath (abs_rel_path )
233
+ self .assertEqual (data_abs_path [part ][key ], abs_rel_path )
234
+
235
+
150
236
if __name__ == '__main__' :
151
237
unittest .main ()
0 commit comments