[pypy-commit] pypy cpyext-ext: merge default into branch
mattip
pypy.commits at gmail.com
Mon Apr 18 12:20:24 EDT 2016
Author: mattip <matti.picus at gmail.com>
Branch: cpyext-ext
Changeset: r83746:a734e99db063
Date: 2016-04-18 19:18 +0300
http://bitbucket.org/pypy/pypy/changeset/a734e99db063/
Log: merge default into branch
diff too long, truncating to 2000 out of 10773 lines
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -111,23 +111,24 @@
Simon Burton
Martin Matusiak
Konstantin Lopuhin
+ Stefano Rivera
Wenzhu Man
John Witulski
Laurence Tratt
Ivan Sichmann Freitas
Greg Price
Dario Bertini
- Stefano Rivera
Mark Pearse
Simon Cross
+ Edd Barrett
Andreas Stührk
- Edd Barrett
Jean-Philippe St. Pierre
Guido van Rossum
Pavel Vinogradov
+ Spenser Bauman
Jeremy Thurgood
Paweł Piotr Przeradowski
- Spenser Bauman
+ Tobias Pape
Paul deGrandis
Ilya Osadchiy
marky1991
@@ -139,7 +140,7 @@
Georg Brandl
Bert Freudenberg
Stian Andreassen
- Tobias Pape
+ Mark Young
Wanja Saatkamp
Gerald Klix
Mike Blume
@@ -170,9 +171,9 @@
Yichao Yu
Rocco Moretti
Gintautas Miliauskas
+ Devin Jeanpierre
Michael Twomey
Lucian Branescu Mihaila
- Devin Jeanpierre
Gabriel Lavoie
Olivier Dormond
Jared Grubb
@@ -183,6 +184,7 @@
Victor Stinner
Andrews Medina
anatoly techtonik
+ Sergey Matyunin
Stuart Williams
Jasper Schulz
Christian Hudon
@@ -217,7 +219,6 @@
Arjun Naik
Valentina Mukhamedzhanova
Stefano Parmesan
- Mark Young
Alexis Daboville
Jens-Uwe Mager
Carl Meyer
@@ -225,7 +226,9 @@
Pieter Zieschang
Gabriel
Lukas Vacek
+ Kunal Grover
Andrew Dalke
+ Florin Papa
Sylvain Thenault
Jakub Stasiak
Nathan Taylor
@@ -240,7 +243,6 @@
Kristjan Valur Jonsson
David Lievens
Neil Blakey-Milner
- Sergey Matyunin
Lutz Paelike
Lucio Torre
Lars Wassermann
@@ -252,9 +254,11 @@
Artur Lisiecki
Sergey Kishchenko
Ignas Mikalajunas
+ Alecsandru Patrascu
Christoph Gerum
Martin Blais
Lene Wagner
+ Catalin Gabriel Manciu
Tomo Cocoa
Kim Jin Su
Toni Mattis
@@ -291,6 +295,7 @@
Akira Li
Gustavo Niemeyer
Stephan Busemann
+ florinpapa
Rafał Gałczyński
Matt Bogosian
Christian Muirhead
@@ -305,6 +310,7 @@
Boglarka Vezer
Chris Pressey
Buck Golemon
+ Diana Popa
Konrad Delong
Dinu Gherman
Chris Lambacher
diff --git a/lib_pypy/_ctypes/structure.py b/lib_pypy/_ctypes/structure.py
--- a/lib_pypy/_ctypes/structure.py
+++ b/lib_pypy/_ctypes/structure.py
@@ -67,7 +67,8 @@
subvalue = subfield.ctype
fields[subname] = Field(subname,
relpos, subvalue._sizeofinstances(),
- subvalue, i, is_bitfield)
+ subvalue, i, is_bitfield,
+ inside_anon_field=fields[name])
else:
resnames.append(name)
names = resnames
@@ -77,13 +78,15 @@
class Field(object):
- def __init__(self, name, offset, size, ctype, num, is_bitfield):
+ def __init__(self, name, offset, size, ctype, num, is_bitfield,
+ inside_anon_field=None):
self.__dict__['name'] = name
self.__dict__['offset'] = offset
self.__dict__['size'] = size
self.__dict__['ctype'] = ctype
self.__dict__['num'] = num
self.__dict__['is_bitfield'] = is_bitfield
+ self.__dict__['inside_anon_field'] = inside_anon_field
def __setattr__(self, name, value):
raise AttributeError(name)
@@ -95,6 +98,8 @@
def __get__(self, obj, cls=None):
if obj is None:
return self
+ if self.inside_anon_field is not None:
+ return getattr(self.inside_anon_field.__get__(obj), self.name)
if self.is_bitfield:
# bitfield member, use direct access
return obj._buffer.__getattr__(self.name)
@@ -105,6 +110,9 @@
return fieldtype._CData_output(suba, obj, offset)
def __set__(self, obj, value):
+ if self.inside_anon_field is not None:
+ setattr(self.inside_anon_field.__get__(obj), self.name, value)
+ return
fieldtype = self.ctype
cobj = fieldtype.from_param(value)
key = keepalive_key(self.num)
diff --git a/lib_pypy/_pypy_wait.py b/lib_pypy/_pypy_wait.py
--- a/lib_pypy/_pypy_wait.py
+++ b/lib_pypy/_pypy_wait.py
@@ -1,51 +1,22 @@
-from resource import _struct_rusage, struct_rusage
-from ctypes import CDLL, c_int, POINTER, byref
-from ctypes.util import find_library
+from resource import ffi, lib, _make_struct_rusage
__all__ = ["wait3", "wait4"]
-libc = CDLL(find_library("c"))
-c_wait3 = libc.wait3
-c_wait3.argtypes = [POINTER(c_int), c_int, POINTER(_struct_rusage)]
-c_wait3.restype = c_int
-
-c_wait4 = libc.wait4
-c_wait4.argtypes = [c_int, POINTER(c_int), c_int, POINTER(_struct_rusage)]
-c_wait4.restype = c_int
-
-def create_struct_rusage(c_struct):
- return struct_rusage((
- float(c_struct.ru_utime),
- float(c_struct.ru_stime),
- c_struct.ru_maxrss,
- c_struct.ru_ixrss,
- c_struct.ru_idrss,
- c_struct.ru_isrss,
- c_struct.ru_minflt,
- c_struct.ru_majflt,
- c_struct.ru_nswap,
- c_struct.ru_inblock,
- c_struct.ru_oublock,
- c_struct.ru_msgsnd,
- c_struct.ru_msgrcv,
- c_struct.ru_nsignals,
- c_struct.ru_nvcsw,
- c_struct.ru_nivcsw))
def wait3(options):
- status = c_int()
- _rusage = _struct_rusage()
- pid = c_wait3(byref(status), c_int(options), byref(_rusage))
+ status = ffi.new("int *")
+ ru = ffi.new("struct rusage *")
+ pid = lib.wait3(status, options, ru)
- rusage = create_struct_rusage(_rusage)
+ rusage = _make_struct_rusage(ru)
- return pid, status.value, rusage
+ return pid, status[0], rusage
def wait4(pid, options):
- status = c_int()
- _rusage = _struct_rusage()
- pid = c_wait4(c_int(pid), byref(status), c_int(options), byref(_rusage))
+ status = ffi.new("int *")
+ ru = ffi.new("struct rusage *")
+ pid = lib.wait4(pid, status, options, ru)
- rusage = create_struct_rusage(_rusage)
+ rusage = _make_struct_rusage(ru)
- return pid, status.value, rusage
+ return pid, status[0], rusage
diff --git a/lib_pypy/_resource_build.py b/lib_pypy/_resource_build.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_resource_build.py
@@ -0,0 +1,118 @@
+from cffi import FFI
+
+ffi = FFI()
+
+# Note: we don't directly expose 'struct timeval' or 'struct rlimit'
+
+
+rlimit_consts = '''
+RLIMIT_CPU
+RLIMIT_FSIZE
+RLIMIT_DATA
+RLIMIT_STACK
+RLIMIT_CORE
+RLIMIT_NOFILE
+RLIMIT_OFILE
+RLIMIT_VMEM
+RLIMIT_AS
+RLIMIT_RSS
+RLIMIT_NPROC
+RLIMIT_MEMLOCK
+RLIMIT_SBSIZE
+RLIM_INFINITY
+RUSAGE_SELF
+RUSAGE_CHILDREN
+RUSAGE_BOTH
+'''.split()
+
+rlimit_consts = ['#ifdef %s\n\t{"%s", %s},\n#endif\n' % (s, s, s)
+ for s in rlimit_consts]
+
+
+ffi.set_source("_resource_cffi", """
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+
+static const struct my_rlimit_def {
+ const char *name;
+ long long value;
+} my_rlimit_consts[] = {
+$RLIMIT_CONSTS
+ { NULL, 0 }
+};
+
+#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
+
+static double my_utime(struct rusage *input)
+{
+ return doubletime(input->ru_utime);
+}
+
+static double my_stime(struct rusage *input)
+{
+ return doubletime(input->ru_stime);
+}
+
+static int my_getrlimit(int resource, long long result[2])
+{
+ struct rlimit rl;
+ if (getrlimit(resource, &rl) == -1)
+ return -1;
+ result[0] = rl.rlim_cur;
+ result[1] = rl.rlim_max;
+ return 0;
+}
+
+static int my_setrlimit(int resource, long long cur, long long max)
+{
+ struct rlimit rl;
+ rl.rlim_cur = cur & RLIM_INFINITY;
+ rl.rlim_max = max & RLIM_INFINITY;
+ return setrlimit(resource, &rl);
+}
+
+""".replace('$RLIMIT_CONSTS', ''.join(rlimit_consts)))
+
+
+ffi.cdef("""
+
+#define RLIM_NLIMITS ...
+
+const struct my_rlimit_def {
+ const char *name;
+ long long value;
+} my_rlimit_consts[];
+
+struct rusage {
+ long ru_maxrss;
+ long ru_ixrss;
+ long ru_idrss;
+ long ru_isrss;
+ long ru_minflt;
+ long ru_majflt;
+ long ru_nswap;
+ long ru_inblock;
+ long ru_oublock;
+ long ru_msgsnd;
+ long ru_msgrcv;
+ long ru_nsignals;
+ long ru_nvcsw;
+ long ru_nivcsw;
+ ...;
+};
+
+static double my_utime(struct rusage *);
+static double my_stime(struct rusage *);
+void getrusage(int who, struct rusage *result);
+int my_getrlimit(int resource, long long result[2]);
+int my_setrlimit(int resource, long long cur, long long max);
+
+int wait3(int *status, int options, struct rusage *rusage);
+int wait4(int pid, int *status, int options, struct rusage *rusage);
+""")
+
+
+if __name__ == "__main__":
+ ffi.compile()
diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
--- a/lib_pypy/cffi.egg-info/PKG-INFO
+++ b/lib_pypy/cffi.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: cffi
-Version: 1.5.2
+Version: 1.6.0
Summary: Foreign Function Interface for Python calling C code.
Home-page: http://cffi.readthedocs.org
Author: Armin Rigo, Maciej Fijalkowski
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,8 +4,8 @@
from .api import FFI, CDefError, FFIError
from .ffiplatform import VerificationError, VerificationMissing
-__version__ = "1.5.2"
-__version_info__ = (1, 5, 2)
+__version__ = "1.6.0"
+__version_info__ = (1, 6, 0)
# The verifier module file names are based on the CRC32 of a string that
# contains the following version number. It may be older than __version__
diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h
--- a/lib_pypy/cffi/_embedding.h
+++ b/lib_pypy/cffi/_embedding.h
@@ -233,7 +233,7 @@
f = PySys_GetObject((char *)"stderr");
if (f != NULL && f != Py_None) {
PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
- "\ncompiled with cffi version: 1.5.2"
+ "\ncompiled with cffi version: 1.6.0"
"\n_cffi_backend module: ", f);
modules = PyImport_GetModuleDict();
mod = PyDict_GetItemString(modules, "_cffi_backend");
diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py
--- a/lib_pypy/cffi/api.py
+++ b/lib_pypy/cffi/api.py
@@ -299,6 +299,23 @@
"""
return self._backend.string(cdata, maxlen)
+ def unpack(self, cdata, length):
+ """Unpack an array of C data of the given length,
+ returning a Python string/unicode/list.
+
+ If 'cdata' is a pointer to 'char', returns a byte string.
+ It does not stop at the first null. This is equivalent to:
+ ffi.buffer(cdata, length)[:]
+
+ If 'cdata' is a pointer to 'wchar_t', returns a unicode string.
+ 'length' is measured in wchar_t's; it is not the size in bytes.
+
+ If 'cdata' is a pointer to anything else, returns a list of
+ 'length' items. This is a faster equivalent to:
+ [cdata[i] for i in range(length)]
+ """
+ return self._backend.unpack(cdata, length)
+
def buffer(self, cdata, size=-1):
"""Return a read-write buffer object that references the raw C data
pointed to by the given 'cdata'. The 'cdata' must be a pointer or
@@ -721,6 +738,26 @@
raise ValueError("ffi.def_extern() is only available on API-mode FFI "
"objects")
+ def list_types(self):
+ """Returns the user type names known to this FFI instance.
+ This returns a tuple containing three lists of names:
+ (typedef_names, names_of_structs, names_of_unions)
+ """
+ typedefs = []
+ structs = []
+ unions = []
+ for key in self._parser._declarations:
+ if key.startswith('typedef '):
+ typedefs.append(key[8:])
+ elif key.startswith('struct '):
+ structs.append(key[7:])
+ elif key.startswith('union '):
+ unions.append(key[6:])
+ typedefs.sort()
+ structs.sort()
+ unions.sort()
+ return (typedefs, structs, unions)
+
def _load_backend_lib(backend, name, flags):
if name is None:
diff --git a/lib_pypy/cffi/cparser.py b/lib_pypy/cffi/cparser.py
--- a/lib_pypy/cffi/cparser.py
+++ b/lib_pypy/cffi/cparser.py
@@ -29,7 +29,8 @@
_r_stdcall1 = re.compile(r"\b(__stdcall|WINAPI)\b")
_r_stdcall2 = re.compile(r"[(]\s*(__stdcall|WINAPI)\b")
_r_cdecl = re.compile(r"\b__cdecl\b")
-_r_extern_python = re.compile(r'\bextern\s*"Python"\s*.')
+_r_extern_python = re.compile(r'\bextern\s*"'
+ r'(Python|Python\s*\+\s*C|C\s*\+\s*Python)"\s*.')
_r_star_const_space = re.compile( # matches "* const "
r"[*]\s*((const|volatile|restrict)\b\s*)+")
@@ -88,6 +89,12 @@
# void __cffi_extern_python_start;
# int foo(int);
# void __cffi_extern_python_stop;
+ #
+ # input: `extern "Python+C" int foo(int);`
+ # output:
+ # void __cffi_extern_python_plus_c_start;
+ # int foo(int);
+ # void __cffi_extern_python_stop;
parts = []
while True:
match = _r_extern_python.search(csource)
@@ -98,7 +105,10 @@
#print ''.join(parts)+csource
#print '=>'
parts.append(csource[:match.start()])
- parts.append('void __cffi_extern_python_start; ')
+ if 'C' in match.group(1):
+ parts.append('void __cffi_extern_python_plus_c_start; ')
+ else:
+ parts.append('void __cffi_extern_python_start; ')
if csource[endpos] == '{':
# grouping variant
closing = csource.find('}', endpos)
@@ -302,7 +312,7 @@
break
#
try:
- self._inside_extern_python = False
+ self._inside_extern_python = '__cffi_extern_python_stop'
for decl in iterator:
if isinstance(decl, pycparser.c_ast.Decl):
self._parse_decl(decl)
@@ -376,8 +386,10 @@
tp = self._get_type_pointer(tp, quals)
if self._options.get('dllexport'):
tag = 'dllexport_python '
- elif self._inside_extern_python:
+ elif self._inside_extern_python == '__cffi_extern_python_start':
tag = 'extern_python '
+ elif self._inside_extern_python == '__cffi_extern_python_plus_c_start':
+ tag = 'extern_python_plus_c '
else:
tag = 'function '
self._declare(tag + decl.name, tp)
@@ -421,11 +433,9 @@
# hack: `extern "Python"` in the C source is replaced
# with "void __cffi_extern_python_start;" and
# "void __cffi_extern_python_stop;"
- self._inside_extern_python = not self._inside_extern_python
- assert self._inside_extern_python == (
- decl.name == '__cffi_extern_python_start')
+ self._inside_extern_python = decl.name
else:
- if self._inside_extern_python:
+ if self._inside_extern_python !='__cffi_extern_python_stop':
raise api.CDefError(
"cannot declare constants or "
"variables with 'extern \"Python\"'")
diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py
--- a/lib_pypy/cffi/recompiler.py
+++ b/lib_pypy/cffi/recompiler.py
@@ -1145,11 +1145,11 @@
def _generate_cpy_extern_python_collecttype(self, tp, name):
assert isinstance(tp, model.FunctionPtrType)
self._do_collect_type(tp)
+ _generate_cpy_dllexport_python_collecttype = \
+ _generate_cpy_extern_python_plus_c_collecttype = \
+ _generate_cpy_extern_python_collecttype
- def _generate_cpy_dllexport_python_collecttype(self, tp, name):
- self._generate_cpy_extern_python_collecttype(tp, name)
-
- def _generate_cpy_extern_python_decl(self, tp, name, dllexport=False):
+ def _extern_python_decl(self, tp, name, tag_and_space):
prnt = self._prnt
if isinstance(tp.result, model.VoidType):
size_of_result = '0'
@@ -1184,11 +1184,7 @@
size_of_a = 'sizeof(%s) > %d ? sizeof(%s) : %d' % (
tp.result.get_c_name(''), size_of_a,
tp.result.get_c_name(''), size_of_a)
- if dllexport:
- tag = 'CFFI_DLLEXPORT'
- else:
- tag = 'static'
- prnt('%s %s' % (tag, tp.result.get_c_name(name_and_arguments)))
+ prnt('%s%s' % (tag_and_space, tp.result.get_c_name(name_and_arguments)))
prnt('{')
prnt(' char a[%s];' % size_of_a)
prnt(' char *p = a;')
@@ -1206,8 +1202,14 @@
prnt()
self._num_externpy += 1
+ def _generate_cpy_extern_python_decl(self, tp, name):
+ self._extern_python_decl(tp, name, 'static ')
+
def _generate_cpy_dllexport_python_decl(self, tp, name):
- self._generate_cpy_extern_python_decl(tp, name, dllexport=True)
+ self._extern_python_decl(tp, name, 'CFFI_DLLEXPORT ')
+
+ def _generate_cpy_extern_python_plus_c_decl(self, tp, name):
+ self._extern_python_decl(tp, name, '')
def _generate_cpy_extern_python_ctx(self, tp, name):
if self.target_is_python:
@@ -1220,8 +1222,9 @@
self._lsts["global"].append(
GlobalExpr(name, '&_cffi_externpy__%s' % name, type_op, name))
- def _generate_cpy_dllexport_python_ctx(self, tp, name):
- self._generate_cpy_extern_python_ctx(tp, name)
+ _generate_cpy_dllexport_python_ctx = \
+ _generate_cpy_extern_python_plus_c_ctx = \
+ _generate_cpy_extern_python_ctx
def _string_literal(self, s):
def _char_repr(c):
@@ -1231,7 +1234,7 @@
if c == '\n': return '\\n'
return '\\%03o' % ord(c)
lines = []
- for line in s.splitlines(True):
+ for line in s.splitlines(True) or ['']:
lines.append('"%s"' % ''.join([_char_repr(c) for c in line]))
return ' \\\n'.join(lines)
@@ -1319,7 +1322,9 @@
s = s.encode('ascii')
super(NativeIO, self).write(s)
-def _make_c_or_py_source(ffi, module_name, preamble, target_file):
+def _make_c_or_py_source(ffi, module_name, preamble, target_file, verbose):
+ if verbose:
+ print("generating %s" % (target_file,))
recompiler = Recompiler(ffi, module_name,
target_is_python=(preamble is None))
recompiler.collect_type_table()
@@ -1331,6 +1336,8 @@
with open(target_file, 'r') as f1:
if f1.read(len(output) + 1) != output:
raise IOError
+ if verbose:
+ print("(already up-to-date)")
return False # already up-to-date
except IOError:
tmp_file = '%s.~%d' % (target_file, os.getpid())
@@ -1343,12 +1350,14 @@
os.rename(tmp_file, target_file)
return True
-def make_c_source(ffi, module_name, preamble, target_c_file):
+def make_c_source(ffi, module_name, preamble, target_c_file, verbose=False):
assert preamble is not None
- return _make_c_or_py_source(ffi, module_name, preamble, target_c_file)
+ return _make_c_or_py_source(ffi, module_name, preamble, target_c_file,
+ verbose)
-def make_py_source(ffi, module_name, target_py_file):
- return _make_c_or_py_source(ffi, module_name, None, target_py_file)
+def make_py_source(ffi, module_name, target_py_file, verbose=False):
+ return _make_c_or_py_source(ffi, module_name, None, target_py_file,
+ verbose)
def _modname_to_file(outputdir, modname, extension):
parts = modname.split('.')
@@ -1438,7 +1447,8 @@
target = '*'
#
ext = ffiplatform.get_extension(ext_c_file, module_name, **kwds)
- updated = make_c_source(ffi, module_name, preamble, c_file)
+ updated = make_c_source(ffi, module_name, preamble, c_file,
+ verbose=compiler_verbose)
if call_c_compiler:
patchlist = []
cwd = os.getcwd()
@@ -1458,7 +1468,8 @@
else:
if c_file is None:
c_file, _ = _modname_to_file(tmpdir, module_name, '.py')
- updated = make_py_source(ffi, module_name, c_file)
+ updated = make_py_source(ffi, module_name, c_file,
+ verbose=compiler_verbose)
if call_c_compiler:
return c_file
else:
@@ -1484,4 +1495,7 @@
def typeof_disabled(*args, **kwds):
raise NotImplementedError
ffi._typeof = typeof_disabled
+ for name in dir(ffi):
+ if not name.startswith('_') and not hasattr(module.ffi, name):
+ setattr(ffi, name, NotImplemented)
return module.lib
diff --git a/lib_pypy/ctypes_config_cache/__init__.py b/lib_pypy/ctypes_config_cache/__init__.py
deleted file mode 100644
diff --git a/lib_pypy/ctypes_config_cache/dumpcache.py b/lib_pypy/ctypes_config_cache/dumpcache.py
deleted file mode 100644
--- a/lib_pypy/ctypes_config_cache/dumpcache.py
+++ /dev/null
@@ -1,21 +0,0 @@
-import sys, os
-from ctypes_configure import dumpcache
-
-def dumpcache2(basename, config):
- size = 32 if sys.maxint <= 2**32 else 64
- filename = '_%s_%s_.py' % (basename, size)
- dumpcache.dumpcache(__file__, filename, config)
- #
- filename = os.path.join(os.path.dirname(__file__),
- '_%s_cache.py' % (basename,))
- g = open(filename, 'w')
- print >> g, '''\
-import sys
-_size = 32 if sys.maxint <= 2**32 else 64
-# XXX relative import, should be removed together with
-# XXX the relative imports done e.g. by lib_pypy/pypy_test/test_hashlib
-_mod = __import__("_%s_%%s_" %% (_size,),
- globals(), locals(), ["*"])
-globals().update(_mod.__dict__)\
-''' % (basename,)
- g.close()
diff --git a/lib_pypy/ctypes_config_cache/locale.ctc.py b/lib_pypy/ctypes_config_cache/locale.ctc.py
deleted file mode 100644
--- a/lib_pypy/ctypes_config_cache/locale.ctc.py
+++ /dev/null
@@ -1,73 +0,0 @@
-"""
-'ctypes_configure' source for _locale.py.
-Run this to rebuild _locale_cache.py.
-"""
-
-from ctypes_configure.configure import (configure, ExternalCompilationInfo,
- ConstantInteger, DefinedConstantInteger, SimpleType, check_eci)
-import dumpcache
-
-# ____________________________________________________________
-
-_CONSTANTS = [
- 'LC_CTYPE',
- 'LC_TIME',
- 'LC_COLLATE',
- 'LC_MONETARY',
- 'LC_MESSAGES',
- 'LC_NUMERIC',
- 'LC_ALL',
- 'CHAR_MAX',
-]
-
-class LocaleConfigure:
- _compilation_info_ = ExternalCompilationInfo(includes=['limits.h',
- 'locale.h'])
-for key in _CONSTANTS:
- setattr(LocaleConfigure, key, DefinedConstantInteger(key))
-
-config = configure(LocaleConfigure, noerr=True)
-for key, value in config.items():
- if value is None:
- del config[key]
- _CONSTANTS.remove(key)
-
-# ____________________________________________________________
-
-eci = ExternalCompilationInfo(includes=['locale.h', 'langinfo.h'])
-HAS_LANGINFO = check_eci(eci)
-
-if HAS_LANGINFO:
- # list of all possible names
- langinfo_names = [
- "RADIXCHAR", "THOUSEP", "CRNCYSTR",
- "D_T_FMT", "D_FMT", "T_FMT", "AM_STR", "PM_STR",
- "CODESET", "T_FMT_AMPM", "ERA", "ERA_D_FMT", "ERA_D_T_FMT",
- "ERA_T_FMT", "ALT_DIGITS", "YESEXPR", "NOEXPR", "_DATE_FMT",
- ]
- for i in range(1, 8):
- langinfo_names.append("DAY_%d" % i)
- langinfo_names.append("ABDAY_%d" % i)
- for i in range(1, 13):
- langinfo_names.append("MON_%d" % i)
- langinfo_names.append("ABMON_%d" % i)
-
- class LanginfoConfigure:
- _compilation_info_ = eci
- nl_item = SimpleType('nl_item')
- for key in langinfo_names:
- setattr(LanginfoConfigure, key, DefinedConstantInteger(key))
-
- langinfo_config = configure(LanginfoConfigure)
- for key, value in langinfo_config.items():
- if value is None:
- del langinfo_config[key]
- langinfo_names.remove(key)
- config.update(langinfo_config)
- _CONSTANTS += langinfo_names
-
-# ____________________________________________________________
-
-config['ALL_CONSTANTS'] = tuple(_CONSTANTS)
-config['HAS_LANGINFO'] = HAS_LANGINFO
-dumpcache.dumpcache2('locale', config)
diff --git a/lib_pypy/ctypes_config_cache/rebuild.py b/lib_pypy/ctypes_config_cache/rebuild.py
deleted file mode 100755
--- a/lib_pypy/ctypes_config_cache/rebuild.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#! /usr/bin/env python
-# Run this script to rebuild all caches from the *.ctc.py files.
-
-import os, sys
-
-sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), '..', '..')))
-
-import py
-
-_dirpath = os.path.dirname(__file__) or os.curdir
-
-from rpython.tool.ansi_print import AnsiLogger
-log = AnsiLogger("ctypes_config_cache")
-
-
-def rebuild_one(name):
- filename = os.path.join(_dirpath, name)
- d = {'__file__': filename}
- path = sys.path[:]
- try:
- sys.path.insert(0, _dirpath)
- execfile(filename, d)
- finally:
- sys.path[:] = path
-
-def try_rebuild():
- size = 32 if sys.maxint <= 2**32 else 64
- # remove the files '_*_size_.py'
- left = {}
- for p in os.listdir(_dirpath):
- if p.startswith('_') and (p.endswith('_%s_.py' % size) or
- p.endswith('_%s_.pyc' % size)):
- os.unlink(os.path.join(_dirpath, p))
- elif p.startswith('_') and (p.endswith('_.py') or
- p.endswith('_.pyc')):
- for i in range(2, len(p)-4):
- left[p[:i]] = True
- # remove the files '_*_cache.py' if there is no '_*_*_.py' left around
- for p in os.listdir(_dirpath):
- if p.startswith('_') and (p.endswith('_cache.py') or
- p.endswith('_cache.pyc')):
- if p[:-9] not in left:
- os.unlink(os.path.join(_dirpath, p))
- #
- for p in os.listdir(_dirpath):
- if p.endswith('.ctc.py'):
- try:
- rebuild_one(p)
- except Exception, e:
- log.ERROR("Running %s:\n %s: %s" % (
- os.path.join(_dirpath, p),
- e.__class__.__name__, e))
-
-
-if __name__ == '__main__':
- try_rebuild()
diff --git a/lib_pypy/ctypes_config_cache/resource.ctc.py b/lib_pypy/ctypes_config_cache/resource.ctc.py
deleted file mode 100644
--- a/lib_pypy/ctypes_config_cache/resource.ctc.py
+++ /dev/null
@@ -1,62 +0,0 @@
-"""
-'ctypes_configure' source for resource.py.
-Run this to rebuild _resource_cache.py.
-"""
-
-
-from ctypes import sizeof
-import dumpcache
-from ctypes_configure.configure import (configure,
- ExternalCompilationInfo, ConstantInteger, DefinedConstantInteger,
- SimpleType)
-
-
-_CONSTANTS = (
- 'RLIM_INFINITY',
- 'RLIM_NLIMITS',
-)
-_OPTIONAL_CONSTANTS = (
- 'RLIMIT_CPU',
- 'RLIMIT_FSIZE',
- 'RLIMIT_DATA',
- 'RLIMIT_STACK',
- 'RLIMIT_CORE',
- 'RLIMIT_RSS',
- 'RLIMIT_NPROC',
- 'RLIMIT_NOFILE',
- 'RLIMIT_OFILE',
- 'RLIMIT_MEMLOCK',
- 'RLIMIT_AS',
- 'RLIMIT_LOCKS',
- 'RLIMIT_SIGPENDING',
- 'RLIMIT_MSGQUEUE',
- 'RLIMIT_NICE',
- 'RLIMIT_RTPRIO',
- 'RLIMIT_VMEM',
-
- 'RUSAGE_BOTH',
- 'RUSAGE_SELF',
- 'RUSAGE_CHILDREN',
-)
-
-# Setup our configure
-class ResourceConfigure:
- _compilation_info_ = ExternalCompilationInfo(includes=['sys/resource.h'])
- rlim_t = SimpleType('rlim_t')
-for key in _CONSTANTS:
- setattr(ResourceConfigure, key, ConstantInteger(key))
-for key in _OPTIONAL_CONSTANTS:
- setattr(ResourceConfigure, key, DefinedConstantInteger(key))
-
-# Configure constants and types
-config = configure(ResourceConfigure)
-config['rlim_t_max'] = (1<<(sizeof(config['rlim_t']) * 8)) - 1
-optional_constants = []
-for key in _OPTIONAL_CONSTANTS:
- if config[key] is not None:
- optional_constants.append(key)
- else:
- del config[key]
-
-config['ALL_CONSTANTS'] = _CONSTANTS + tuple(optional_constants)
-dumpcache.dumpcache2('resource', config)
diff --git a/lib_pypy/pwd.py b/lib_pypy/pwd.py
--- a/lib_pypy/pwd.py
+++ b/lib_pypy/pwd.py
@@ -1,4 +1,4 @@
-# ctypes implementation: Victor Stinner, 2008-05-08
+# indirectly based on ctypes implementation: Victor Stinner, 2008-05-08
"""
This module provides access to the Unix password database.
It is available on all Unix versions.
diff --git a/lib_pypy/resource.py b/lib_pypy/resource.py
--- a/lib_pypy/resource.py
+++ b/lib_pypy/resource.py
@@ -1,15 +1,8 @@
-import sys
-if sys.platform == 'win32':
- raise ImportError('resource module not available for win32')
+"""http://docs.python.org/library/resource"""
-# load the platform-specific cache made by running resource.ctc.py
-from ctypes_config_cache._resource_cache import *
-
-from ctypes_support import standard_c_lib as libc
-from ctypes_support import get_errno
-from ctypes import Structure, c_int, c_long, byref, POINTER
+from _resource_cffi import ffi, lib
from errno import EINVAL, EPERM
-import _structseq
+import _structseq, os
try: from __pypy__ import builtinify
except ImportError: builtinify = lambda f: f
@@ -18,106 +11,37 @@
class error(Exception):
pass
+class struct_rusage:
+ """struct_rusage: Result from getrusage.
-# Read required libc functions
-_getrusage = libc.getrusage
-_getrlimit = libc.getrlimit
-_setrlimit = libc.setrlimit
-try:
- _getpagesize = libc.getpagesize
- _getpagesize.argtypes = ()
- _getpagesize.restype = c_int
-except AttributeError:
- from os import sysconf
- _getpagesize = None
+This object may be accessed either as a tuple of
+ (utime,stime,maxrss,ixrss,idrss,isrss,minflt,majflt,
+ nswap,inblock,oublock,msgsnd,msgrcv,nsignals,nvcsw,nivcsw)
+or via the attributes ru_utime, ru_stime, ru_maxrss, and so on."""
-
-class timeval(Structure):
- _fields_ = (
- ("tv_sec", c_long),
- ("tv_usec", c_long),
- )
- def __str__(self):
- return "(%s, %s)" % (self.tv_sec, self.tv_usec)
-
- def __float__(self):
- return self.tv_sec + self.tv_usec/1000000.0
-
-class _struct_rusage(Structure):
- _fields_ = (
- ("ru_utime", timeval),
- ("ru_stime", timeval),
- ("ru_maxrss", c_long),
- ("ru_ixrss", c_long),
- ("ru_idrss", c_long),
- ("ru_isrss", c_long),
- ("ru_minflt", c_long),
- ("ru_majflt", c_long),
- ("ru_nswap", c_long),
- ("ru_inblock", c_long),
- ("ru_oublock", c_long),
- ("ru_msgsnd", c_long),
- ("ru_msgrcv", c_long),
- ("ru_nsignals", c_long),
- ("ru_nvcsw", c_long),
- ("ru_nivcsw", c_long),
- )
-
-_getrusage.argtypes = (c_int, POINTER(_struct_rusage))
-_getrusage.restype = c_int
-
-
-class struct_rusage:
__metaclass__ = _structseq.structseqtype
- ru_utime = _structseq.structseqfield(0)
- ru_stime = _structseq.structseqfield(1)
- ru_maxrss = _structseq.structseqfield(2)
- ru_ixrss = _structseq.structseqfield(3)
- ru_idrss = _structseq.structseqfield(4)
- ru_isrss = _structseq.structseqfield(5)
- ru_minflt = _structseq.structseqfield(6)
- ru_majflt = _structseq.structseqfield(7)
- ru_nswap = _structseq.structseqfield(8)
- ru_inblock = _structseq.structseqfield(9)
- ru_oublock = _structseq.structseqfield(10)
- ru_msgsnd = _structseq.structseqfield(11)
- ru_msgrcv = _structseq.structseqfield(12)
- ru_nsignals = _structseq.structseqfield(13)
- ru_nvcsw = _structseq.structseqfield(14)
- ru_nivcsw = _structseq.structseqfield(15)
+ ru_utime = _structseq.structseqfield(0, "user time used")
+ ru_stime = _structseq.structseqfield(1, "system time used")
+ ru_maxrss = _structseq.structseqfield(2, "max. resident set size")
+ ru_ixrss = _structseq.structseqfield(3, "shared memory size")
+ ru_idrss = _structseq.structseqfield(4, "unshared data size")
+ ru_isrss = _structseq.structseqfield(5, "unshared stack size")
+ ru_minflt = _structseq.structseqfield(6, "page faults not requiring I/O")
+ ru_majflt = _structseq.structseqfield(7, "page faults requiring I/O")
+ ru_nswap = _structseq.structseqfield(8, "number of swap outs")
+ ru_inblock = _structseq.structseqfield(9, "block input operations")
+ ru_oublock = _structseq.structseqfield(10, "block output operations")
+ ru_msgsnd = _structseq.structseqfield(11, "IPC messages sent")
+ ru_msgrcv = _structseq.structseqfield(12, "IPC messages received")
+ ru_nsignals = _structseq.structseqfield(13,"signals received")
+ ru_nvcsw = _structseq.structseqfield(14, "voluntary context switches")
+ ru_nivcsw = _structseq.structseqfield(15, "involuntary context switches")
- at builtinify
-def rlimit_check_bounds(rlim_cur, rlim_max):
- if rlim_cur > rlim_t_max:
- raise ValueError("%d does not fit into rlim_t" % rlim_cur)
- if rlim_max > rlim_t_max:
- raise ValueError("%d does not fit into rlim_t" % rlim_max)
-
-class rlimit(Structure):
- _fields_ = (
- ("rlim_cur", rlim_t),
- ("rlim_max", rlim_t),
- )
-
-_getrlimit.argtypes = (c_int, POINTER(rlimit))
-_getrlimit.restype = c_int
-_setrlimit.argtypes = (c_int, POINTER(rlimit))
-_setrlimit.restype = c_int
-
-
- at builtinify
-def getrusage(who):
- ru = _struct_rusage()
- ret = _getrusage(who, byref(ru))
- if ret == -1:
- errno = get_errno()
- if errno == EINVAL:
- raise ValueError("invalid who parameter")
- raise error(errno)
+def _make_struct_rusage(ru):
return struct_rusage((
- float(ru.ru_utime),
- float(ru.ru_stime),
+ lib.my_utime(ru),
+ lib.my_stime(ru),
ru.ru_maxrss,
ru.ru_ixrss,
ru.ru_idrss,
@@ -135,48 +59,59 @@
))
@builtinify
+def getrusage(who):
+ ru = ffi.new("struct rusage *")
+ if lib.getrusage(who, ru) == -1:
+ if ffi.errno == EINVAL:
+ raise ValueError("invalid who parameter")
+ raise error(ffi.errno)
+ return _make_struct_rusage(ru)
+
+ at builtinify
def getrlimit(resource):
- if not(0 <= resource < RLIM_NLIMITS):
+ if not (0 <= resource < lib.RLIM_NLIMITS):
return ValueError("invalid resource specified")
- rlim = rlimit()
- ret = _getrlimit(resource, byref(rlim))
- if ret == -1:
- errno = get_errno()
- raise error(errno)
- return (rlim.rlim_cur, rlim.rlim_max)
+ result = ffi.new("long long[2]")
+ if lib.my_getrlimit(resource, result) == -1:
+ raise error(ffi.errno)
+ return (result[0], result[1])
@builtinify
-def setrlimit(resource, rlim):
- if not(0 <= resource < RLIM_NLIMITS):
+def setrlimit(resource, limits):
+ if not (0 <= resource < lib.RLIM_NLIMITS):
return ValueError("invalid resource specified")
- rlimit_check_bounds(*rlim)
- rlim = rlimit(rlim[0], rlim[1])
- ret = _setrlimit(resource, byref(rlim))
- if ret == -1:
- errno = get_errno()
- if errno == EINVAL:
- return ValueError("current limit exceeds maximum limit")
- elif errno == EPERM:
- return ValueError("not allowed to raise maximum limit")
+ limits = tuple(limits)
+ if len(limits) != 2:
+ raise ValueError("expected a tuple of 2 integers")
+
+ if lib.my_setrlimit(resource, limits[0], limits[1]) == -1:
+ if ffi.errno == EINVAL:
+ raise ValueError("current limit exceeds maximum limit")
+ elif ffi.errno == EPERM:
+ raise ValueError("not allowed to raise maximum limit")
else:
- raise error(errno)
+ raise error(ffi.errno)
+
@builtinify
def getpagesize():
- if _getpagesize:
- return _getpagesize()
- else:
- try:
- return sysconf("SC_PAGE_SIZE")
- except ValueError:
- # Irix 5.3 has _SC_PAGESIZE, but not _SC_PAGE_SIZE
- return sysconf("SC_PAGESIZE")
+ return os.sysconf("SC_PAGESIZE")
-__all__ = ALL_CONSTANTS + (
- 'error', 'timeval', 'struct_rusage', 'rlimit',
- 'getrusage', 'getrlimit', 'setrlimit', 'getpagesize',
+
+def _setup():
+ all_constants = []
+ p = lib.my_rlimit_consts
+ while p.name:
+ name = ffi.string(p.name)
+ globals()[name] = int(p.value)
+ all_constants.append(name)
+ p += 1
+ return all_constants
+
+__all__ = tuple(_setup()) + (
+ 'error', 'getpagesize', 'struct_rusage',
+ 'getrusage', 'getrlimit', 'setrlimit',
)
-
-del ALL_CONSTANTS
+del _setup
diff --git a/pypy/doc/__pypy__-module.rst b/pypy/doc/__pypy__-module.rst
--- a/pypy/doc/__pypy__-module.rst
+++ b/pypy/doc/__pypy__-module.rst
@@ -18,6 +18,7 @@
- ``bytebuffer(length)``: return a new read-write buffer of the given length.
It works like a simplified array of characters (actually, depending on the
configuration the ``array`` module internally uses this).
+ - ``attach_gdb()``: start a GDB at the interpreter-level (or a PDB before translation).
Transparent Proxy Functionality
@@ -37,4 +38,3 @@
--------------------------------------------------------
- ``isfake(obj)``: returns True if ``obj`` is faked.
- - ``interp_pdb()``: start a pdb at interpreter-level.
diff --git a/pypy/doc/contributor.rst b/pypy/doc/contributor.rst
--- a/pypy/doc/contributor.rst
+++ b/pypy/doc/contributor.rst
@@ -81,13 +81,13 @@
Simon Burton
Martin Matusiak
Konstantin Lopuhin
+ Stefano Rivera
Wenzhu Man
John Witulski
Laurence Tratt
Ivan Sichmann Freitas
Greg Price
Dario Bertini
- Stefano Rivera
Mark Pearse
Simon Cross
Andreas Stührk
@@ -95,9 +95,10 @@
Jean-Philippe St. Pierre
Guido van Rossum
Pavel Vinogradov
+ Spenser Bauman
Jeremy Thurgood
Paweł Piotr Przeradowski
- Spenser Bauman
+ Tobias Pape
Paul deGrandis
Ilya Osadchiy
marky1991
@@ -109,7 +110,7 @@
Georg Brandl
Bert Freudenberg
Stian Andreassen
- Tobias Pape
+ Mark Young
Wanja Saatkamp
Gerald Klix
Mike Blume
@@ -140,9 +141,9 @@
Yichao Yu
Rocco Moretti
Gintautas Miliauskas
+ Devin Jeanpierre
Michael Twomey
Lucian Branescu Mihaila
- Devin Jeanpierre
Gabriel Lavoie
Olivier Dormond
Jared Grubb
@@ -153,6 +154,7 @@
Victor Stinner
Andrews Medina
anatoly techtonik
+ Sergey Matyunin
Stuart Williams
Jasper Schulz
Christian Hudon
@@ -187,7 +189,6 @@
Arjun Naik
Valentina Mukhamedzhanova
Stefano Parmesan
- Mark Young
Alexis Daboville
Jens-Uwe Mager
Carl Meyer
@@ -195,7 +196,9 @@
Pieter Zieschang
Gabriel
Lukas Vacek
+ Kunal Grover
Andrew Dalke
+ Florin Papa
Sylvain Thenault
Jakub Stasiak
Nathan Taylor
@@ -210,7 +213,6 @@
Kristjan Valur Jonsson
David Lievens
Neil Blakey-Milner
- Sergey Matyunin
Lutz Paelike
Lucio Torre
Lars Wassermann
@@ -222,9 +224,11 @@
Artur Lisiecki
Sergey Kishchenko
Ignas Mikalajunas
+ Alecsandru Patrascu
Christoph Gerum
Martin Blais
Lene Wagner
+ Catalin Gabriel Manciu
Tomo Cocoa
Kim Jin Su
Toni Mattis
@@ -261,6 +265,7 @@
Akira Li
Gustavo Niemeyer
Stephan Busemann
+ florinpapa
Rafał Gałczyński
Matt Bogosian
Christian Muirhead
@@ -275,6 +280,7 @@
Boglarka Vezer
Chris Pressey
Buck Golemon
+ Diana Popa
Konrad Delong
Dinu Gherman
Chris Lambacher
diff --git a/pypy/doc/index-of-release-notes.rst b/pypy/doc/index-of-release-notes.rst
--- a/pypy/doc/index-of-release-notes.rst
+++ b/pypy/doc/index-of-release-notes.rst
@@ -6,6 +6,7 @@
.. toctree::
+ release-5.1.0.rst
release-5.0.1.rst
release-5.0.0.rst
release-4.0.1.rst
diff --git a/pypy/doc/index-of-whatsnew.rst b/pypy/doc/index-of-whatsnew.rst
--- a/pypy/doc/index-of-whatsnew.rst
+++ b/pypy/doc/index-of-whatsnew.rst
@@ -7,6 +7,7 @@
.. toctree::
whatsnew-head.rst
+ whatsnew-5.1.0.rst
whatsnew-5.0.0.rst
whatsnew-4.0.1.rst
whatsnew-4.0.0.rst
diff --git a/pypy/doc/release-5.1.0.rst b/pypy/doc/release-5.1.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-5.1.0.rst
@@ -0,0 +1,136 @@
+========
+PyPy 5.1
+========
+
+We have released PyPy 5.1, about a month after PyPy 5.0.
+We encourage all users of PyPy to update to this version. Apart from the usual
+bug fixes, there is an ongoing effort to improve the warmup time and memory
+usage of JIT-related metadata, and we now fully support the IBM s390x
+architecture.
+
+You can download the PyPy 5.1 release here:
+
+ http://pypy.org/download.html
+
+We would like to thank our donors for the continued support of the PyPy
+project.
+
+We would also like to thank our contributors and
+encourage new people to join the project. PyPy has many
+layers and we need help with all of them: `PyPy`_ and `RPython`_ documentation
+improvements, tweaking popular `modules`_ to run on pypy, or general `help`_
+with making RPython's JIT even better.
+
+.. _`PyPy`: http://doc.pypy.org
+.. _`RPython`: https://rpython.readthedocs.org
+.. _`modules`: http://doc.pypy.org/en/latest/project-ideas.html#make-more-python-modules-pypy-friendly
+.. _`help`: http://doc.pypy.org/en/latest/project-ideas.html
+.. _`numpy`: https://bitbucket.org/pypy/numpy
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7. It's fast (`PyPy and CPython 2.7.x`_ performance comparison)
+due to its integrated tracing JIT compiler.
+
+We also welcome developers of other
+`dynamic languages`_ to see what RPython can do for them.
+
+This release supports:
+
+ * **x86** machines on most common operating systems
+ (Linux 32/64, Mac OS X 64, Windows 32, OpenBSD, FreeBSD),
+
+ * newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux,
+
+ * big- and little-endian variants of **PPC64** running Linux,
+
+ * **s960x** running Linux
+
+.. _`PyPy and CPython 2.7.x`: http://speed.pypy.org
+.. _`dynamic languages`: http://pypyjs.org
+
+Other Highlights (since 5.0 released in March 2015)
+=========================================================
+
+* New features:
+
+ * A new jit backend for the IBM s390x, which was a large effort over the past
+ few months.
+
+ * Add better support for PyUnicodeObject in the C-API compatibility layer
+
+ * Support GNU/kFreeBSD Debian ports in vmprof
+
+ * Add __pypy__._promote
+
+ * Make attrgetter a single type for CPython compatibility
+
+* Bug Fixes
+
+ * Catch exceptions raised in an exit function
+
+ * Fix a corner case in the JIT
+
+ * Fix edge cases in the cpyext refcounting-compatible semantics
+
+ * Try harder to not emit NEON instructions on ARM processors without NEON
+ support
+
+ * Improve the rpython posix module system interaction function calls
+
+ * Detect a missing class function implementation instead of calling a random
+ function
+
+ * Check that PyTupleObjects do not contain any NULLs at the
+ point of conversion to W_TupleObjects
+
+ * In ctypes, fix _anonymous_ fields of instances
+
+ * Fix JIT issue with unpack() on a Trace which contains half-written operations
+
+ * Fix sandbox startup (a regression in 5.0)
+
+ * Issues reported with our previous release were resolved_ after reports from users on
+ our issue tracker at https://bitbucket.org/pypy/pypy/issues or on IRC at
+ #pypy
+
+* Numpy:
+
+ * Implemented numpy.where for a single argument
+
+ * Indexing by a numpy scalar now returns a scalar
+
+ * Fix transpose(arg) when arg is a sequence
+
+ * Refactor include file handling, now all numpy ndarray, ufunc, and umath
+ functions exported from libpypy.so are declared in pypy_numpy.h, which is
+ included only when building our fork of numpy
+
+* Performance improvements:
+
+ * Improve str.endswith([tuple]) and str.startswith([tuple]) to allow JITting
+
+ * Merge another round of improvements to the warmup performance
+
+ * Cleanup history rewriting in pyjitpl
+
+ * Remove the forced minor collection that occurs when rewriting the
+ assembler at the start of the JIT backend
+
+* Internal refactorings:
+
+ * Use a simpler logger to speed up translation
+
+ * Drop vestiges of Python 2.5 support in testing
+
+.. _resolved: http://doc.pypy.org/en/latest/whatsnew-5.0.0.html
+.. _`blog post`: http://morepypy.blogspot.com/2016/02/c-api-support-update.html
+
+Please update, and continue to help us make PyPy better.
+
+Cheers
+
+The PyPy Team
+
diff --git a/pypy/doc/whatsnew-5.1.0.rst b/pypy/doc/whatsnew-5.1.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/whatsnew-5.1.0.rst
@@ -0,0 +1,62 @@
+=========================
+What's new in PyPy 5.1
+=========================
+
+.. this is a revision shortly after release-5.0
+.. startrev: b238b48f9138
+
+.. branch: s390x-backend
+
+The jit compiler backend implementation for the s390x architecutre.
+The backend manages 64-bit values in the literal pool of the assembly instead of loading them as immediates.
+It includes a simplification for the operation 'zero_array'. Start and length parameters are bytes instead of size.
+
+.. branch: remove-py-log
+
+Replace py.log with something simpler, which should speed up logging
+
+.. branch: where_1_arg
+
+Implemented numpy.where for 1 argument (thanks sergem)
+
+.. branch: fix_indexing_by_numpy_int
+
+Implement yet another strange numpy indexing compatibility; indexing by a scalar
+returns a scalar
+
+.. branch: fix_transpose_for_list_v3
+
+Allow arguments to transpose to be sequences
+
+.. branch: jit-leaner-frontend
+
+Improve the tracing speed in the frontend as well as heapcache by using a more compact representation
+of traces
+
+.. branch: win32-lib-name
+
+.. branch: remove-frame-forcing-in-executioncontext
+
+.. branch: rposix-for-3
+
+Wrap more POSIX functions in `rpython.rlib.rposix`.
+
+.. branch: cleanup-history-rewriting
+
+A local clean-up in the JIT front-end.
+
+.. branch: jit-constptr-2
+
+Remove the forced minor collection that occurs when rewriting the
+assembler at the start of the JIT backend. This is done by emitting
+the ConstPtrs in a separate table, and loading from the table. It
+gives improved warm-up time and memory usage, and also removes
+annoying special-purpose code for pinned pointers.
+
+.. branch: fix-jitlog
+
+.. branch: cleanup-includes
+
+Remove old uneeded numpy headers, what is left is only for testing. Also
+generate pypy_numpy.h which exposes functions to directly use micronumpy
+ndarray and ufuncs
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
@@ -1,34 +1,16 @@
=========================
-What's new in PyPy 5.0.+
+What's new in PyPy 5.1+
=========================
-.. this is a revision shortly after release-5.0
-.. startrev: b238b48f9138
+.. this is a revision shortly after release-5.1
+.. startrev: 2180e1eaf6f6
-.. branch: s390x-backend
+.. branch: rposix-for-3
-The jit compiler backend implementation for the s390x architecutre.
-The backend manages 64-bit values in the literal pool of the assembly instead of loading them as immediates.
-It includes a simplification for the operation 'zero_array'. Start and length parameters are bytes instead of size.
+Reuse rposix definition of TIMESPEC in rposix_stat, add wrapper for fstatat().
+This updates the underlying rpython functions with the ones needed for the
+py3k branch
+
+.. branch: numpy_broadcast
-.. branch: remove-py-log
-
-Replace py.log with something simpler, which should speed up logging
-
-.. branch: where_1_arg
-
-Implemented numpy.where for 1 argument (thanks sergem)
-
-.. branch: fix_indexing_by_numpy_int
-
-Implement yet another strange numpy indexing compatibility; indexing by a scalar
-returns a scalar
-
-.. branch: fix_transpose_for_list_v3
-
-Allow arguments to transpose to be sequences
-
-.. branch: jit-leaner-frontend
-
-Improve the tracing speed in the frontend as well as heapcache by using a more compact representation
-of traces
\ No newline at end of file
+Add broadcast to micronumpy
diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -240,8 +240,9 @@
"when --shared is on (it is by default). "
"See issue #1971.")
if sys.platform == 'win32':
- config.translation.libname = '..\\..\\libs\\python27.lib'
- thisdir.join('..', '..', 'libs').ensure(dir=1)
+ libdir = thisdir.join('..', '..', 'libs')
+ libdir.ensure(dir=1)
+ config.translation.libname = str(libdir.join('python27.lib'))
if config.translation.thread:
config.objspace.usemodules.thread = True
@@ -339,10 +340,6 @@
return PyPyJitPolicy(pypy_hooks)
def get_entry_point(self, config):
- from pypy.tool.lib_pypy import import_from_lib_pypy
- rebuild = import_from_lib_pypy('ctypes_config_cache/rebuild')
- rebuild.try_rebuild()
-
space = make_objspace(config)
# manually imports app_main.py
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1029,6 +1029,9 @@
def newlist_int(self, list_i):
return self.newlist([self.wrap(i) for i in list_i])
+ def newlist_float(self, list_f):
+ return self.newlist([self.wrap(f) for f in list_f])
+
def newlist_hint(self, sizehint):
from pypy.objspace.std.listobject import make_empty_list_with_size
return make_empty_list_with_size(self, sizehint)
diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -291,13 +291,7 @@
return tb
def set_traceback(self, traceback):
- """Set the current traceback. It should either be a traceback
- pointing to some already-escaped frame, or a traceback for the
- current frame. To support the latter case we do not mark the
- frame as escaped. The idea is that it will be marked as escaping
- only if the exception really propagates out of this frame, by
- executioncontext.leave() being called with got_exception=True.
- """
+ """Set the current traceback."""
self._application_traceback = traceback
diff --git a/pypy/module/__builtin__/app_functional.py b/pypy/module/__builtin__/app_functional.py
--- a/pypy/module/__builtin__/app_functional.py
+++ b/pypy/module/__builtin__/app_functional.py
@@ -15,9 +15,9 @@
# ____________________________________________________________
-def sorted(lst, cmp=None, key=None, reverse=False):
+def sorted(iterable, cmp=None, key=None, reverse=False):
"sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list"
- sorted_lst = list(lst)
+ sorted_lst = list(iterable)
sorted_lst.sort(cmp, key, reverse)
return sorted_lst
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
@@ -90,6 +90,7 @@
'save_module_content_for_future_reload':
'interp_magic.save_module_content_for_future_reload',
'decode_long' : 'interp_magic.decode_long',
+ '_promote' : 'interp_magic._promote',
}
if sys.platform == 'win32':
interpleveldefs['get_console_cp'] = 'interp_magic.get_console_cp'
diff --git a/pypy/module/__pypy__/interp_magic.py b/pypy/module/__pypy__/interp_magic.py
--- a/pypy/module/__pypy__/interp_magic.py
+++ b/pypy/module/__pypy__/interp_magic.py
@@ -168,3 +168,23 @@
except InvalidEndiannessError:
raise oefmt(space.w_ValueError, "invalid byteorder argument")
return space.newlong_from_rbigint(result)
+
+def _promote(space, w_obj):
+ """ Promote the first argument of the function and return it. Promote is by
+ value for ints, floats, strs, unicodes (but not subclasses thereof) and by
+ reference otherwise. (Unicodes not supported right now.)
+
+ This function is experimental!"""
+ from rpython.rlib import jit
+ if space.is_w(space.type(w_obj), space.w_int):
+ jit.promote(space.int_w(w_obj))
+ elif space.is_w(space.type(w_obj), space.w_float):
+ jit.promote(space.float_w(w_obj))
+ elif space.is_w(space.type(w_obj), space.w_str):
+ jit.promote_string(space.str_w(w_obj))
+ elif space.is_w(space.type(w_obj), space.w_unicode):
+ raise OperationError(space.w_TypeError, space.wrap(
+ "promoting unicode unsupported"))
+ else:
+ jit.promote(w_obj)
+ return w_obj
diff --git a/pypy/module/__pypy__/test/test_magic.py b/pypy/module/__pypy__/test/test_magic.py
--- a/pypy/module/__pypy__/test/test_magic.py
+++ b/pypy/module/__pypy__/test/test_magic.py
@@ -47,3 +47,16 @@
assert decode_long('\x00\x80', 'little', False) == 32768
assert decode_long('\x00\x80', 'little', True) == -32768
raises(ValueError, decode_long, '', 'foo')
+
+ def test_promote(self):
+ from __pypy__ import _promote
+ assert _promote(1) == 1
+ assert _promote(1.1) == 1.1
+ assert _promote("abc") == "abc"
+ raises(TypeError, _promote, u"abc")
+ l = []
+ assert _promote(l) is l
+ class A(object):
+ pass
+ a = A()
+ assert _promote(a) is a
diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -3,7 +3,7 @@
from rpython.rlib import rdynload, clibffi, entrypoint
from rpython.rtyper.lltypesystem import rffi
-VERSION = "1.5.2"
+VERSION = "1.6.0"
FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI
try:
@@ -48,6 +48,7 @@
'from_buffer': 'func.from_buffer',
'string': 'func.string',
+ 'unpack': 'func.unpack',
'buffer': 'cbuffer.buffer',
'memmove': 'func.memmove',
diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -323,14 +323,18 @@
from pypy.module._cffi_backend import ctypearray
ctype = self.ctype
if isinstance(ctype, ctypearray.W_CTypeArray):
- return ctype.ctitem.unpack_list_of_int_items(self)
+ length = self.get_array_length()
+ with self as ptr:
+ return ctype.ctitem.unpack_list_of_int_items(ptr, length)
return None
def unpackiterable_float(self, space):
from pypy.module._cffi_backend import ctypearray
ctype = self.ctype
if isinstance(ctype, ctypearray.W_CTypeArray):
- return ctype.ctitem.unpack_list_of_float_items(self)
+ length = self.get_array_length()
+ with self as ptr:
+ return ctype.ctitem.unpack_list_of_float_items(ptr, length)
return None
@specialize.argtype(1)
@@ -367,6 +371,25 @@
with self as ptr:
return W_CDataGCP(self.space, ptr, self.ctype, self, w_destructor)
+ def unpack(self, length):
+ from pypy.module._cffi_backend.ctypeptr import W_CTypePtrOrArray
+ space = self.space
+ if not self.ctype.is_nonfunc_pointer_or_array:
+ raise oefmt(space.w_TypeError,
+ "expected a pointer or array, got '%s'",
+ self.ctype.name)
+ if length < 0:
+ raise oefmt(space.w_ValueError, "'length' cannot be negative")
+ ctype = self.ctype
+ assert isinstance(ctype, W_CTypePtrOrArray)
+ with self as ptr:
+ if not ptr:
+ raise oefmt(space.w_RuntimeError,
+ "cannot use unpack() on %s",
+ space.str_w(self.repr()))
+ w_result = ctype.ctitem.unpack_ptr(ctype, ptr, length)
+ return w_result
+
class W_CDataMem(W_CData):
"""This is used only by the results of cffi.cast('int', x)
diff --git a/pypy/module/_cffi_backend/ctypearray.py b/pypy/module/_cffi_backend/ctypearray.py
--- a/pypy/module/_cffi_backend/ctypearray.py
+++ b/pypy/module/_cffi_backend/ctypearray.py
@@ -7,11 +7,12 @@
from pypy.interpreter.gateway import interp2app
from pypy.interpreter.typedef import TypeDef
-from rpython.rtyper.lltypesystem import rffi
+from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rlib.rarithmetic import ovfcheck
from pypy.module._cffi_backend import cdataobj
from pypy.module._cffi_backend.ctypeptr import W_CTypePtrOrArray
+from pypy.module._cffi_backend import ctypeprim
class W_CTypeArray(W_CTypePtrOrArray):
diff --git a/pypy/module/_cffi_backend/ctypeobj.py b/pypy/module/_cffi_backend/ctypeobj.py
--- a/pypy/module/_cffi_backend/ctypeobj.py
+++ b/pypy/module/_cffi_backend/ctypeobj.py
@@ -49,10 +49,10 @@
def is_unichar_ptr_or_array(self):
return False
- def unpack_list_of_int_items(self, cdata):
+ def unpack_list_of_int_items(self, ptr, length):
return None
- def unpack_list_of_float_items(self, cdata):
+ def unpack_list_of_float_items(self, ptr, length):
return None
def pack_list_of_items(self, cdata, w_ob):
@@ -127,6 +127,21 @@
raise oefmt(space.w_TypeError,
"string(): unexpected cdata '%s' argument", self.name)
+ def unpack_ptr(self, w_ctypeptr, ptr, length):
+ # generic implementation, when the type of items is not known to
+ # be one for which a fast-case exists
+ space = self.space
+ itemsize = self.size
+ if itemsize < 0:
+ raise oefmt(space.w_ValueError,
+ "'%s' points to items of unknown size",
+ w_ctypeptr.name)
+ result_w = [None] * length
+ for i in range(length):
+ result_w[i] = self.convert_to_object(ptr)
+ ptr = rffi.ptradd(ptr, itemsize)
+ return space.newlist(result_w)
+
def add(self, cdata, i):
space = self.space
raise oefmt(space.w_TypeError, "cannot add a cdata '%s' and a number",
diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py
--- a/pypy/module/_cffi_backend/ctypeprim.py
+++ b/pypy/module/_cffi_backend/ctypeprim.py
@@ -87,6 +87,13 @@
return self.space.wrap(s)
return W_CType.string(self, cdataobj, maxlen)
+ def unpack_ptr(self, w_ctypeptr, ptr, length):
+ result = self.unpack_list_of_int_items(ptr, length)
+ if result is not None:
+ return self.space.newlist_int(result)
+ return W_CType.unpack_ptr(self, w_ctypeptr, ptr, length)
+
+
class W_CTypePrimitiveCharOrUniChar(W_CTypePrimitive):
_attrs_ = []
is_primitive_integer = True
@@ -125,6 +132,10 @@
value = self._convert_to_char(w_ob)
cdata[0] = value
+ def unpack_ptr(self, w_ctypeptr, ptr, length):
+ s = rffi.charpsize2str(ptr, length)
+ return self.space.wrapbytes(s)
+
# XXX explicitly use an integer type instead of lltype.UniChar here,
# because for now the latter is defined as unsigned by RPython (even
@@ -171,6 +182,10 @@
value = self._convert_to_unichar(w_ob)
rffi.cast(rffi.CWCHARP, cdata)[0] = value
+ def unpack_ptr(self, w_ctypeptr, ptr, length):
+ u = rffi.wcharpsize2unicode(rffi.cast(rffi.CWCHARP, ptr), length)
+ return self.space.wrap(u)
+
class W_CTypePrimitiveSigned(W_CTypePrimitive):
_attrs_ = ['value_fits_long', 'value_smaller_than_long']
@@ -221,19 +236,16 @@
def write_raw_integer_data(self, w_cdata, value):
w_cdata.write_raw_signed_data(value)
- def unpack_list_of_int_items(self, w_cdata):
+ def unpack_list_of_int_items(self, ptr, length):
if self.size == rffi.sizeof(rffi.LONG):
from rpython.rlib.rrawarray import populate_list_from_raw_array
res = []
- length = w_cdata.get_array_length()
- with w_cdata as ptr:
- buf = rffi.cast(rffi.LONGP, ptr)
- populate_list_from_raw_array(res, buf, length)
+ buf = rffi.cast(rffi.LONGP, ptr)
+ populate_list_from_raw_array(res, buf, length)
return res
elif self.value_smaller_than_long:
- res = [0] * w_cdata.get_array_length()
- with w_cdata as ptr:
- misc.unpack_list_from_raw_array(res, ptr, self.size)
+ res = [0] * length
+ misc.unpack_list_from_raw_array(res, ptr, self.size)
return res
return None
@@ -313,11 +325,10 @@
def write_raw_integer_data(self, w_cdata, value):
w_cdata.write_raw_unsigned_data(value)
- def unpack_list_of_int_items(self, w_cdata):
+ def unpack_list_of_int_items(self, ptr, length):
if self.value_fits_long:
- res = [0] * w_cdata.get_array_length()
- with w_cdata as ptr:
- misc.unpack_unsigned_list_from_raw_array(res, ptr, self.size)
+ res = [0] * length
+ misc.unpack_unsigned_list_from_raw_array(res, ptr, self.size)
return res
return None
@@ -391,19 +402,16 @@
value = space.float_w(space.float(w_ob))
misc.write_raw_float_data(cdata, value, self.size)
- def unpack_list_of_float_items(self, w_cdata):
+ def unpack_list_of_float_items(self, ptr, length):
if self.size == rffi.sizeof(rffi.DOUBLE):
from rpython.rlib.rrawarray import populate_list_from_raw_array
res = []
- length = w_cdata.get_array_length()
- with w_cdata as ptr:
- buf = rffi.cast(rffi.DOUBLEP, ptr)
- populate_list_from_raw_array(res, buf, length)
+ buf = rffi.cast(rffi.DOUBLEP, ptr)
+ populate_list_from_raw_array(res, buf, length)
return res
elif self.size == rffi.sizeof(rffi.FLOAT):
- res = [0.0] * w_cdata.get_array_length()
- with w_cdata as ptr:
- misc.unpack_cfloat_list_from_raw_array(res, ptr)
+ res = [0.0] * length
+ misc.unpack_cfloat_list_from_raw_array(res, ptr)
return res
return None
@@ -421,6 +429,12 @@
return True
return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob)
+ def unpack_ptr(self, w_ctypeptr, ptr, length):
+ result = self.unpack_list_of_float_items(ptr, length)
+ if result is not None:
+ return self.space.newlist_float(result)
+ return W_CType.unpack_ptr(self, w_ctypeptr, ptr, length)
+
class W_CTypePrimitiveLongDouble(W_CTypePrimitiveFloat):
_attrs_ = []
diff --git a/pypy/module/_cffi_backend/ffi_obj.py b/pypy/module/_cffi_backend/ffi_obj.py
--- a/pypy/module/_cffi_backend/ffi_obj.py
+++ b/pypy/module/_cffi_backend/ffi_obj.py
@@ -542,6 +542,25 @@
return w_cdata.ctype.string(w_cdata, maxlen)
+ @unwrap_spec(w_cdata=W_CData, length=int)
+ def descr_unpack(self, w_cdata, length):
+ """Unpack an array of C data of the given length,
+returning a Python string/unicode/list.
+
+If 'cdata' is a pointer to 'char', returns a byte string.
+It does not stop at the first null. This is equivalent to:
+ffi.buffer(cdata, length)[:]
+
+If 'cdata' is a pointer to 'wchar_t', returns a unicode string.
+'length' is measured in wchar_t's; it is not the size in bytes.
+
+If 'cdata' is a pointer to anything else, returns a list of
+'length' items. This is a faster equivalent to:
+[cdata[i] for i in range(length)]"""
+ #
+ return w_cdata.unpack(length)
+
+
def descr_sizeof(self, w_arg):
"""\
Return the size in bytes of the argument.
@@ -611,6 +630,38 @@
return w_result
+ def descr_list_types(self):
+ """\
+Returns the user type names known to this FFI instance.
+This returns a tuple containing three lists of names:
+(typedef_names, names_of_structs, names_of_unions)"""
+ #
+ space = self.space
+ ctx = self.ctxobj.ctx
+
+ lst1_w = []
+ for i in range(rffi.getintfield(ctx, 'c_num_typenames')):
+ s = rffi.charp2str(ctx.c_typenames[i].c_name)
+ lst1_w.append(space.wrap(s))
+
+ lst2_w = []
+ lst3_w = []
+ for i in range(rffi.getintfield(ctx, 'c_num_struct_unions')):
+ su = ctx.c_struct_unions[i]
+ if su.c_name[0] == '$':
+ continue
+ s = rffi.charp2str(su.c_name)
+ if rffi.getintfield(su, 'c_flags') & cffi_opcode.F_UNION:
+ lst_w = lst3_w
+ else:
+ lst_w = lst2_w
+ lst_w.append(space.wrap(s))
+
+ return space.newtuple([space.newlist(lst1_w),
+ space.newlist(lst2_w),
+ space.newlist(lst3_w)])
+
+
def descr_init_once(self, w_func, w_tag):
"""\
init_once(function, tag): run function() once. More precisely,
@@ -731,6 +782,7 @@
getctype = interp2app(W_FFIObject.descr_getctype),
init_once = interp2app(W_FFIObject.descr_init_once),
integer_const = interp2app(W_FFIObject.descr_integer_const),
+ list_types = interp2app(W_FFIObject.descr_list_types),
memmove = interp2app(W_FFIObject.descr_memmove),
new = interp2app(W_FFIObject.descr_new),
new_allocator = interp2app(W_FFIObject.descr_new_allocator),
@@ -739,4 +791,5 @@
sizeof = interp2app(W_FFIObject.descr_sizeof),
string = interp2app(W_FFIObject.descr_string),
typeof = interp2app(W_FFIObject.descr_typeof),
+ unpack = interp2app(W_FFIObject.descr_unpack),
More information about the pypy-commit
mailing list