@@ -23,14 +23,17 @@ def add(self, key, value):
23
23
if key in self .info :
24
24
raise ValueError ("duplicate key: %r" % key )
25
25
26
- if isinstance (value , str ):
26
+ if value is None :
27
+ return
28
+
29
+ if not isinstance (value , int ):
30
+ if not isinstance (value , str ):
31
+ # convert other objects like sys.flags to string
32
+ value = str (value )
33
+
27
34
value = value .strip ()
28
35
if not value :
29
36
return
30
- elif value is None :
31
- return
32
- elif not isinstance (value , int ):
33
- raise TypeError ("value type must be str, int or None" )
34
37
35
38
self .info [key ] = value
36
39
@@ -52,25 +55,47 @@ def copy_attributes(info_add, obj, name_fmt, attributes, *, formatter=None):
52
55
info_add (name , value )
53
56
54
57
55
- def collect_sys (info_add ):
56
- def format_attr (attr , value ):
57
- if attr == 'flags' :
58
- # convert sys.flags tuple to string
59
- return str (value )
60
- else :
61
- return value
58
+ def call_func (info_add , name , mod , func_name , * , formatter = None ):
59
+ try :
60
+ func = getattr (mod , func_name )
61
+ except AttributeError :
62
+ return
63
+ value = func ()
64
+ if formatter is not None :
65
+ value = formatter (value )
66
+ info_add (name , value )
62
67
68
+
69
+ def collect_sys (info_add ):
63
70
attributes = (
64
71
'_framework' ,
72
+ 'abiflags' ,
73
+ 'api_version' ,
74
+ 'builtin_module_names' ,
65
75
'byteorder' ,
76
+ 'dont_write_bytecode' ,
66
77
'executable' ,
67
78
'flags' ,
79
+ 'float_info' ,
80
+ 'float_repr_style' ,
81
+ 'hash_info' ,
82
+ 'hexversion' ,
83
+ 'implementation' ,
84
+ 'int_info' ,
68
85
'maxsize' ,
69
86
'maxunicode' ,
87
+ 'path' ,
88
+ 'platform' ,
89
+ 'prefix' ,
90
+ 'thread_info' ,
70
91
'version' ,
92
+ 'version_info' ,
93
+ 'winver' ,
71
94
)
72
- copy_attributes (info_add , sys , 'sys.%s' , attributes ,
73
- formatter = format_attr )
95
+ copy_attributes (info_add , sys , 'sys.%s' , attributes )
96
+
97
+ call_func (info_add , 'sys.androidapilevel' , sys , 'getandroidapilevel' )
98
+ call_func (info_add , 'sys.windowsversion' , sys , 'getwindowsversion' )
74
99
75
100
encoding = sys .getfilesystemencoding ()
76
101
if hasattr (sys , 'getfilesystemencodeerrors' ):
@@ -89,15 +114,6 @@ def format_attr(attr, value):
89
114
encoding = '%s/%s' % (encoding , errors )
90
115
info_add ('sys.%s.encoding' % name , encoding )
91
116
92
- if hasattr (sys , 'hash_info' ):
93
- alg = sys .hash_info .algorithm
94
- bits = 64 if sys .maxsize > 2 ** 32 else 32
95
- alg = '%s (%s bits)' % (alg , bits )
96
- info_add ('sys.hash_info' , alg )
97
-
98
- if hasattr (sys , 'getandroidapilevel' ):
99
- info_add ('sys.androidapilevel' , sys .getandroidapilevel ())
100
-
101
117
102
118
def collect_platform (info_add ):
103
119
import platform
@@ -121,20 +137,27 @@ def collect_locale(info_add):
121
137
def collect_os (info_add ):
122
138
import os
123
139
124
- if hasattr (os , 'getrandom' ):
125
- # PEP 524: Check is system urandom is initialized
126
- try :
127
- os .getrandom (1 , os .GRND_NONBLOCK )
128
- state = 'ready (initialized)'
129
- except BlockingIOError as exc :
130
- state = 'not seeded yet (%s)' % exc
131
- info_add ('os.getrandom' , state )
140
+ def format_attr (attr , value ):
141
+ if attr in ('supports_follow_symlinks' , 'supports_fd' ,
142
+ 'supports_effective_ids' ):
143
+ return str (sorted (func .__name__ for func in value ))
144
+ else :
145
+ return value
146
+
147
+ attributes = (
148
+ 'name' ,
149
+ 'supports_bytes_environ' ,
150
+ 'supports_effective_ids' ,
151
+ 'supports_fd' ,
152
+ 'supports_follow_symlinks' ,
153
+ )
154
+ copy_attributes (info_add , os , 'os.%s' , attributes , formatter = format_attr )
132
155
133
156
info_add ("os.cwd" , os .getcwd ())
134
157
135
- if hasattr ( os , 'getuid' ):
136
- info_add ( " os.uid" , os . getuid () )
137
- info_add ( " os.gid" , os . getgid () )
158
+ call_func ( info_add , 'os.uid' , os , 'getuid' )
159
+ call_func ( info_add , ' os.gid' , os , 'getgid' )
160
+ call_func ( info_add , ' os.uname' , os , 'uname' )
138
161
139
162
if hasattr (os , 'getgroups' ):
140
163
groups = os .getgroups ()
@@ -157,9 +180,7 @@ def collect_os(info_add):
157
180
if cpu_count :
158
181
info_add ('os.cpu_count' , cpu_count )
159
182
160
- if hasattr (os , 'getloadavg' ):
161
- load = os .getloadavg ()
162
- info_add ('os.loadavg' , str (load ))
183
+ call_func (info_add , 'os.loadavg' , os , 'getloadavg' )
163
184
164
185
# Get environment variables: filter to list
165
186
# to not leak sensitive information
@@ -194,6 +215,20 @@ def collect_os(info_add):
194
215
or (uname .startswith ("VS" ) and uname .endswith ("COMNTOOLS" ))):
195
216
info_add ('os.environ[%s]' % name , value )
196
217
218
+ if hasattr (os , 'umask' ):
219
+ mask = os .umask (0 )
220
+ os .umask (mask )
221
+ info_add ("os.umask" , '%03o' % mask )
222
+
223
+ if hasattr (os , 'getrandom' ):
224
+ # PEP 524: Check if system urandom is initialized
225
+ try :
226
+ os .getrandom (1 , os .GRND_NONBLOCK )
227
+ state = 'ready (initialized)'
228
+ except BlockingIOError as exc :
229
+ state = 'not seeded yet (%s)' % exc
230
+ info_add ('os.getrandom' , state )
231
+
197
232
198
233
def collect_readline (info_add ):
199
234
try :
@@ -255,12 +290,20 @@ def collect_tkinter(info_add):
255
290
def collect_time (info_add ):
256
291
import time
257
292
293
+ attributes = (
294
+ 'altzone' ,
295
+ 'daylight' ,
296
+ 'timezone' ,
297
+ 'tzname' ,
298
+ )
299
+ copy_attributes (info_add , time , 'time.%s' , attributes )
300
+
258
301
if not hasattr (time , 'get_clock_info' ):
259
302
return
260
303
261
304
for clock in ('time' , 'perf_counter' ):
262
305
tinfo = time .get_clock_info (clock )
263
- info_add ('time.%s' % clock , str ( tinfo ) )
306
+ info_add ('time.%s' % clock , tinfo )
264
307
265
308
266
309
def collect_sysconfig (info_add ):
@@ -305,8 +348,7 @@ def format_attr(attr, value):
305
348
if attr .startswith ('OP_' ):
306
349
return '%#8x' % value
307
350
else :
308
- # Convert OPENSSL_VERSION_INFO tuple to str
309
- return str (value )
351
+ return value
310
352
311
353
attributes = (
312
354
'OPENSSL_VERSION' ,
0 commit comments