Author: Alex Gaynor <alex.gay...@gmail.com> Branch: release-2.1.x Changeset: r65613:a52810f16fa8 Date: 2013-07-24 08:49 -0700 http://bitbucket.org/pypy/pypy/changeset/a52810f16fa8/
Log: Manually transplanted add-statvfs from default. diff --git a/lib-python/2.7/test/test_os.py b/lib-python/2.7/test/test_os.py --- a/lib-python/2.7/test/test_os.py +++ b/lib-python/2.7/test/test_os.py @@ -275,7 +275,7 @@ try: result.f_bfree = 1 self.fail("No exception thrown") - except TypeError: + except (TypeError, AttributeError): pass try: diff --git a/pypy/module/posix/__init__.py b/pypy/module/posix/__init__.py --- a/pypy/module/posix/__init__.py +++ b/pypy/module/posix/__init__.py @@ -17,12 +17,13 @@ 'setregid', 'setreuid', 'setsid', 'setuid', 'stat_float_times', 'statvfs', 'statvfs_result', 'symlink', 'sysconf', 'sysconf_names', 'tcgetpgrp', 'tcsetpgrp', 'ttyname', 'uname', 'wait', 'wait3', 'wait4' - ] +] # the Win32 urandom implementation isn't going to translate on JVM or CLI so # we have to remove it lltype_only_defs.append('urandom') + class Module(MixedModule): """This module provides access to operating system functionality that is standardized by the C Standard and the POSIX standard (a thinly @@ -53,44 +54,49 @@ appleveldefs['wait3'] = 'app_posix.wait3' if hasattr(os, 'wait4'): appleveldefs['wait4'] = 'app_posix.wait4' - + interpleveldefs = { - 'open' : 'interp_posix.open', - 'lseek' : 'interp_posix.lseek', - 'write' : 'interp_posix.write', - 'isatty' : 'interp_posix.isatty', - 'read' : 'interp_posix.read', - 'close' : 'interp_posix.close', - 'closerange': 'interp_posix.closerange', - 'fstat' : 'interp_posix.fstat', - 'stat' : 'interp_posix.stat', - 'lstat' : 'interp_posix.lstat', - 'stat_float_times' : 'interp_posix.stat_float_times', - 'dup' : 'interp_posix.dup', - 'dup2' : 'interp_posix.dup2', - 'access' : 'interp_posix.access', - 'times' : 'interp_posix.times', - 'system' : 'interp_posix.system', - 'unlink' : 'interp_posix.unlink', - 'remove' : 'interp_posix.remove', - 'getcwd' : 'interp_posix.getcwd', - 'getcwdu' : 'interp_posix.getcwdu', - 'chdir' : 'interp_posix.chdir', - 'mkdir' : 'interp_posix.mkdir', - 'rmdir' : 'interp_posix.rmdir', - 'environ' : 'interp_posix.get(space).w_environ', - 'listdir' : 'interp_posix.listdir', - 'strerror' : 'interp_posix.strerror', - 'pipe' : 'interp_posix.pipe', - 'chmod' : 'interp_posix.chmod', - 'rename' : 'interp_posix.rename', - 'umask' : 'interp_posix.umask', - '_exit' : 'interp_posix._exit', - 'utime' : 'interp_posix.utime', - '_statfields': 'interp_posix.getstatfields(space)', - 'kill' : 'interp_posix.kill', - 'abort' : 'interp_posix.abort', - 'urandom' : 'interp_posix.urandom', + 'open': 'interp_posix.open', + 'lseek': 'interp_posix.lseek', + 'write': 'interp_posix.write', + 'isatty': 'interp_posix.isatty', + 'read': 'interp_posix.read', + 'close': 'interp_posix.close', + 'closerange': 'interp_posix.closerange', + + 'fstat': 'interp_posix.fstat', + 'stat': 'interp_posix.stat', + 'lstat': 'interp_posix.lstat', + 'stat_float_times': 'interp_posix.stat_float_times', + + 'fstatvfs': 'interp_posix.fstatvfs', + 'statvfs': 'interp_posix.statvfs', + + 'dup': 'interp_posix.dup', + 'dup2': 'interp_posix.dup2', + 'access': 'interp_posix.access', + 'times': 'interp_posix.times', + 'system': 'interp_posix.system', + 'unlink': 'interp_posix.unlink', + 'remove': 'interp_posix.remove', + 'getcwd': 'interp_posix.getcwd', + 'getcwdu': 'interp_posix.getcwdu', + 'chdir': 'interp_posix.chdir', + 'mkdir': 'interp_posix.mkdir', + 'rmdir': 'interp_posix.rmdir', + 'environ': 'interp_posix.get(space).w_environ', + 'listdir': 'interp_posix.listdir', + 'strerror': 'interp_posix.strerror', + 'pipe': 'interp_posix.pipe', + 'chmod': 'interp_posix.chmod', + 'rename': 'interp_posix.rename', + 'umask': 'interp_posix.umask', + '_exit': 'interp_posix._exit', + 'utime': 'interp_posix.utime', + '_statfields': 'interp_posix.getstatfields(space)', + 'kill': 'interp_posix.kill', + 'abort': 'interp_posix.abort', + 'urandom': 'interp_posix.urandom', } if hasattr(os, 'chown'): @@ -167,8 +173,8 @@ interpleveldefs['getlogin'] = 'interp_posix.getlogin' for name in ['setsid', 'getuid', 'geteuid', 'getgid', 'getegid', 'setuid', - 'seteuid', 'setgid', 'setegid', 'getgroups', 'getpgrp', - 'setpgrp', 'getppid', 'getpgid', 'setpgid', 'setreuid', + 'seteuid', 'setgid', 'setegid', 'getgroups', 'getpgrp', + 'setpgrp', 'getppid', 'getpgid', 'setpgid', 'setreuid', 'setregid', 'getsid', 'setsid']: if hasattr(os, name): interpleveldefs[name] = 'interp_posix.%s' % (name,) @@ -177,7 +183,7 @@ interpleveldefs['_getfullpathname'] = 'interp_posix._getfullpathname' if hasattr(os, 'chroot'): interpleveldefs['chroot'] = 'interp_posix.chroot' - + for name in RegisterOs.w_star: if hasattr(os, name): interpleveldefs[name] = 'interp_posix.' + name @@ -186,7 +192,7 @@ # if it's an ootype translation, remove all the defs that are lltype # only backend = space.config.translation.backend - if backend == 'cli' or backend == 'jvm': + if backend == 'cli' or backend == 'jvm' : for name in lltype_only_defs: self.interpleveldefs.pop(name, None) MixedModule.__init__(self, space, w_name) @@ -194,7 +200,7 @@ def startup(self, space): from pypy.module.posix import interp_posix interp_posix.get(space).startup(space) - + for constant in dir(os): value = getattr(os, constant) if constant.isupper() and type(value) is int: diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py --- a/pypy/module/posix/interp_posix.py +++ b/pypy/module/posix/interp_posix.py @@ -1,15 +1,17 @@ -from pypy.interpreter.gateway import unwrap_spec +import os +import sys + from rpython.rlib import rposix, objectmodel, rurandom from rpython.rlib.objectmodel import specialize from rpython.rlib.rarithmetic import r_longlong from rpython.rlib.unroll import unrolling_iterable +from rpython.rtyper.module import ll_os_stat +from rpython.rtyper.module.ll_os import RegisterOs + +from pypy.interpreter.gateway import unwrap_spec from pypy.interpreter.error import OperationError, wrap_oserror, wrap_oserror2 -from rpython.rtyper.module.ll_os import RegisterOs -from rpython.rtyper.module import ll_os_stat from pypy.module.sys.interp_encoding import getfilesystemencoding -import os -import sys _WIN32 = sys.platform == 'win32' if _WIN32: @@ -213,6 +215,7 @@ STAT_FIELDS = unrolling_iterable(enumerate(ll_os_stat.STAT_FIELDS)) PORTABLE_STAT_FIELDS = unrolling_iterable( enumerate(ll_os_stat.PORTABLE_STAT_FIELDS)) +STATVFS_FIELDS = unrolling_iterable(enumerate(ll_os_stat.STATVFS_FIELDS)) def build_stat_result(space, st): if space.config.translation.type_system == 'ootype': @@ -253,6 +256,16 @@ space.wrap('stat_result')) return space.call_function(w_stat_result, w_tuple, w_keywords) + +def build_statvfs_result(space, st): + vals_w = [None] * len(ll_os_stat.STATVFS_FIELDS) + for i, (name, _) in STATVFS_FIELDS: + vals_w[i] = space.wrap(getattr(st, name)) + w_tuple = space.newtuple(vals_w) + w_statvfs_result = space.getattr(space.getbuiltinmodule(os.name), space.wrap('statvfs_result')) + return space.call_function(w_statvfs_result, w_tuple) + + @unwrap_spec(fd=c_int) def fstat(space, fd): """Perform a stat system call on the file referenced to by an open @@ -314,6 +327,26 @@ else: state.stat_float_times = space.bool_w(w_value) + +@unwrap_spec(fd=c_int) +def fstatvfs(space, fd): + try: + st = os.fstatvfs(fd) + except OSError as e: + raise wrap_oserror(space, e) + else: + return build_statvfs_result(space, st) + + +def statvfs(space, w_path): + try: + st = dispatch_filename(rposix.statvfs)(space, w_path) + except OSError as e: + raise wrap_oserror2(space, e, w_path) + else: + return build_statvfs_result(space, st) + + @unwrap_spec(fd=c_int) def dup(space, fd): """Create a copy of the file descriptor. Return the new file diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -169,7 +169,8 @@ assert stat.S_ISDIR(st.st_mode) def test_stat_exception(self): - import sys, errno + import sys + import errno for fn in [self.posix.stat, self.posix.lstat]: try: fn("nonexistentdir/nonexistentfile") @@ -183,6 +184,15 @@ assert isinstance(e, WindowsError) assert e.winerror == 3 + def test_statvfs(self): + st = self.posix.statvfs(".") + assert isinstance(st, self.posix.statvfs_result) + for field in [ + 'f_bsize', 'f_frsize', 'f_blocks', 'f_bfree', 'f_bavail', + 'f_files', 'f_ffree', 'f_favail', 'f_flag', 'f_namemax', + ]: + assert hasattr(st, field) + def test_pickle(self): import pickle, os st = self.posix.stat(os.curdir) diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py --- a/rpython/rlib/rposix.py +++ b/rpython/rlib/rposix.py @@ -154,6 +154,15 @@ else: return os.lstat(path.as_bytes()) + +@specialize.argtype(0) +def statvfs(path): + if isinstance(path, str): + return os.statvfs(path) + else: + return os.statvfs(path.as_bytes()) + + @specialize.argtype(0) def unlink(path): if isinstance(path, str): diff --git a/rpython/rtyper/module/ll_os.py b/rpython/rtyper/module/ll_os.py --- a/rpython/rtyper/module/ll_os.py +++ b/rpython/rtyper/module/ll_os.py @@ -1698,6 +1698,17 @@ from rpython.rtyper.module import ll_os_stat return ll_os_stat.register_stat_variant('lstat', traits) + @registering(os.fstatvfs) + def register_os_fstatvfs(self): + from rpython.rtyper.module import ll_os_stat + return ll_os_stat.register_statvfs_variant('fstatvfs', StringTraits()) + + @registering_str_unicode(os.statvfs) + def register_os_statvfs(self, traits): + from rpython.rtyper.module import ll_os_stat + return ll_os_stat.register_statvfs_variant('statvfs', traits) + + # ------------------------------- os.W* --------------------------------- w_star = ['WCOREDUMP', 'WIFCONTINUED', 'WIFSTOPPED', diff --git a/rpython/rtyper/module/ll_os_stat.py b/rpython/rtyper/module/ll_os_stat.py --- a/rpython/rtyper/module/ll_os_stat.py +++ b/rpython/rtyper/module/ll_os_stat.py @@ -2,20 +2,22 @@ and os.fstat(). In RPython like in plain Python the stat result can be indexed like a tuple but also exposes the st_xxx attributes. """ -import os, sys + +import os +import sys + from rpython.annotator import model as annmodel -from rpython.tool.pairtype import pairtype -from rpython.tool.sourcetools import func_with_new_name, func_renamer -from rpython.rtyper import extregistry -from rpython.rtyper.extfunc import register_external, extdef -from rpython.rtyper.lltypesystem import rffi, lltype -from rpython.rtyper.tool import rffi_platform as platform -from rpython.rtyper.lltypesystem.rtupletype import TUPLE_TYPE from rpython.rlib import rposix from rpython.rlib.rarithmetic import intmask -from rpython.rlib.objectmodel import specialize +from rpython.rtyper import extregistry +from rpython.rtyper.annlowlevel import hlstr +from rpython.rtyper.extfunc import extdef +from rpython.rtyper.lltypesystem import rffi, lltype +from rpython.rtyper.lltypesystem.rtupletype import TUPLE_TYPE +from rpython.rtyper.tool import rffi_platform as platform +from rpython.tool.pairtype import pairtype +from rpython.tool.sourcetools import func_renamer from rpython.translator.tool.cbuild import ExternalCompilationInfo -from rpython.rtyper.annlowlevel import hlstr # Support for float times is here. # - ALL_STAT_FIELDS contains Float fields if the system can retrieve @@ -47,12 +49,26 @@ ("st_flags", lltype.Signed), #("st_gen", lltype.Signed), -- new in CPy 2.5, not implemented #("st_birthtime", lltype.Float), -- new in CPy 2.5, not implemented - ] +] N_INDEXABLE_FIELDS = 10 # For OO backends, expose only the portable fields (the first 10). PORTABLE_STAT_FIELDS = ALL_STAT_FIELDS[:N_INDEXABLE_FIELDS] +STATVFS_FIELDS = [ + ("f_bsize", lltype.Signed), + ("f_frsize", lltype.Signed), + ("f_blocks", lltype.Signed), + ("f_bfree", lltype.Signed), + ("f_bavail", lltype.Signed), + ("f_files", lltype.Signed), + ("f_ffree", lltype.Signed), + ("f_favail", lltype.Signed), + ("f_flag", lltype.Signed), + ("f_namemax", lltype.Signed), +] + + # ____________________________________________________________ # # Annotation support @@ -79,6 +95,7 @@ def stat_result_reduce(st): return (st[0], st[1], st[2], st[3], st[4], st[5], st[6], st[7], st[8], st[9]) + def stat_result_recreate(tup): return make_stat_result(tup + extra_zeroes) s_reduced = annmodel.SomeTuple([annmodel.lltype_to_annotation(TYPE) @@ -86,6 +103,23 @@ extra_zeroes = (0,) * (len(STAT_FIELDS) - len(PORTABLE_STAT_FIELDS)) return s_reduced, stat_result_reduce, stat_result_recreate + +class SomeStatvfsResult(annmodel.SomeObject): + knowntype = os.statvfs_result + + def rtyper_makerepr(self, rtyper): + from rpython.rtyper.module import r_os_stat + return r_os_stat.StatvfsResultRepr(rtyper) + + def rtyper_makekey_ex(self, rtyper): + return self.__class__, + + def getattr(self, s_attr): + assert s_attr.is_constant() + TYPE = STATVFS_FIELD_TYPES[s_attr.const] + return annmodel.lltype_to_annotation(TYPE) + + class __extend__(pairtype(SomeStatResult, annmodel.SomeInteger)): def getitem((s_sta, s_int)): assert s_int.is_constant(), "os.stat()[index]: index must be constant" @@ -94,7 +128,17 @@ name, TYPE = STAT_FIELDS[index] return annmodel.lltype_to_annotation(TYPE) + +class __extend__(pairtype(SomeStatvfsResult, annmodel.SomeInteger)): + def getitem((s_stat, s_int)): + assert s_int.is_constant() + name, TYPE = STATVFS_FIELDS[s_int.const] + return annmodel.lltype_to_annotation(TYPE) + + s_StatResult = SomeStatResult() +s_StatvfsResult = SomeStatvfsResult() + def make_stat_result(tup): """Turn a tuple into an os.stat_result object.""" @@ -104,6 +148,11 @@ kwds[name] = tup[N_INDEXABLE_FIELDS + i] return os.stat_result(positional, kwds) + +def make_statvfs_result(tup): + return os.statvfs_result(tup) + + class MakeStatResultEntry(extregistry.ExtRegistryEntry): _about_ = make_stat_result @@ -114,22 +163,33 @@ from rpython.rtyper.module import r_os_stat return r_os_stat.specialize_make_stat_result(hop) + +class MakeStatvfsResultEntry(extregistry.ExtRegistryEntry): + _about_ = make_statvfs_result + + def compute_result_annotation(self, s_tup): + return s_StatvfsResult + + def specialize_call(self, hop): + from rpython.rtyper.module import r_os_stat + return r_os_stat.specialize_make_statvfs_result(hop) + # ____________________________________________________________ # # RFFI support if sys.platform.startswith('win'): _name_struct_stat = '_stati64' - INCLUDES = ['sys/types.h', 'sys/stat.h'] + INCLUDES = ['sys/types.h', 'sys/stat.h', 'sys/statvfs.h'] else: _name_struct_stat = 'stat' - INCLUDES = ['sys/types.h', 'sys/stat.h', 'unistd.h'] + INCLUDES = ['sys/types.h', 'sys/stat.h', 'sys/statvfs.h', 'unistd.h'] compilation_info = ExternalCompilationInfo( # This must be set to 64 on some systems to enable large file support. #pre_include_bits = ['#define _FILE_OFFSET_BITS 64'], # ^^^ nowadays it's always set in all C files we produce. - includes = INCLUDES + includes=INCLUDES ) if TIMESPEC is not None: @@ -141,7 +201,7 @@ def posix_declaration(try_to_add=None): - global STAT_STRUCT + global STAT_STRUCT, STATVFS_STRUCT LL_STAT_FIELDS = STAT_FIELDS[:] if try_to_add: @@ -173,15 +233,17 @@ class CConfig: _compilation_info_ = compilation_info STAT_STRUCT = platform.Struct('struct %s' % _name_struct_stat, LL_STAT_FIELDS) + STATVFS_STRUCT = platform.Struct('struct statvfs', STATVFS_FIELDS) + try: - config = platform.configure(CConfig, ignore_errors= - try_to_add is not None) + config = platform.configure(CConfig, ignore_errors=try_to_add is not None) except platform.CompilationError: if try_to_add: return # failed to add this field, give up raise STAT_STRUCT = lltype.Ptr(config['STAT_STRUCT']) + STATVFS_STRUCT = lltype.Ptr(config['STATVFS_STRUCT']) if try_to_add: STAT_FIELDS.append(try_to_add) @@ -202,6 +264,9 @@ STAT_FIELD_NAMES = [_name for (_name, _TYPE) in STAT_FIELDS] del _name, _TYPE +STATVFS_FIELD_TYPES = dict(STATVFS_FIELDS) +STATVFS_FIELD_NAMES = [name for name, tp in STATVFS_FIELDS] + def build_stat_result(st): # only for LL backends @@ -233,6 +298,21 @@ return make_stat_result(result) +def build_statvfs_result(st): + return make_statvfs_result(( + st.c_f_bsize, + st.c_f_frsize, + st.c_f_blocks, + st.c_f_bfree, + st.c_f_bavail, + st.c_f_files, + st.c_f_ffree, + st.c_f_favail, + st.c_f_flag, + st.c_f_namemax + )) + + def register_stat_variant(name, traits): if name != 'fstat': arg_is_path = True @@ -301,6 +381,56 @@ [s_arg], s_StatResult, "ll_os.ll_os_%s" % (name,), llimpl=posix_stat_llimpl, llfakeimpl=posix_fakeimpl) + +def register_statvfs_variant(name, traits): + if name != 'fstatvfs': + arg_is_path = True + s_arg = traits.str0 + ARG1 = traits.CCHARP + else: + arg_is_path = False + s_arg = int + ARG1 = rffi.INT + + posix_mystatvfs = rffi.llexternal(name, + [ARG1, STATVFS_STRUCT], rffi.INT, + compilation_info=compilation_info + ) + + @func_renamer('os_%s_llimpl' % (name,)) + def posix_statvfs_llimpl(arg): + stresult = lltype.malloc(STATVFS_STRUCT.TO, flavor='raw') + try: + if arg_is_path: + arg = traits.str2charp(arg) + error = rffi.cast(rffi.LONG, posix_mystatvfs(arg, stresult)) + if arg_is_path: + traits.free_charp(arg) + if error != 0: + raise OSError(rposix.get_errno(), "os_?statvfs failed") + return build_statvfs_result(stresult) + finally: + lltype.free(stresult, flavor='raw') + + @func_renamer('os_%s_fake' % (name,)) + def posix_fakeimpl(arg): + if s_arg == traits.str0: + arg = hlstr(arg) + st = getattr(os, name)(arg) + fields = [TYPE for fieldname, TYPE in STATVFS_FIELDS] + TP = TUPLE_TYPE(fields) + ll_tup = lltype.malloc(TP.TO) + for i, (fieldname, TYPE) in enumerate(STATVFS_FIELDS): + val = getattr(st, fieldname) + rffi.setintfield(ll_tup, 'item%d' % i, int(val)) + return ll_tup + + return extdef( + [s_arg], s_StatvfsResult, "ll_os.ll_os_%s" % (name,), + llimpl=posix_statvfs_llimpl, llfakeimpl=posix_fakeimpl + ) + + def make_win32_stat_impl(name, traits): from rpython.rlib import rwin32 from rpython.rtyper.module.ll_win32file import make_win32_traits diff --git a/rpython/rtyper/module/r_os_stat.py b/rpython/rtyper/module/r_os_stat.py --- a/rpython/rtyper/module/r_os_stat.py +++ b/rpython/rtyper/module/r_os_stat.py @@ -67,3 +67,52 @@ # no-op conversion from r_StatResult.r_tuple to r_StatResult hop.exception_cannot_occur() return v_result + + +class StatvfsResultRepr(Repr): + + def __init__(self, rtyper): + self.rtyper = rtyper + self.statvfs_fields = ll_os_stat.STATVFS_FIELDS + + self.statvfs_field_indexes = {} + for i, (name, TYPE) in enumerate(self.statvfs_fields): + self.statvfs_field_indexes[name] = i + + self.s_tuple = annmodel.SomeTuple([annmodel.lltype_to_annotation(TYPE) + for name, TYPE in self.statvfs_fields]) + self.r_tuple = rtyper.getrepr(self.s_tuple) + self.lowleveltype = self.r_tuple.lowleveltype + + def redispatch_getfield(self, hop, index): + rtyper = self.rtyper + s_index = rtyper.annotator.bookkeeper.immutablevalue(index) + hop2 = hop.copy() + hop2.forced_opname = 'getitem' + hop2.args_v = [hop2.args_v[0], Constant(index)] + hop2.args_s = [self.s_tuple, s_index] + hop2.args_r = [self.r_tuple, rtyper.getrepr(s_index)] + return hop2.dispatch() + + def rtype_getattr(self, hop): + s_attr = hop.args_s[1] + attr = s_attr.const + try: + index = self.statvfs_field_indexes[attr] + except KeyError: + raise TyperError("os.statvfs().%s: field not available" % (attr,)) + return self.redispatch_getfield(hop, index) + + +class __extend__(pairtype(StatvfsResultRepr, IntegerRepr)): + def rtype_getitem((r_sta, r_int), hop): + s_int = hop.args_s[1] + index = s_int.const + return r_sta.redispatch_getfield(hop, index) + + +def specialize_make_statvfs_result(hop): + r_StatvfsResult = hop.rtyper.getrepr(ll_os_stat.s_StatvfsResult) + [v_result] = hop.inputargs(r_StatvfsResult.r_tuple) + hop.exception_cannot_occur() + return v_result _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit