Author: mattip <matti.pi...@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") -@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 - - -@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) + +@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), _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit