Author: Philip Jenvey <[email protected]>
Branch: py3k
Changeset: r65675:c8db1997988c
Date: 2013-07-25 16:40 -0700
http://bitbucket.org/pypy/pypy/changeset/c8db1997988c/
Log: merge 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/doc/coding-guide.rst b/pypy/doc/coding-guide.rst
--- a/pypy/doc/coding-guide.rst
+++ b/pypy/doc/coding-guide.rst
@@ -626,7 +626,7 @@
Here is the order in which PyPy looks up Python modules:
-*pypy/modules*
+*pypy/module*
mixed interpreter/app-level builtin modules, such as
the ``sys`` and ``__builtin__`` module.
@@ -657,7 +657,7 @@
on some classes being old-style.
We just maintain those changes in place,
-to see what is changed we have a branch called `vendot/stdlib`
+to see what is changed we have a branch called `vendor/stdlib`
wich contains the unmodified cpython stdlib
.. _`mixed module mechanism`:
diff --git a/pypy/doc/how-to-release.rst b/pypy/doc/how-to-release.rst
--- a/pypy/doc/how-to-release.rst
+++ b/pypy/doc/how-to-release.rst
@@ -30,7 +30,7 @@
* update README
* change the tracker to have a new release tag to file bugs against
* go to pypy/tool/release and run:
- force-builds.py /release/<release branch>
+ force-builds.py <release branch>
* wait for builds to complete, make sure there are no failures
* upload binaries to https://bitbucket.org/pypy/pypy/downloads
diff --git a/pypy/doc/release-2.1.0-beta2.rst b/pypy/doc/release-2.1.0-beta2.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-2.1.0-beta2.rst
@@ -0,0 +1,62 @@
+===============
+PyPy 2.1 beta 2
+===============
+
+We're pleased to announce the second beta of the upcoming 2.1 release of PyPy.
+This beta adds one new feature to the 2.1 release and contains several
bugfixes listed below.
+
+Highlights
+==========
+
+* Support for os.statvfs and os.fstatvfs on unix systems.
+
+* Fixed issue `1533`_: fix an RPython-level OverflowError for
space.float_w(w_big_long_number).
+
+* Fixed issue `1552`_: GreenletExit should inherit from BaseException.
+
+* Fixed issue `1537`_: numpypy __array_interface__
+
+* Fixed issue `1238`_: Writing to an SSL socket in pypy sometimes failed with
a "bad write retry" message.
+
+* `distutils`_: copy CPython's implementation of customize_compiler, dont call
+ split on environment variables, honour CFLAGS, CPPFLAGS, LDSHARED and
+ LDFLAGS.
+
+* During packaging, compile the CFFI tk extension.
+
+.. _`1533`: https://bugs.pypy.org/issue1533
+.. _`1552`: https://bugs.pypy.org/issue1552
+.. _`1537`: https://bugs.pypy.org/issue1537
+.. _`1238`: https://bugs.pypy.org/issue1238
+.. _`distutils`:
https://bitbucket.org/pypy/pypy/src/0c6eeae0316c11146f47fcf83e21e24f11378be1/?at=distutils-cppldflags
+
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7.3. It's fast due to its integrated tracing JIT compiler.
+
+This release supports x86 machines running Linux 32/64, Mac OS X 64 or Windows
+32. Also this release supports ARM machines running Linux 32bit - anything with
+``ARMv6`` (like the Raspberry Pi) or ``ARMv7`` (like Beagleboard,
+Chromebook, Cubieboard, etc.) that supports ``VFPv3`` should work.
+
+Windows 64 work is still stalling, we would welcome a volunteer
+to handle that.
+
+How to use PyPy?
+================
+
+We suggest using PyPy from a `virtualenv`_. Once you have a virtualenv
+installed, you can follow instructions from `pypy documentation`_ on how
+to proceed. This document also covers other `installation schemes`_.
+
+.. _`pypy documentation`:
http://doc.pypy.org/en/latest/getting-started.html#installing-using-virtualenv
+.. _`virtualenv`: http://www.virtualenv.org/en/latest/
+.. _`installation schemes`:
http://doc.pypy.org/en/latest/getting-started.html#installing-pypy
+.. _`PyPy and pip`:
http://doc.pypy.org/en/latest/getting-started.html#installing-pypy
+
+
+Cheers,
+The PyPy Team.
diff --git a/pypy/doc/rffi.rst b/pypy/doc/rffi.rst
--- a/pypy/doc/rffi.rst
+++ b/pypy/doc/rffi.rst
@@ -43,7 +43,7 @@
See cbuild_ for more info on ExternalCompilationInfo.
.. _`low level types`: rtyper.html#low-level-type
-.. _cbuild:
https://bitbucket.org/pypy/pypy/src/tip/pypy/translator/tool/cbuild.py
+.. _cbuild:
https://bitbucket.org/pypy/pypy/src/tip/rpython/translator/tool/cbuild.py
Types
@@ -69,9 +69,3 @@
as a fake low-level implementation for tests performed by an llinterp.
.. _`extfunc.py`:
https://bitbucket.org/pypy/pypy/src/tip/pypy/rpython/extfunc.py
-
-
-OO backends
------------
-
-XXX to be written
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -31,3 +31,15 @@
more precise information about which functions can be called. Needed for Topaz.
.. branch: ssl_moving_write_buffer
+
+.. branch: pythoninspect-fix
+Make PyPy respect PYTHONINSPECT variable set via os.putenv in the same process
+to start interactive prompt when the script execution finishes. This adds
+new __pypy__.os.real_getenv call that bypasses Python cache and looksup env
+in the underlying OS. Translatorshell now works on PyPy.
+
+.. branch: add-statvfs
+Added os.statvfs and os.fstatvfs
+
+.. branch: statvfs_tests
+Added some addition tests for statvfs.
diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py
--- a/pypy/interpreter/app_main.py
+++ b/pypy/interpreter/app_main.py
@@ -550,8 +550,15 @@
# or
# * PYTHONINSPECT is set and stdin is a tty.
#
+ try:
+ # we need a version of getenv that bypasses Python caching
+ from __pypy__.os import real_getenv
+ except ImportError:
+ # dont fail on CPython here
+ real_getenv = os.getenv
+
return (interactive or
- ((inspect or (readenv and os.getenv('PYTHONINSPECT')))
+ ((inspect or (readenv and real_getenv('PYTHONINSPECT')))
and sys.stdin.isatty()))
success = True
diff --git a/pypy/interpreter/test/test_app_main.py
b/pypy/interpreter/test/test_app_main.py
--- a/pypy/interpreter/test/test_app_main.py
+++ b/pypy/interpreter/test/test_app_main.py
@@ -58,7 +58,7 @@
pdir = _get_next_path(ext='')
p = pdir.ensure(dir=1).join('__main__.py')
p.write(str(py.code.Source(source)))
- # return relative path for testing purposes
+ # return relative path for testing purposes
return py.path.local().bestrelpath(pdir)
def pytest_funcarg__demo_script(request):
@@ -768,6 +768,20 @@
expect_prompt=True, expect_banner=False)
assert '42\n' in data
+ def test_putenv_fires_interactive_within_process(self):
+ try:
+ import __pypy__
+ except ImportError:
+ py.test.skip("This can be only tested on PyPy with real_getenv")
+
+ # should be noninteractive when piped in
+ data = 'import os\nos.putenv("PYTHONINSPECT", "1")\n'
+ self.run('', senddata=data, expect_prompt=False)
+
+ # should go interactive with -c
+ data = data.replace('\n', ';')
+ self.run("-c '%s'" % data, expect_prompt=True)
+
def test_option_S_copyright(self):
data = self.run('-S -i', expect_prompt=True, expect_banner=True)
assert 'copyright' not in data
@@ -1090,7 +1104,7 @@
pypy_c = os.path.join(self.trunkdir, 'pypy', 'goal', 'pypy-c')
app_main.setup_bootstrap_path(pypy_c)
newpath = sys.path[:]
- # we get at least lib_pypy
+ # we get at least lib_pypy
# lib-python/X.Y.Z, and maybe more (e.g. plat-linux2)
assert len(newpath) >= 2
for p in newpath:
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -50,6 +50,13 @@
}
+class OsModule(MixedModule):
+ appleveldefs = {}
+ interpleveldefs = {
+ 'real_getenv': 'interp_os.real_getenv'
+ }
+
+
class Module(MixedModule):
appleveldefs = {
}
@@ -82,6 +89,7 @@
"time": TimeModule,
"thread": ThreadModule,
"intop": IntOpModule,
+ "os": OsModule,
}
def setup_after_space_initialization(self):
diff --git a/pypy/module/__pypy__/interp_os.py
b/pypy/module/__pypy__/interp_os.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/__pypy__/interp_os.py
@@ -0,0 +1,9 @@
+import os
+
+from pypy.interpreter.gateway import unwrap_spec
+
+
+@unwrap_spec(name='str0')
+def real_getenv(space, name):
+ """Get an OS environment value skipping Python cache"""
+ return space.wrap(os.environ.get(name))
diff --git a/pypy/module/__pypy__/test/test_os.py
b/pypy/module/__pypy__/test/test_os.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/__pypy__/test/test_os.py
@@ -0,0 +1,16 @@
+class AppTestOs:
+ spaceconfig = dict(usemodules=['__pypy__'])
+
+ def test_real_getenv(self):
+ import __pypy__.os
+ import os
+
+ key = 'UNLIKELY_SET'
+ assert key not in os.environ
+ os.putenv(key, '42')
+ # this one skips Python cache
+ assert __pypy__.os.real_getenv(key) == '42'
+ # this one can only see things set on interpter start (cached)
+ assert os.getenv(key) is None
+ os.unsetenv(key)
+ assert __pypy__.os.real_getenv(key) is None
diff --git a/pypy/module/_cffi_backend/libraryobj.py
b/pypy/module/_cffi_backend/libraryobj.py
--- a/pypy/module/_cffi_backend/libraryobj.py
+++ b/pypy/module/_cffi_backend/libraryobj.py
@@ -4,6 +4,7 @@
from pypy.interpreter.error import operationerrfmt
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.typedef import TypeDef
+from pypy.module._rawffi.interp_rawffi import wrap_dlopenerror
from rpython.rtyper.lltypesystem import rffi
from rpython.rlib.rdynload import DLLHANDLE, dlopen, dlsym, dlclose,
DLOpenError
@@ -24,9 +25,7 @@
try:
self.handle = dlopen(ll_libname, flags)
except DLOpenError, e:
- raise operationerrfmt(space.w_OSError,
- "cannot load library %s: %s",
- filename, e.msg)
+ raise wrap_dlopenerror(space, e, filename)
self.name = filename
def __del__(self):
diff --git a/pypy/module/_ffi/interp_funcptr.py
b/pypy/module/_ffi/interp_funcptr.py
--- a/pypy/module/_ffi/interp_funcptr.py
+++ b/pypy/module/_ffi/interp_funcptr.py
@@ -14,7 +14,7 @@
from rpython.rlib.rarithmetic import r_uint
from rpython.rlib.objectmodel import we_are_translated
from pypy.module._ffi.type_converter import FromAppLevelConverter,
ToAppLevelConverter
-from pypy.module._rawffi.interp_rawffi import got_libffi_error
+from pypy.module._rawffi.interp_rawffi import got_libffi_error,
wrap_dlopenerror
import os
if os.name == 'nt':
@@ -325,8 +325,7 @@
try:
self.cdll = libffi.CDLL(name, mode)
except DLOpenError, e:
- raise operationerrfmt(space.w_OSError, '%s: %s', self.name,
- e.msg or 'unspecified error')
+ raise wrap_dlopenerror(space, e, self.name)
def getfunc(self, space, w_name, w_argtypes, w_restype):
return _getfunc(space, self, w_name, w_argtypes, w_restype)
diff --git a/pypy/module/_ffi/test/test_type_converter.py
b/pypy/module/_ffi/test/test_type_converter.py
--- a/pypy/module/_ffi/test/test_type_converter.py
+++ b/pypy/module/_ffi/test/test_type_converter.py
@@ -150,7 +150,7 @@
return self.do_and_wrap(w_ffitype)
-class TestFromAppLevel(object):
+class TestToAppLevel(object):
spaceconfig = dict(usemodules=('_ffi',))
def setup_class(cls):
diff --git a/pypy/module/_rawffi/interp_rawffi.py
b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -141,6 +141,11 @@
raise OperationError(space.w_SystemError,
space.wrap("not supported by libffi"))
+def wrap_dlopenerror(space, e, filename):
+ msg = e.msg if e.msg else 'unspecified error'
+ return operationerrfmt(space.w_OSError, 'Cannot load library %s: %s',
+ filename, msg)
+
class W_CDLL(W_Root):
def __init__(self, space, name, cdll):
@@ -220,8 +225,7 @@
try:
cdll = CDLL(name)
except DLOpenError, e:
- raise operationerrfmt(space.w_OSError, '%s: %s', name,
- e.msg or 'unspecified error')
+ raise wrap_dlopenerror(space, e, name)
except OSError, e:
raise wrap_oserror(space, e)
return space.wrap(W_CDLL(space, name, cdll))
diff --git a/pypy/module/_rawffi/test/test__rawffi.py
b/pypy/module/_rawffi/test/test__rawffi.py
--- a/pypy/module/_rawffi/test/test__rawffi.py
+++ b/pypy/module/_rawffi/test/test__rawffi.py
@@ -223,7 +223,8 @@
_rawffi.CDLL("xxxxx_this_name_does_not_exist_xxxxx")
except OSError as e:
print(e)
- assert str(e).startswith("xxxxx_this_name_does_not_exist_xxxxx: ")
+ assert str(e).startswith(
+ "Cannot load library xxxxx_this_name_does_not_exist_xxxxx: ")
else:
raise AssertionError("did not fail??")
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
@@ -32,18 +33,18 @@
applevel_name = os.name
appleveldefs = {
- 'error' : 'app_posix.error',
- 'stat_result': 'app_posix.stat_result',
- 'urandom': 'app_posix.urandom',
- 'statvfs_result': 'app_posix.statvfs_result',
+ 'error': 'app_posix.error',
+ 'stat_result': 'app_posix.stat_result',
+ 'statvfs_result': 'app_posix.statvfs_result',
+ 'urandom': 'app_posix.urandom',
}
if os.name == 'nt':
del appleveldefs['urandom'] # at interp on win32
appleveldefs.update({
- 'popen2' : 'app_posix.popen2',
- 'popen3' : 'app_posix.popen3',
- 'popen4' : 'app_posix.popen4',
- })
+ 'popen2': 'app_posix.popen2',
+ 'popen3': 'app_posix.popen3',
+ 'popen4': 'app_posix.popen4',
+ })
if hasattr(os, 'wait'):
appleveldefs['wait'] = 'app_posix.wait'
@@ -51,45 +52,47 @@
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',
- 'getcwdb' : 'interp_posix.getcwdb',
- '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',
- 'device_encoding' : 'interp_posix.device_encoding',
+ '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',
+ 'getcwdb': 'interp_posix.getcwdb',
+ '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',
+ 'device_encoding': 'interp_posix.device_encoding',
}
if hasattr(os, 'chown'):
@@ -166,9 +169,9 @@
interpleveldefs['getlogin'] = 'interp_posix.getlogin'
for name in ['setsid', 'getuid', 'geteuid', 'getgid', 'getegid', 'setuid',
- 'seteuid', 'setgid', 'setegid', 'getgroups', 'getpgrp',
- 'setpgrp', 'getppid', 'getpgid', 'setpgid', 'setreuid',
- 'setregid', 'getsid', 'setsid']:
+ 'seteuid', 'setgid', 'setegid', 'getgroups', 'getpgrp',
+ 'setpgrp', 'getppid', 'getpgid', 'setpgid', 'setreuid',
+ 'setregid', 'getsid', 'setsid', 'fstatvfs', 'statvfs']:
if hasattr(os, name):
interpleveldefs[name] = 'interp_posix.%s' % (name,)
# not visible via os, inconsistency in nt:
@@ -176,7 +179,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
@@ -185,7 +188,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)
@@ -193,7 +196,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,14 +1,16 @@
-from pypy.interpreter.gateway import unwrap_spec, WrappedDefault
+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, WrappedDefault
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
-import os
-import sys
_WIN32 = sys.platform == 'win32'
if _WIN32:
@@ -203,6 +205,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':
@@ -243,6 +246,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
@@ -304,6 +317,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
@@ -168,7 +168,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")
@@ -182,6 +183,16 @@
assert isinstance(e, WindowsError)
assert e.winerror == 3
+ if hasattr(__import__(os.name), "statvfs"):
+ 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/pypy/module/pypyjit/interp_resop.py
b/pypy/module/pypyjit/interp_resop.py
--- a/pypy/module/pypyjit/interp_resop.py
+++ b/pypy/module/pypyjit/interp_resop.py
@@ -125,6 +125,9 @@
self.llbox = llbox
def descr_getint(self, space):
+ if not jit_hooks.box_isint(self.llbox):
+ raise OperationError(space.w_NotImplementedError,
+ space.wrap("Box has no int value"))
return space.wrap(jit_hooks.box_getint(self.llbox))
@unwrap_spec(no=int)
@@ -182,7 +185,12 @@
@unwrap_spec(no=int)
def descr_getarg(self, space, no):
- return WrappedBox(jit_hooks.resop_getarg(self.op, no))
+ try:
+ box = jit_hooks.resop_getarg(self.op, no)
+ except IndexError:
+ raise OperationError(space.w_IndexError,
+ space.wrap("Index out of range"))
+ return WrappedBox(box)
@unwrap_spec(no=int, w_box=WrappedBox)
def descr_setarg(self, space, no, w_box):
@@ -232,7 +240,8 @@
getarg = interp2app(WrappedOp.descr_getarg),
setarg = interp2app(WrappedOp.descr_setarg),
result = GetSetProperty(WrappedOp.descr_getresult,
- WrappedOp.descr_setresult)
+ WrappedOp.descr_setresult),
+ offset = interp_attrproperty("offset", cls=WrappedOp),
)
WrappedOp.acceptable_as_base_class = False
@@ -342,6 +351,10 @@
doc="bridge number (if a bridge)"),
type = interp_attrproperty('type', cls=W_JitLoopInfo,
doc="Loop type"),
+ asmaddr = interp_attrproperty('asmaddr', cls=W_JitLoopInfo,
+ doc="Address of machine code"),
+ asmlen = interp_attrproperty('asmlen', cls=W_JitLoopInfo,
+ doc="Length of machine code"),
__repr__ = interp2app(W_JitLoopInfo.descr_repr),
)
W_JitLoopInfo.acceptable_as_base_class = False
diff --git a/pypy/module/pypyjit/test/test_jit_hook.py
b/pypy/module/pypyjit/test/test_jit_hook.py
--- a/pypy/module/pypyjit/test/test_jit_hook.py
+++ b/pypy/module/pypyjit/test/test_jit_hook.py
@@ -71,7 +71,7 @@
greenkey)
di_loop_optimize = JitDebugInfo(MockJitDriverSD, logger,
JitCellToken(),
oplist, 'loop', greenkey)
- di_loop.asminfo = AsmInfo(offset, 0, 0)
+ di_loop.asminfo = AsmInfo(offset, 0x42, 12)
di_bridge = JitDebugInfo(MockJitDriverSD, logger, JitCellToken(),
oplist, 'bridge', fail_descr=BasicFailDescr())
di_bridge.asminfo = AsmInfo(offset, 0, 0)
@@ -123,6 +123,8 @@
assert info.greenkey[2] == False
assert info.loop_no == 0
assert info.type == 'loop'
+ assert info.asmaddr == 0x42
+ assert info.asmlen == 12
raises(TypeError, 'info.bridge_no')
assert len(info.operations) == 4
int_add = info.operations[0]
@@ -132,8 +134,10 @@
assert dmp.greenkey == (self.f.__code__, 0, False)
assert dmp.call_depth == 0
assert dmp.call_id == 0
+ assert dmp.offset == -1
assert int_add.name == 'int_add'
assert int_add.num == self.int_add_num
+ assert int_add.offset == 0
self.on_compile_bridge()
expected = ('<JitLoopInfo pypyjit, 4 operations, starting at '
'<(%s, 0, False)>>' % repr(self.f.__code__))
@@ -161,6 +165,20 @@
assert 'jit hook' in s.getvalue()
assert 'ZeroDivisionError' in s.getvalue()
+ def test_on_compile_crashes(self):
+ import pypyjit
+ loops = []
+ def hook(loop):
+ loops.append(loop)
+ pypyjit.set_compile_hook(hook)
+ self.on_compile()
+ loop = loops[0]
+ op = loop.operations[2]
+ # Should not crash the interpreter
+ raises(IndexError, op.getarg, 2)
+ assert op.name == 'guard_nonnull'
+ raises(NotImplementedError, op.getarg(0).getint)
+
def test_non_reentrant(self):
import pypyjit
l = []
diff --git a/rpython/jit/backend/x86/assembler.py
b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -735,6 +735,10 @@
self.mc.RET()
def _load_shadowstack_top_in_ebx(self, mc, gcrootmap):
+ """Loads the shadowstack top in ebx, and returns an integer
+ that gives the address of the stack top. If this integer doesn't
+ fit in 32 bits, it will be loaded in r11.
+ """
rst = gcrootmap.get_root_stack_top_addr()
if rx86.fits_in_32bits(rst):
mc.MOV_rj(ebx.value, rst) # MOV ebx, [rootstacktop]
@@ -752,6 +756,9 @@
if rx86.fits_in_32bits(rst):
self.mc.MOV_jr(rst, ebx.value) # MOV [rootstacktop], ebx
else:
+ # The integer 'rst' doesn't fit in 32 bits, so we know that
+ # _load_shadowstack_top_in_ebx() above loaded it in r11.
+ # Reuse it. Be careful not to overwrite r11 in the middle!
self.mc.MOV_mr((X86_64_SCRATCH_REG.value, 0),
ebx.value) # MOV [r11], ebx
diff --git a/rpython/jit/tool/test/f.pypylog.bz2
b/rpython/jit/tool/test/f.pypylog.bz2
new file mode 100644
index
0000000000000000000000000000000000000000..a982e459b1daa33547576733ccc0b560f99a3f79
GIT binary patch
[cut]
diff --git a/rpython/jit/tool/test/test_traceviewer.py
b/rpython/jit/tool/test/test_traceviewer.py
--- a/rpython/jit/tool/test/test_traceviewer.py
+++ b/rpython/jit/tool/test/test_traceviewer.py
@@ -1,7 +1,7 @@
import math
import py
from rpython.jit.tool.traceviewer import splitloops, FinalBlock, Block,\
- split_one_loop, postprocess, main, get_gradient_color
+ split_one_loop, postprocess, main, get_gradient_color, guard_number
def test_gradient_color():
@@ -30,6 +30,20 @@
loops = splitloops(data)
assert len(loops) == 2
+ def test_no_of_loops_hexguards(self):
+ data = [preparse("""
+ # Loop 0 : loop with 39 ops
+ debug_merge_point('', 0)
+ guard_class(p4, 141310752, descr=<Guard0x10abcdef0>) [p0, p1]
+ p60 = getfield_gc(p4, descr=<GcPtrFieldDescr 16>)
+ guard_nonnull(p60, descr=<Guard0x10abcdef1>) [p0, p1]
+ """), preparse("""
+ # Loop 1 : loop with 46 ops
+ p21 = getfield_gc(p4, descr=<GcPtrFieldDescr 16>)
+ """)]
+ loops = splitloops(data)
+ assert len(loops) == 2
+
def test_split_one_loop(self):
real_loops = [FinalBlock(preparse("""
p21 = getfield_gc(p4, descr=<GcPtrFieldDescr 16>)
@@ -50,12 +64,42 @@
assert loop.left.content == ''
assert loop.right.content == 'extra'
+ def test_split_one_loop_hexguards(self):
+ real_loops = [FinalBlock(preparse("""
+ p21 = getfield_gc(p4, descr=<GcPtrFieldDescr 16>)
+ guard_class(p4, 141310752, descr=<Guard0x10abcdef2>) [p0, p1]
+ """), None), FinalBlock(preparse("""
+ p60 = getfield_gc(p4, descr=<GcPtrFieldDescr 16>)
+ guard_nonnull(p60, descr=<Guard0x10abcdef0>) [p0, p1]
+ """), None)]
+ real_loops[0].loop_no = 0
+ real_loops[1].loop_no = 1
+ allloops = real_loops[:]
+ split_one_loop(real_loops, 'Guard0x10abcdef0', 'extra', 1,
guard_number(("0x10abcdef0", "0x")), allloops)
+ loop = real_loops[1]
+ assert isinstance(loop, Block)
+ assert loop.content.endswith('p1]')
+ loop.left = allloops[loop.left]
+ loop.right = allloops[loop.right]
+ assert loop.left.content == ''
+ assert loop.right.content == 'extra'
+
def test_postparse(self):
real_loops = [FinalBlock("debug_merge_point('<code object
_runCallbacks, file '/tmp/x/twisted-trunk/twisted/internet/defer.py', line 357>
#40 POP_TOP', 0)", None)]
postprocess(real_loops, real_loops[:], {})
assert real_loops[0].header.startswith("_runCallbacks, file
'/tmp/x/twisted-trunk/twisted/internet/defer.py', line 357")
+ def test_postparse_new(self):
+ real_loops = [FinalBlock("debug_merge_point(0, 0, '<code object
_optimize_charset. file
'/usr/local/Cellar/pypy/2.0-beta2/lib-python/2.7/sre_compile.py'. line 207>
#351 LOAD_FAST')", None)]
+ postprocess(real_loops, real_loops[:], {})
+ assert real_loops[0].header.startswith("_optimize_charset. file
'/usr/local/Cellar/pypy/2.0-beta2/lib-python/2.7/sre_compile.py'. line 207")
+
def test_load_actual(self):
fname = py.path.local(__file__).join('..', 'data.log.bz2')
main(str(fname), False, view=False)
# assert did not explode
+
+ def test_load_actual_f(self):
+ fname = py.path.local(__file__).join('..', 'f.pypylog.bz2')
+ main(str(fname), False, view=False)
+ # assert did not explode
diff --git a/rpython/jit/tool/traceviewer.py b/rpython/jit/tool/traceviewer.py
--- a/rpython/jit/tool/traceviewer.py
+++ b/rpython/jit/tool/traceviewer.py
@@ -56,6 +56,18 @@
BOX_COLOR = (128, 0, 96)
+GUARDNO_RE = "((0x)?[\da-f]+)"
+def guard_number(guardno_match):
+ if (len(guardno_match) == 1 # ("12354",)
+ or guardno_match[1] != "0x" # ("12345", None)
+ ):
+ return int(guardno_match[0])
+ else: # ("0x12ef", "0x")
+ return int(guardno_match[0], 16)
+
+def guard_number_string(guardno_match):
+ return guardno_match[0] # its always the first group
+
class BasicBlock(object):
counter = 0
startlineno = 0
@@ -85,13 +97,15 @@
def set_content(self, content):
self._content = content
- groups = re.findall('Guard(\d+)', content)
+ groups = re.findall('Guard' + GUARDNO_RE, content)
if not groups:
self.first_guard = -1
self.last_guard = -1
else:
- self.first_guard = int(groups[0])
- self.last_guard = int(groups[-1])
+ # guards can be out of order nowadays
+ groups = sorted(groups)
+ self.first_guard = guard_number(groups[0])
+ self.last_guard = guard_number(groups[-1])
content = property(get_content, set_content)
@@ -197,11 +211,11 @@
_loop.loop_no = no
allloops.append(_loop)
else:
- m = re.search("bridge out of Guard (\d+)", firstline)
+ m = re.search("bridge out of Guard " + GUARDNO_RE, firstline)
assert m
- guard_s = 'Guard' + m.group(1)
+ guard_s = 'Guard' + guard_number_string(m.groups())
split_one_loop(real_loops, guard_s, loop, counter,
- int(m.group(1)), allloops)
+ guard_number(m.groups()), allloops)
counter += loop.count("\n") + 2
return real_loops, allloops
@@ -211,7 +225,7 @@
memo.add(loop)
if loop is None:
return
- m = re.search("debug_merge_point\('(<code object (.*?)> (.*?))'",
loop.content)
+ m = re.search("debug_merge_point\((?:\d+,\ )*'(<code object (.*?)>
(.*?))'", loop.content)
if m is None:
name = '?'
loop.key = '?'
@@ -236,7 +250,7 @@
content = loop.content
loop.content = "Logfile at %d\n" % loop.startlineno + content
loop.postprocess(loops, memo, counts)
-
+
def postprocess(loops, allloops, counts):
for loop in allloops:
if isinstance(loop, Block):
diff --git a/rpython/rlib/jit_hooks.py b/rpython/rlib/jit_hooks.py
--- a/rpython/rlib/jit_hooks.py
+++ b/rpython/rlib/jit_hooks.py
@@ -111,6 +111,11 @@
from rpython.jit.metainterp.history import Const
return isinstance(_cast_to_box(llbox), Const)
+@register_helper(annmodel.SomeBool())
+def box_isint(llbox):
+ from rpython.jit.metainterp.history import INT
+ return _cast_to_box(llbox).type == INT
+
# ------------------------- stats interface ---------------------------
@register_helper(annmodel.SomeBool())
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())
+
[email protected](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,18 @@
from rpython.rtyper.module import ll_os_stat
return ll_os_stat.register_stat_variant('lstat', traits)
+ @registering_if(os, 'fstatvfs')
+ def register_os_fstatvfs(self):
+ from rpython.rtyper.module import ll_os_stat
+ return ll_os_stat.register_statvfs_variant('fstatvfs', StringTraits())
+
+ if hasattr(os, 'statvfs'):
+ @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,26 @@
extra_zeroes = (0,) * (len(STAT_FIELDS) - len(PORTABLE_STAT_FIELDS))
return s_reduced, stat_result_reduce, stat_result_recreate
+
+class SomeStatvfsResult(annmodel.SomeObject):
+ if hasattr(os, 'statvfs_result'):
+ knowntype = os.statvfs_result
+ else:
+ knowntype = None # will not be used
+
+ 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 +131,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 +151,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 +166,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 +204,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 +236,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 +267,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 +301,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 +384,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
diff --git a/rpython/rtyper/module/test/test_ll_os.py
b/rpython/rtyper/module/test/test_ll_os.py
--- a/rpython/rtyper/module/test/test_ll_os.py
+++ b/rpython/rtyper/module/test/test_ll_os.py
@@ -46,6 +46,26 @@
data = getllimpl(os.getlogin)()
assert data == expected
+def test_statvfs():
+ if not hasattr(os, 'statvfs'):
+ py.test.skip('posix specific function')
+ try:
+ expected = os.statvfs('.')
+ except OSError, e:
+ py.test.skip("the underlying os.statvfs() failed: %s" % e)
+ data = getllimpl(os.statvfs)('.')
+ assert data == expected
+
+def test_fstatvfs():
+ if not hasattr(os, 'fstatvfs'):
+ py.test.skip('posix specific function')
+ try:
+ expected = os.fstatvfs(0)
+ except OSError, e:
+ py.test.skip("the underlying os.fstatvfs() failed: %s" % e)
+ data = getllimpl(os.fstatvfs)(0)
+ assert data == expected
+
def test_utimes():
if os.name != 'nt':
py.test.skip('Windows specific feature')
diff --git a/rpython/translator/c/gcc/trackgcroot.py
b/rpython/translator/c/gcc/trackgcroot.py
--- a/rpython/translator/c/gcc/trackgcroot.py
+++ b/rpython/translator/c/gcc/trackgcroot.py
@@ -478,7 +478,7 @@
'rep', 'movs', 'movhp', 'lods', 'stos', 'scas', 'cwde', 'prefetch',
# floating-point operations cannot produce GC pointers
'f',
- 'cvt', 'ucomi', 'comi', 'subs', 'subp' , 'adds', 'addp', 'xorp',
+ 'cvt', 'ucomi', 'comi', 'subs', 'subp', 'adds', 'addp', 'xorp',
'movap', 'movd', 'movlp', 'movup', 'sqrt', 'rsqrt', 'movhlp', 'movlhp',
'mins', 'minp', 'maxs', 'maxp', 'unpck', 'pxor', 'por', # sse2
'shufps', 'shufpd',
@@ -495,13 +495,15 @@
# sign-extending moves should not produce GC pointers
'cbtw', 'cwtl', 'cwtd', 'cltd', 'cltq', 'cqto',
# zero-extending moves should not produce GC pointers
- 'movz',
+ 'movz',
# locked operations should not move GC pointers, at least so far
'lock', 'pause',
# non-temporal moves should be reserved for areas containing
# raw data, not GC pointers
'movnt', 'mfence', 'lfence', 'sfence',
- ])
+ # bit manipulations
+ 'bextr',
+ ])
# a partial list is hopefully good enough for now; it's all to support
# only one corner case, tested in elf64/track_zero.s
@@ -741,7 +743,7 @@
# tail-calls are equivalent to RET for us
return InsnRet(self.CALLEE_SAVE_REGISTERS)
return InsnStop("jump")
-
+
def register_jump_to(self, label, lastinsn=None):
if lastinsn is None:
lastinsn = self.insns[-1]
@@ -1020,7 +1022,7 @@
visit_movl = visit_mov
visit_xorl = _maybe_32bit_dest(FunctionGcRootTracker.binary_insn)
-
+
visit_pushq = FunctionGcRootTracker._visit_push
visit_addq = FunctionGcRootTracker._visit_add
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit