[pypy-commit] pypy default: Don't use "hasattr(os.stat_result)" on top of CPython. Instead
arigo
noreply at buildbot.pypy.org
Mon Sep 5 16:44:45 CEST 2011
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r47083:cf485730ec67
Date: 2011-09-05 16:31 +0200
http://bitbucket.org/pypy/pypy/changeset/cf485730ec67/
Log: Don't use "hasattr(os.stat_result)" on top of CPython. Instead try
to compile with each of the extra fields, keeping the ones that
work.
diff --git a/pypy/rpython/module/ll_os_stat.py b/pypy/rpython/module/ll_os_stat.py
--- a/pypy/rpython/module/ll_os_stat.py
+++ b/pypy/rpython/module/ll_os_stat.py
@@ -49,19 +49,8 @@
]
N_INDEXABLE_FIELDS = 10
-# for now, check the host Python to know which st_xxx fields exist
-STAT_FIELDS = [(_name, _TYPE) for (_name, _TYPE) in ALL_STAT_FIELDS
- if hasattr(os.stat_result, _name)]
-
-STAT_FIELD_TYPES = dict(STAT_FIELDS) # {'st_xxx': TYPE}
-
-STAT_FIELD_NAMES = [_name for (_name, _TYPE) in ALL_STAT_FIELDS
- if _name in STAT_FIELD_TYPES]
-
-del _name, _TYPE
-
# For OO backends, expose only the portable fields (the first 10).
-PORTABLE_STAT_FIELDS = STAT_FIELDS[:N_INDEXABLE_FIELDS]
+PORTABLE_STAT_FIELDS = ALL_STAT_FIELDS[:N_INDEXABLE_FIELDS]
# ____________________________________________________________
#
@@ -142,17 +131,22 @@
includes = INCLUDES
)
-if sys.platform != 'win32':
+if TIMESPEC is not None:
+ class CConfig_for_timespec:
+ _compilation_info_ = compilation_info
+ TIMESPEC = TIMESPEC
+ TIMESPEC = lltype.Ptr(
+ platform.configure(CConfig_for_timespec)['TIMESPEC'])
+
+
+def posix_declaration(try_to_add=None):
+ global STAT_STRUCT
LL_STAT_FIELDS = STAT_FIELDS[:]
+ if try_to_add:
+ LL_STAT_FIELDS.append(try_to_add)
if TIMESPEC is not None:
- class CConfig_for_timespec:
- _compilation_info_ = compilation_info
- TIMESPEC = TIMESPEC
-
- TIMESPEC = lltype.Ptr(
- platform.configure(CConfig_for_timespec)['TIMESPEC'])
def _expand(lst, originalname, timespecname):
for i, (_name, _TYPE) in enumerate(lst):
@@ -178,9 +172,34 @@
class CConfig:
_compilation_info_ = compilation_info
STAT_STRUCT = platform.Struct('struct %s' % _name_struct_stat, LL_STAT_FIELDS)
- config = platform.configure(CConfig)
+ try:
+ config = platform.configure(CConfig)
+ except platform.CompilationError:
+ if try_to_add:
+ return # failed to add this field, give up
+ raise
STAT_STRUCT = lltype.Ptr(config['STAT_STRUCT'])
+ if try_to_add:
+ STAT_FIELDS.append(try_to_add)
+
+
+# This lists only the fields that have been found on the underlying platform.
+# Initially only the PORTABLE_STAT_FIELDS, but more may be added by the
+# following loop.
+STAT_FIELDS = PORTABLE_STAT_FIELDS[:]
+
+if sys.platform != 'win32':
+ posix_declaration()
+ for _i in range(len(PORTABLE_STAT_FIELDS), len(ALL_STAT_FIELDS)):
+ posix_declaration(ALL_STAT_FIELDS[_i])
+ del _i
+
+# these two global vars only list the fields defined in the underlying platform
+STAT_FIELD_TYPES = dict(STAT_FIELDS) # {'st_xxx': TYPE}
+STAT_FIELD_NAMES = [_name for (_name, _TYPE) in STAT_FIELDS]
+del _name, _TYPE
+
def build_stat_result(st):
# only for LL backends
diff --git a/pypy/rpython/module/test/test_ll_os_stat.py b/pypy/rpython/module/test/test_ll_os_stat.py
--- a/pypy/rpython/module/test/test_ll_os_stat.py
+++ b/pypy/rpython/module/test/test_ll_os_stat.py
@@ -2,6 +2,16 @@
import sys, os
import py
+
+class TestLinuxImplementation:
+ def setup_class(cls):
+ if not sys.platform.startswith('linux'):
+ py.test.skip("linux specific tests")
+
+ def test_has_all_fields(self):
+ assert ll_os_stat.STAT_FIELDS == ll_os_stat.ALL_STAT_FIELDS[:13]
+
+
class TestWin32Implementation:
def setup_class(cls):
if sys.platform != 'win32':
More information about the pypy-commit
mailing list