[pypy-commit] pypy.org extradoc: update the values
Author: Armin RigoBranch: extradoc Changeset: r866:2970c7ecb9a9 Date: 2017-03-01 08:27 +0100 http://bitbucket.org/pypy/pypy.org/changeset/2970c7ecb9a9/ Log:update the values diff --git a/don1.html b/don1.html --- a/don1.html +++ b/don1.html @@ -15,7 +15,7 @@ - $7 of $105000 (63.5%) + $66677 of $105000 (63.5%) @@ -23,7 +23,7 @@ This donation goes towards supporting Python 3 in PyPy. Current status: -we have $2487 left +we have $2495 left in the account. Read proposal ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy fix-cpyext-releasebuffer: (antocuni, rlamy): modify an existing test to show broken behavior: the correct way to implement bf_getbuffer is to do a Py_INCREF(obj), which the broken t
Author: Antonio CuniBranch: fix-cpyext-releasebuffer Changeset: r90432:0d60d6a74fdc Date: 2017-02-28 23:09 +0100 http://bitbucket.org/pypy/pypy/changeset/0d60d6a74fdc/ Log:(antocuni, rlamy): modify an existing test to show broken behavior: the correct way to implement bf_getbuffer is to do a Py_INCREF(obj), which the broken test didn't. Once you do, you notice that cpyext never does the corresponding decref, thus causing a leak because the original object is never deallocated diff --git a/pypy/module/cpyext/test/test_bufferobject.py b/pypy/module/cpyext/test/test_bufferobject.py --- a/pypy/module/cpyext/test/test_bufferobject.py +++ b/pypy/module/cpyext/test/test_bufferobject.py @@ -73,16 +73,27 @@ return obj; """), ("get_cnt", "METH_NOARGS", - 'return PyLong_FromLong(cnt);')], prologue=""" + 'return PyLong_FromLong(cnt);'), +("get_dealloc_cnt", "METH_NOARGS", + 'return PyLong_FromLong(dealloc_cnt);'), +], +prologue=""" static float test_data = 42.f; static int cnt=0; +static int dealloc_cnt=0; static PyHeapTypeObject * type=NULL; +void dealloc(PyObject *self) { +dealloc_cnt++; +} int getbuffer(PyObject *obj, Py_buffer *view, int flags) { cnt ++; memset(view, 0, sizeof(Py_buffer)); view->obj = obj; +/* see the CPython docs for why we need this incref: + https://docs.python.org/3.5/c-api/typeobj.html#c.PyBufferProcs.bf_getbuffer */ +Py_INCREF(obj); view->ndim = 0; view->buf = (void *) _data; view->itemsize = sizeof(float); @@ -96,7 +107,7 @@ void releasebuffer(PyObject *obj, Py_buffer *view) { cnt --; } -""", more_init=""" +""", more_init=""" type = (PyHeapTypeObject *) PyType_Type.tp_alloc(_Type, 0); type->ht_type.tp_name = "Test"; @@ -106,6 +117,7 @@ Py_TPFLAGS_HEAPTYPE | Py_TPFLAGS_HAVE_NEWBUFFER; type->ht_type.tp_flags &= ~Py_TPFLAGS_HAVE_GC; +type->ht_type.tp_dealloc = dealloc; type->ht_type.tp_as_buffer = >as_buffer; type->as_buffer.bf_getbuffer = getbuffer; type->as_buffer.bf_releasebuffer = releasebuffer; @@ -116,6 +128,8 @@ assert module.get_cnt() == 0 a = memoryview(module.create_test()) assert module.get_cnt() == 1 +assert module.get_dealloc_cnt() == 0 del a -gc.collect(); gc.collect(); gc.collect() +self.debug_collect() assert module.get_cnt() == 0 +assert module.get_dealloc_cnt() == 1 ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: merge heads
Author: Antonio CuniBranch: Changeset: r90433:fdae6b92de2f Date: 2017-02-28 23:10 +0100 http://bitbucket.org/pypy/pypy/changeset/fdae6b92de2f/ Log:merge heads diff --git a/pypy/goal/getnightly.py b/pypy/goal/getnightly.py --- a/pypy/goal/getnightly.py +++ b/pypy/goal/getnightly.py @@ -4,16 +4,24 @@ import os import py +TAR_OPTIONS = '-x -v --strip-components=2' +TAR = 'tar {options} -f {tarfile} {files}' + +def untar(tarfile, files): +cmd = TAR.format(options=TAR_OPTIONS, tarfile=tarfile, files=files) +os.system(cmd) + if sys.platform.startswith('linux'): arch = 'linux' cmd = 'wget "%s"' -tar = "tar -x -v --wildcards --strip-components=2 -f %s '*/bin/pypy' '*/bin/libpypy-c.so'" +TAR_OPTIONS += ' --wildcards' +binfiles = "'*/bin/pypy' '*/bin/libpypy-c.so'" if os.uname()[-1].startswith('arm'): arch += '-armhf-raspbian' elif sys.platform.startswith('darwin'): arch = 'osx' cmd = 'curl -O "%s"' -tar = "tar -x -v --strip-components=2 -f %s '*/bin/pypy'" +binfiles = "'*/bin/pypy'" else: print 'Cannot determine the platform, please update this script' sys.exit(1) @@ -34,6 +42,7 @@ filename = 'pypy-c-%s-latest-%s.tar.bz2' % (kind, arch) url = 'http://buildbot.pypy.org/nightly/%s/%s' % (branch, filename) tmp = py.path.local.mkdtemp() +pypy_latest = tmp.join(filename) mydir = tmp.chdir() print 'Downloading pypy to', tmp if os.system(cmd % url) != 0: @@ -41,4 +50,10 @@ print 'Extracting pypy binary' mydir.chdir() -os.system(tar % tmp.join(filename)) +untar(pypy_latest, binfiles) +include_dir = py.path.local('../../include') +if include_dir.check(dir=True): +include_dir.chdir() +untar(pypy_latest, '*/include/*') +else: +print 'WARNING: could not find the include/ dir' ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: hack hack hack getnightly.py until it extracts also the *.h files in the proper dir
Author: Antonio CuniBranch: Changeset: r90431:e2e364614275 Date: 2017-02-27 12:06 +0100 http://bitbucket.org/pypy/pypy/changeset/e2e364614275/ Log:hack hack hack getnightly.py until it extracts also the *.h files in the proper dir diff --git a/pypy/goal/getnightly.py b/pypy/goal/getnightly.py --- a/pypy/goal/getnightly.py +++ b/pypy/goal/getnightly.py @@ -4,16 +4,24 @@ import os import py +TAR_OPTIONS = '-x -v --strip-components=2' +TAR = 'tar {options} -f {tarfile} {files}' + +def untar(tarfile, files): +cmd = TAR.format(options=TAR_OPTIONS, tarfile=tarfile, files=files) +os.system(cmd) + if sys.platform.startswith('linux'): arch = 'linux' cmd = 'wget "%s"' -tar = "tar -x -v --wildcards --strip-components=2 -f %s '*/bin/pypy' '*/bin/libpypy-c.so'" +TAR_OPTIONS += ' --wildcards' +binfiles = "'*/bin/pypy' '*/bin/libpypy-c.so'" if os.uname()[-1].startswith('arm'): arch += '-armhf-raspbian' elif sys.platform.startswith('darwin'): arch = 'osx' cmd = 'curl -O "%s"' -tar = "tar -x -v --strip-components=2 -f %s '*/bin/pypy'" +binfiles = "'*/bin/pypy'" else: print 'Cannot determine the platform, please update this script' sys.exit(1) @@ -34,6 +42,7 @@ filename = 'pypy-c-%s-latest-%s.tar.bz2' % (kind, arch) url = 'http://buildbot.pypy.org/nightly/%s/%s' % (branch, filename) tmp = py.path.local.mkdtemp() +pypy_latest = tmp.join(filename) mydir = tmp.chdir() print 'Downloading pypy to', tmp if os.system(cmd % url) != 0: @@ -41,4 +50,10 @@ print 'Extracting pypy binary' mydir.chdir() -os.system(tar % tmp.join(filename)) +untar(pypy_latest, binfiles) +include_dir = py.path.local('../../include') +if include_dir.check(dir=True): +include_dir.chdir() +untar(pypy_latest, '*/include/*') +else: +print 'WARNING: could not find the include/ dir' ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Fix logging.getLevelName, applying #29220 CPython issue.
Author: Robert ZarembaBranch: py3.5 Changeset: r90430:55230b1507ef Date: 2017-02-28 18:33 +0100 http://bitbucket.org/pypy/pypy/changeset/55230b1507ef/ Log:Fix logging.getLevelName, applying #29220 CPython issue. The getLevelName function incorrectly fallsback. 0 is correct value returned from the names map, but when using `or` check it falsifies and fallback to the "level" case. http://buildbot.pypy.org/summary/longrepr?testname=unmodified r=pypy-c-jit-linux-x86-64=4416=lib- python.3.test.test_logging diff --git a/lib-python/3/logging/__init__.py b/lib-python/3/logging/__init__.py --- a/lib-python/3/logging/__init__.py +++ b/lib-python/3/logging/__init__.py @@ -129,9 +129,14 @@ Otherwise, the string "Level %s" % level is returned. """ -# See Issues #22386 and #27937 for why it's this way -return (_levelToName.get(level) or _nameToLevel.get(level) or -"Level %s" % level) +# See Issues #22386, #27937 and #29220 for why it's this way +result = _levelToName.get(level) +if result is not None: +return result +result = _nameToLevel.get(level) +if result is not None: +return result +return "Level %s" % level def addLevelName(level, levelName): """ ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy nogil-unsafe-2: (remi, arigo) general process, still completely crashing
Author: Armin RigoBranch: nogil-unsafe-2 Changeset: r90429:7be972407621 Date: 2017-02-28 17:22 +0100 http://bitbucket.org/pypy/pypy/changeset/7be972407621/ Log:(remi, arigo) general process, still completely crashing diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py --- a/rpython/memory/gc/incminimark.py +++ b/rpython/memory/gc/incminimark.py @@ -506,7 +506,7 @@ if gc_increment_step > 0: self.gc_increment_step = gc_increment_step else: -self.gc_increment_step = newsize * 4 +self.gc_increment_step = r_uint(newsize) * 4 # nursery_debug = env.read_uint_from_env('PYPY_GC_NURSERY_DEBUG') if nursery_debug > 0: @@ -514,7 +514,6 @@ else: self.gc_nursery_debug = False self._minor_collection()# to empty the nursery -llarena.arena_free(self.nursery) self.nursery_size = newsize self.allocate_nursery() # @@ -556,6 +555,17 @@ def allocate_nursery(self): debug_start("gc-set-nursery-size") debug_print("nursery size:", self.nursery_size) +# +if self.nursery:# free the old nursery +llarena.arena_free(self.nursery) +self.nursery = llmemory.NULL +ll_assert(not self.surviving_pinned_objects.non_empty(), + "pinned objects too early in the process") +self.nursery_barriers.delete() +self.nursery_barriers = self.AddressDeque() +self.set_nursery_free(llmemory.NULL) +self.set_nursery_top(llmemory.NULL) +# self.nursery = self._alloc_nursery() # initialize the threshold self.min_heap_size = max(self.min_heap_size, self.nursery_size * @@ -645,10 +655,10 @@ @property def nursery_top(self): -raise AssertionError, "fix caller" +XXX # fix caller @property def nursery_free(self): -raise AssertionError, "fix caller" +XXX # fix caller def malloc_fixedsize(self, typeid, size, @@ -752,10 +762,15 @@ # # Get the memory from the nursery. If there is not enough space # there, do a collect first. -result = self.nursery_free -ll_assert(result != llmemory.NULL, "uninitialized nursery") -self.nursery_free = new_free = result + totalsize -if new_free > self.nursery_top: +result = self.get_nursery_free() +if not we_are_translated() and result == llmemory.NULL: +# can't do arithmetic from NULL when non-translated +grab_next_block = True +else: +new_free = result + totalsize +self.set_nursery_free(new_free) +grab_next_block = new_free > self.get_nursery_top() +if grab_next_block: result = self.collect_and_reserve(totalsize) # # Build the object. @@ -916,8 +931,10 @@ # # if self.debug_tiny_nursery >= 0: # for debugging -if self.nursery_top - self.nursery_free > self.debug_tiny_nursery: -self.nursery_free = self.nursery_top - self.debug_tiny_nursery +if (self.get_nursery_top() - self.get_nursery_free() > + self.debug_tiny_nursery): +self.set_nursery_free(self.get_nursery_top() - + self.debug_tiny_nursery) # rthread.release_NOAUTO(self.ll_lock) return result @@ -1078,7 +1095,7 @@ if self.next_major_collection_threshold < 0: # cannot trigger a full collection now, but we can ensure # that one will occur very soon -self.nursery_free = self.nursery_top +self.set_nursery_free(self.get_nursery_top()) def can_optimize_clean_setarrayitems(self): if self.card_page_indices > 0: @@ -1185,7 +1202,7 @@ # Check if the object at 'addr' is young. if not self.is_valid_gc_object(addr): return False # filter out tagged pointers explicitly. -if self.nursery <= addr < self.nursery_top: +if self.is_in_nursery(addr): return True # addr is in the nursery # Else, it may be in the set 'young_rawmalloced_objects' return (bool(self.young_rawmalloced_objects) and @@ -1675,8 +1692,8 @@ # nursery_top if we_are_translated(): def zero_nursery_pointers(arg, tl): -(tl + NURSERY_FREE.offset).address[0] = llmemory.NULL -(tl + NURSERY_TOP.offset).address[0] = llmemory.NULL +(tl + NURSERY_FREE._offset).address[0] = llmemory.NULL +(tl + NURSERY_TOP._offset).address[0] = llmemory.NULL
[pypy-commit] pypy default: (remi, arigo)
Author: Armin RigoBranch: Changeset: r90428:71318996f4ec Date: 2017-02-28 16:41 +0100 http://bitbucket.org/pypy/pypy/changeset/71318996f4ec/ Log:(remi, arigo) - use incminimark in test_standalone, instead of semispace gc - fix potential future bug diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py --- a/rpython/memory/gc/incminimark.py +++ b/rpython/memory/gc/incminimark.py @@ -1138,7 +1138,7 @@ # Check if the object at 'addr' is young. if not self.is_valid_gc_object(addr): return False # filter out tagged pointers explicitly. -if self.nursery <= addr < self.nursery_top: +if self.is_in_nursery(addr): return True # addr is in the nursery # Else, it may be in the set 'young_rawmalloced_objects' return (bool(self.young_rawmalloced_objects) and diff --git a/rpython/translator/c/test/test_standalone.py b/rpython/translator/c/test/test_standalone.py --- a/rpython/translator/c/test/test_standalone.py +++ b/rpython/translator/c/test/test_standalone.py @@ -1123,7 +1123,7 @@ def compile(self, entry_point, no__thread=True): t = TranslationContext(self.config) -t.config.translation.gc = "semispace" +t.config.translation.gc = "incminimark" t.config.translation.gcrootfinder = self.gcrootfinder t.config.translation.thread = True t.config.translation.no__thread = no__thread ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy nogil-unsafe-2: (remi, arigo) port some locks from stmgc
Author: Armin RigoBranch: nogil-unsafe-2 Changeset: r90427:52bbdf98f118 Date: 2017-02-28 16:15 +0100 http://bitbucket.org/pypy/pypy/changeset/52bbdf98f118/ Log:(remi, arigo) port some locks from stmgc diff --git a/rpython/translator/c/src/mem.c b/rpython/translator/c/src/mem.c --- a/rpython/translator/c/src/mem.c +++ b/rpython/translator/c/src/mem.c @@ -15,15 +15,19 @@ static struct pypy_debug_alloc_s *pypy_debug_alloc_list = NULL; +static rpy_spinlock_t pypy_debug_alloc_lock = 0; + RPY_EXTERN void pypy_debug_alloc_start(void *addr, const char *funcname) { struct pypy_debug_alloc_s *p = malloc(sizeof(struct pypy_debug_alloc_s)); RPyAssert(p, "out of memory"); - p->next = pypy_debug_alloc_list; p->addr = addr; p->funcname = funcname; + rpy_spinlock_acquire(_debug_alloc_lock); + p->next = pypy_debug_alloc_list; pypy_debug_alloc_list = p; + rpy_spinlock_release(_debug_alloc_lock); } RPY_EXTERN @@ -32,12 +36,14 @@ struct pypy_debug_alloc_s **p; if (!addr) return; + rpy_spinlock_acquire(_debug_alloc_lock); for (p = _debug_alloc_list; *p; p = &((*p)->next)) if ((*p)->addr == addr) { struct pypy_debug_alloc_s *dying; dying = *p; *p = dying->next; +rpy_spinlock_release(_debug_alloc_lock); free(dying); return; } @@ -49,6 +55,7 @@ { long count = 0; struct pypy_debug_alloc_s *p; + rpy_spinlock_acquire(_debug_alloc_lock); for (p = pypy_debug_alloc_list; p; p = p->next) count++; if (count > 0) @@ -64,6 +71,7 @@ else fprintf(stderr, " (use PYPY_ALLOC=1 to see the list)\n"); } + rpy_spinlock_release(_debug_alloc_lock); } #endif /* RPY_ASSERT */ diff --git a/rpython/translator/c/src/thread.h b/rpython/translator/c/src/thread.h --- a/rpython/translator/c/src/thread.h +++ b/rpython/translator/c/src/thread.h @@ -58,4 +58,15 @@ //return _fastgil; } +typedef unsigned char rpy_spinlock_t; +static inline void rpy_spinlock_acquire(rpy_spinlock_t *p) +{ +while (pypy_lock_test_and_set(p, 1) != 0) +pypy_spin_loop(); +} +static inline void rpy_spinlock_release(rpy_spinlock_t *p) +{ +pypy_lock_release(p); +} + #endif diff --git a/rpython/translator/c/src/thread_pthread.h b/rpython/translator/c/src/thread_pthread.h --- a/rpython/translator/c/src/thread_pthread.h +++ b/rpython/translator/c/src/thread_pthread.h @@ -84,3 +84,9 @@ #define pypy_lock_test_and_set(ptr, value) __sync_lock_test_and_set(ptr, value) #define pypy_lock_release(ptr) __sync_lock_release(ptr) + +#if defined(__i386__) || defined(__amd64__) + static inline void pypy_spin_loop(void) { asm("pause" : : : "memory"); } +#else +# define pypy_spin_loop() /* nothing */ +#endif diff --git a/rpython/translator/c/test/test_standalone.py b/rpython/translator/c/test/test_standalone.py --- a/rpython/translator/c/test/test_standalone.py +++ b/rpython/translator/c/test/test_standalone.py @@ -1431,8 +1431,15 @@ import time, gc from rpython.rlib import rthread, rposix +class X: +def __init__(self, prev): +self.prev = prev + def bootstrap(): rthread.gc_thread_start() +x = None +for i in range(1000): +x = X(x) os.write(1, "hi there\n") rthread.gc_thread_die() ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy nogil-unsafe-2: (fijal, remi, arigo) add a lock
Author: Armin RigoBranch: nogil-unsafe-2 Changeset: r90426:41abf85d7a14 Date: 2017-02-28 15:49 +0100 http://bitbucket.org/pypy/pypy/changeset/41abf85d7a14/ Log:(fijal, remi, arigo) add a lock diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py --- a/rpython/memory/gc/incminimark.py +++ b/rpython/memory/gc/incminimark.py @@ -438,6 +438,12 @@ self.old_objects_pointing_to_pinned = self.AddressStack() self.updated_old_objects_pointing_to_pinned = False # +# Allocate lock(s) +ll_lock = lltype.malloc(rthread.TLOCKP.TO, flavor='raw', +track_allocation=False) +rthread.c_thread_lock_init(ll_lock) +self.ll_lock = ll_lock +# # Allocate a nursery. In case of auto_nursery_size, start by # allocating a very small nursery, enough to do things like look # up the env var, which requires the GC; and then really @@ -838,6 +844,8 @@ major collection, and finally reserve totalsize bytes. """ +rthread.acquire_NOAUTO(self.ll_lock, 1) + minor_collection_count = 0 while True: self.set_nursery_free(llmemory.NULL) # debug: don't use me @@ -911,6 +919,7 @@ if self.nursery_top - self.nursery_free > self.debug_tiny_nursery: self.nursery_free = self.nursery_top - self.debug_tiny_nursery # +rthread.release_NOAUTO(self.ll_lock) return result collect_and_reserve._dont_inline_ = True ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5-fix-decimal-module-name: (stevie, robert-zaremba) FIX: test_pickle (test.test_decimal.PyPythonAPItests)
Author: Robert ZarembaBranch: py3.5-fix-decimal-module-name Changeset: r90424:793b49cacddd Date: 2017-02-28 15:32 +0100 http://bitbucket.org/pypy/pypy/changeset/793b49cacddd/ Log:(stevie, robert-zaremba) FIX: test_pickle (test.test_decimal.PyPythonAPItests) Fixes: http://buildbot.pypy.org/summary/longrepr?testname=unmodified =pypy-c-jit-linux-x86-64=4406=lib- python.3.test.test_decimal We removed the __module__ hack from the classes in lib_pypy/_decimal.py and added module __name__ pointing to the right module name. diff --git a/extra_tests/support.py b/extra_tests/support.py new file mode 100644 --- /dev/null +++ b/extra_tests/support.py @@ -0,0 +1,98 @@ +import contextlib +import importlib +import sys +import warnings + + +@contextlib.contextmanager +def _ignore_deprecated_imports(ignore=True): +"""Context manager to suppress package and module deprecation +warnings when importing them. + +If ignore is False, this context manager has no effect. +""" +if ignore: +with warnings.catch_warnings(): +warnings.filterwarnings("ignore", ".+ (module|package)", +DeprecationWarning) +yield +else: +yield + + +def _save_and_remove_module(name, orig_modules): +"""Helper function to save and remove a module from sys.modules + +Raise ImportError if the module can't be imported. +""" +# try to import the module and raise an error if it can't be imported +if name not in sys.modules: +__import__(name) +del sys.modules[name] +for modname in list(sys.modules): +if modname == name or modname.startswith(name + '.'): +orig_modules[modname] = sys.modules[modname] +del sys.modules[modname] + +def _save_and_block_module(name, orig_modules): +"""Helper function to save and block a module in sys.modules + +Return True if the module was in sys.modules, False otherwise. +""" +saved = True +try: +orig_modules[name] = sys.modules[name] +except KeyError: +saved = False +sys.modules[name] = None +return saved + + +def import_fresh_module(name, fresh=(), blocked=(), deprecated=False): +"""Import and return a module, deliberately bypassing sys.modules. + +This function imports and returns a fresh copy of the named Python module +by removing the named module from sys.modules before doing the import. +Note that unlike reload, the original module is not affected by +this operation. + +*fresh* is an iterable of additional module names that are also removed +from the sys.modules cache before doing the import. + +*blocked* is an iterable of module names that are replaced with None +in the module cache during the import to ensure that attempts to import +them raise ImportError. + +The named module and any modules named in the *fresh* and *blocked* +parameters are saved before starting the import and then reinserted into +sys.modules when the fresh import is complete. + +Module and package deprecation messages are suppressed during this import +if *deprecated* is True. + +This function will raise ImportError if the named module cannot be +imported. +""" +# NOTE: test_heapq, test_json and test_warnings include extra sanity checks +# to make sure that this utility function is working as expected +with _ignore_deprecated_imports(deprecated): +# Keep track of modules saved for later restoration as well +# as those which just need a blocking entry removed +orig_modules = {} +names_to_remove = [] +_save_and_remove_module(name, orig_modules) +try: +for fresh_name in fresh: +_save_and_remove_module(fresh_name, orig_modules) +for blocked_name in blocked: +if not _save_and_block_module(blocked_name, orig_modules): +names_to_remove.append(blocked_name) +fresh_module = importlib.import_module(name) +except ImportError: +fresh_module = None +finally: +for orig_name, module in orig_modules.items(): +sys.modules[orig_name] = module +for name_to_remove in names_to_remove: +del sys.modules[name_to_remove] +return fresh_module diff --git a/extra_tests/test_decimal.py b/extra_tests/test_decimal.py new file mode 100644 --- /dev/null +++ b/extra_tests/test_decimal.py @@ -0,0 +1,59 @@ +import pickle +import sys + +from support import import_fresh_module + +C = import_fresh_module('decimal', fresh=['_decimal']) +P = import_fresh_module('decimal', blocked=['_decimal']) +# import _decimal as C +# import _pydecimal as P + + +class TestPythonAPI: + +def check_equal(self, val, proto): +d = C.Decimal(val) +p = pickle.dumps(d, proto) +
[pypy-commit] pypy py3.5-fix-decimal-module-name: Added .venv (virtualenvironment) and .cache to .hgignore
Author: Robert ZarembaBranch: py3.5-fix-decimal-module-name Changeset: r90423:cc54d3bbf8a5 Date: 2017-02-28 15:28 +0100 http://bitbucket.org/pypy/pypy/changeset/cc54d3bbf8a5/ Log:Added .venv (virtualenvironment) and .cache to .hgignore diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -7,6 +7,8 @@ .project .pydevproject __pycache__ +.venv +.cache syntax: regexp ^testresult$ ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Merged in robert-zaremba/pypy/py3.5-fix-decimal-module-name (pull request #522)
Author: Ronan LamyBranch: py3.5 Changeset: r90425:b7745d301387 Date: 2017-02-28 14:48 + http://bitbucket.org/pypy/pypy/changeset/b7745d301387/ Log:Merged in robert-zaremba/pypy/py3.5-fix-decimal-module-name (pull request #522) Py3.5 fix decimal module name diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -7,6 +7,8 @@ .project .pydevproject __pycache__ +.venv +.cache syntax: regexp ^testresult$ diff --git a/extra_tests/support.py b/extra_tests/support.py new file mode 100644 --- /dev/null +++ b/extra_tests/support.py @@ -0,0 +1,98 @@ +import contextlib +import importlib +import sys +import warnings + + +@contextlib.contextmanager +def _ignore_deprecated_imports(ignore=True): +"""Context manager to suppress package and module deprecation +warnings when importing them. + +If ignore is False, this context manager has no effect. +""" +if ignore: +with warnings.catch_warnings(): +warnings.filterwarnings("ignore", ".+ (module|package)", +DeprecationWarning) +yield +else: +yield + + +def _save_and_remove_module(name, orig_modules): +"""Helper function to save and remove a module from sys.modules + +Raise ImportError if the module can't be imported. +""" +# try to import the module and raise an error if it can't be imported +if name not in sys.modules: +__import__(name) +del sys.modules[name] +for modname in list(sys.modules): +if modname == name or modname.startswith(name + '.'): +orig_modules[modname] = sys.modules[modname] +del sys.modules[modname] + +def _save_and_block_module(name, orig_modules): +"""Helper function to save and block a module in sys.modules + +Return True if the module was in sys.modules, False otherwise. +""" +saved = True +try: +orig_modules[name] = sys.modules[name] +except KeyError: +saved = False +sys.modules[name] = None +return saved + + +def import_fresh_module(name, fresh=(), blocked=(), deprecated=False): +"""Import and return a module, deliberately bypassing sys.modules. + +This function imports and returns a fresh copy of the named Python module +by removing the named module from sys.modules before doing the import. +Note that unlike reload, the original module is not affected by +this operation. + +*fresh* is an iterable of additional module names that are also removed +from the sys.modules cache before doing the import. + +*blocked* is an iterable of module names that are replaced with None +in the module cache during the import to ensure that attempts to import +them raise ImportError. + +The named module and any modules named in the *fresh* and *blocked* +parameters are saved before starting the import and then reinserted into +sys.modules when the fresh import is complete. + +Module and package deprecation messages are suppressed during this import +if *deprecated* is True. + +This function will raise ImportError if the named module cannot be +imported. +""" +# NOTE: test_heapq, test_json and test_warnings include extra sanity checks +# to make sure that this utility function is working as expected +with _ignore_deprecated_imports(deprecated): +# Keep track of modules saved for later restoration as well +# as those which just need a blocking entry removed +orig_modules = {} +names_to_remove = [] +_save_and_remove_module(name, orig_modules) +try: +for fresh_name in fresh: +_save_and_remove_module(fresh_name, orig_modules) +for blocked_name in blocked: +if not _save_and_block_module(blocked_name, orig_modules): +names_to_remove.append(blocked_name) +fresh_module = importlib.import_module(name) +except ImportError: +fresh_module = None +finally: +for orig_name, module in orig_modules.items(): +sys.modules[orig_name] = module +for name_to_remove in names_to_remove: +del sys.modules[name_to_remove] +return fresh_module diff --git a/extra_tests/test_decimal.py b/extra_tests/test_decimal.py new file mode 100644 --- /dev/null +++ b/extra_tests/test_decimal.py @@ -0,0 +1,59 @@ +import pickle +import sys + +from support import import_fresh_module + +C = import_fresh_module('decimal', fresh=['_decimal']) +P = import_fresh_module('decimal', blocked=['_decimal']) +# import _decimal as C +# import _pydecimal as P + + +class TestPythonAPI: + +def check_equal(self, val, proto): +d = C.Decimal(val) +p = pickle.dumps(d, proto) +assert d == pickle.loads(p) + +def test_C(self): +sys.modules["decimal"] = C +import decimal +d =
[pypy-commit] pypy nogil-unsafe-2: progress
Author: Armin RigoBranch: nogil-unsafe-2 Changeset: r90422:643158ba7b39 Date: 2017-02-28 15:31 +0100 http://bitbucket.org/pypy/pypy/changeset/643158ba7b39/ Log:progress diff --git a/rpython/memory/gctransform/shadowstack.py b/rpython/memory/gctransform/shadowstack.py --- a/rpython/memory/gctransform/shadowstack.py +++ b/rpython/memory/gctransform/shadowstack.py @@ -104,7 +104,7 @@ self.rootstackhook(collect_stack_root, gcdata.root_stack_base, gcdata.root_stack_top) -def need_thread_support(self, gctransformer, getfn): +def need_thread_support_WITH_GIL(self, gctransformer, getfn): from rpython.rlib import rthread# xxx fish gcdata = self.gcdata # the interfacing between the threads and the GC is done via @@ -218,6 +218,49 @@ annmodel.s_None, minimal_transform=False) +def need_thread_support(self, gctransformer, getfn): # NO GIL VERSION +from rpython.rlib import rthread +gcdata = self.gcdata +# the interfacing between the threads and the GC is done via +# two completely ad-hoc operations at the moment: +# gc_thread_run and gc_thread_die. See docstrings below. + +tl_shadowstack = rthread.ThreadLocalField(llmemory.Address, + 'shadowstack') + +def thread_setup(): +allocate_shadow_stack() + +def thread_run(): +# If it's the first time we see this thread, allocate +# a shadowstack. +if tl_shadowstack.get_or_make_raw() == llmemory.NULL: +allocate_shadow_stack() + +def allocate_shadow_stack(): +root_stack_depth = 163840 +root_stack_size = sizeofaddr * root_stack_depth +ss = llmemory.raw_malloc(root_stack_size) +if not ss: +raise MemoryError +tl_shadowstack.setraw(ss) +allocate_shadow_stack._dont_inline_ = True + +def thread_die(): +"""Called just before the final GIL release done by a dying +thread. After a thread_die(), no more gc operation should +occur in this thread. +""" +p = tl_shadowstack.get_or_make_raw() +tl_shadowstack.setraw(llmemory.NULL) +llmemory.raw_free(p) + +self.thread_setup = thread_setup +self.thread_run_ptr = getfn(thread_run, [], annmodel.s_None, +inline=True, minimal_transform=False) +self.thread_die_ptr = getfn(thread_die, [], annmodel.s_None, +minimal_transform=False) + def need_stacklet_support(self, gctransformer, getfn): from rpython.rlib import _stacklet_shadowstack _stacklet_shadowstack.complete_destrptr(gctransformer) diff --git a/rpython/translator/c/src/thread.h b/rpython/translator/c/src/thread.h --- a/rpython/translator/c/src/thread.h +++ b/rpython/translator/c/src/thread.h @@ -2,6 +2,7 @@ #define __PYPY_THREAD_H #include "precommondefs.h" #include +#include #define RPY_TIMEOUT_T long long @@ -41,19 +42,20 @@ # define RPY_FASTGIL_LOCKED(x) (x != 0) #endif -RPY_EXTERN long rpy_fastgil; +//RPY_EXTERN long rpy_fastgil; static inline void _RPyGilAcquire(void) { -long old_fastgil = pypy_lock_test_and_set(_fastgil, 1); -if (old_fastgil != 0) -RPyGilAcquireSlowPath(old_fastgil); +//long old_fastgil = pypy_lock_test_and_set(_fastgil, 1); +//if (old_fastgil != 0) +//RPyGilAcquireSlowPath(old_fastgil); } static inline void _RPyGilRelease(void) { -assert(RPY_FASTGIL_LOCKED(rpy_fastgil)); -pypy_lock_release(_fastgil); +//assert(RPY_FASTGIL_LOCKED(rpy_fastgil)); +//pypy_lock_release(_fastgil); } static inline long *_RPyFetchFastGil(void) { -return _fastgil; +abort(); +//return _fastgil; } #endif diff --git a/rpython/translator/c/src/thread_gil.c b/rpython/translator/c/src/thread_gil.c --- a/rpython/translator/c/src/thread_gil.c +++ b/rpython/translator/c/src/thread_gil.c @@ -58,13 +58,13 @@ void RPyGilAllocate(void) { -if (rpy_waiting_threads < 0) { -assert(rpy_waiting_threads == -42); -rpy_init_mutexes(); +//if (rpy_waiting_threads < 0) { +//assert(rpy_waiting_threads == -42); +//rpy_init_mutexes(); #ifdef HAVE_PTHREAD_ATFORK -pthread_atfork(NULL, NULL, rpy_init_mutexes); +//pthread_atfork(NULL, NULL, rpy_init_mutexes); #endif -} +//} } static void check_and_save_old_fastgil(long old_fastgil) diff --git a/rpython/translator/c/test/test_standalone.py b/rpython/translator/c/test/test_standalone.py --- a/rpython/translator/c/test/test_standalone.py +++ b/rpython/translator/c/test/test_standalone.py @@ -1427,6 +1427,46 @@ and result.count('a') == 1
[pypy-commit] pypy default: test showing a corner case of the interaction between finalizers and heap
Author: Carl Friedrich BolzBranch: Changeset: r90421:846ed5d2ac16 Date: 2017-02-28 15:00 +0100 http://bitbucket.org/pypy/pypy/changeset/846ed5d2ac16/ Log:test showing a corner case of the interaction between finalizers and heap caching in the JIT diff --git a/rpython/jit/metainterp/test/test_ajit.py b/rpython/jit/metainterp/test/test_ajit.py --- a/rpython/jit/metainterp/test/test_ajit.py +++ b/rpython/jit/metainterp/test/test_ajit.py @@ -4636,3 +4636,28 @@ return i self.meta_interp(f, [10]) + +@py.test.skip("loops!") +def test_finalizer_bug(self): +from rpython.rlib import rgc +driver = JitDriver(greens=[], reds=[]) +class Fin(object): +@rgc.must_be_light_finalizer +def __del__(self): +holder[0].field = 7 +class Un(object): +def __init__(self): +self.field = 0 +holder = [Un()] + +def f(): +while True: +driver.jit_merge_point() +holder[0].field = 0 +Fin() +if holder[0].field: +break +return holder[0].field + +f() # finishes +self.meta_interp(f, []) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy nogil-unsafe-2: (fijal, arigo) test and fix
Author: Armin RigoBranch: nogil-unsafe-2 Changeset: r90420:56c4cf2a149a Date: 2017-02-28 13:53 +0100 http://bitbucket.org/pypy/pypy/changeset/56c4cf2a149a/ Log:(fijal, arigo) test and fix diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py --- a/rpython/memory/gc/incminimark.py +++ b/rpython/memory/gc/incminimark.py @@ -1653,12 +1653,25 @@ # -- # Nursery collection +def zero_nursery_pointers_in_all_threads(self): +pass# patched in test_thread + def _minor_collection(self): """Perform a minor collection: find the objects from the nursery that remain alive and move them out.""" # debug_start("gc-minor") # +# First, write NULLs in all thread's nursery_free and +# nursery_top +if we_are_translated(): +def zero_nursery_pointers(arg, tl): +(tl + NURSERY_FREE.offset).address[0] = llmemory.NULL +(tl + NURSERY_TOP.offset).address[0] = llmemory.NULL +rthread.enum_all_threadlocals(zero_nursery_pointers, None) +else: +self.zero_nursery_pointers_in_all_threads() +# # All nursery barriers are invalid from this point on. They # are evaluated anew as part of the minor collection. self.nursery_barriers.delete() diff --git a/rpython/memory/gc/test/test_thread.py b/rpython/memory/gc/test/test_thread.py --- a/rpython/memory/gc/test/test_thread.py +++ b/rpython/memory/gc/test/test_thread.py @@ -1,5 +1,5 @@ import pytest -from rpython.rtyper.lltypesystem import lltype +from rpython.rtyper.lltypesystem import lltype, llmemory from rpython.memory.gc import incminimark from rpython.memory.gc.test.test_direct import BaseDirectGCTest, S @@ -14,9 +14,15 @@ incminimark.NEXT_NUBLOCK, ] -def __init__(self): +def __init__(self, gc): self.cache = {} self.switch_thread(0) +gc.zero_nursery_pointers_in_all_threads = self._zero_pointers + +def _zero_pointers(self): +for (tl, thread_num), local in self.cache.items(): +if tl in (incminimark.NURSERY_FREE, incminimark.NURSERY_TOP): +local.rawvalue = llmemory.NULL def switch_thread(self, thread_num): for tl in self.all_threadlocals: @@ -27,11 +33,19 @@ from rpython.memory.gc.incminimark import IncrementalMiniMarkGC as GCClass def test_malloc_fixedsize(self): -ts = ThreadSwitcher() +ts = ThreadSwitcher(self.gc) for i in range(1000): p = self.malloc(S) p.x = 42 assert p.prev == lltype.nullptr(S) assert p.next == lltype.nullptr(S) ts.switch_thread(i & 1) -#... + +def test_malloc_fixedsize_2(self): +ts = ThreadSwitcher(self.gc) +for i in range(1000): +p = self.malloc(S) +p.x = 42 +assert p.prev == lltype.nullptr(S) +assert p.next == lltype.nullptr(S) +ts.switch_thread(0 if i % 5 < 2 else 1) diff --git a/rpython/rlib/rthread.py b/rpython/rlib/rthread.py --- a/rpython/rlib/rthread.py +++ b/rpython/rlib/rthread.py @@ -469,3 +469,15 @@ def specialize_call(self, hop): hop.exception_cannot_occur() + + +@specialize.arg(0) +def enum_all_threadlocals(callback, arg): +p = llmemory.NULL +llop.threadlocalref_acquire(lltype.Void) +while True: +p = llop.threadlocalref_enum(llmemory.Address, p) +if not p: +break +callback(arg, p) +llop.threadlocalref_release(lltype.Void) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy nogil-unsafe-2: (fijal, arigo) add the test
Author: Armin RigoBranch: nogil-unsafe-2 Changeset: r90419:ef99e1203aa4 Date: 2017-02-28 13:20 +0100 http://bitbucket.org/pypy/pypy/changeset/ef99e1203aa4/ Log:(fijal, arigo) add the test diff --git a/rpython/memory/gc/test/test_thread.py b/rpython/memory/gc/test/test_thread.py new file mode 100644 --- /dev/null +++ b/rpython/memory/gc/test/test_thread.py @@ -0,0 +1,37 @@ +import pytest +from rpython.rtyper.lltypesystem import lltype +from rpython.memory.gc import incminimark +from rpython.memory.gc.test.test_direct import BaseDirectGCTest, S + + +class LocalsForTests: +pass + + +class ThreadSwitcher: +all_threadlocals = [incminimark.NURSERY_FREE, +incminimark.NURSERY_TOP, +incminimark.NEXT_NUBLOCK, +] + +def __init__(self): +self.cache = {} +self.switch_thread(0) + +def switch_thread(self, thread_num): +for tl in self.all_threadlocals: +tl.local = self.cache.setdefault((tl, thread_num), LocalsForTests()) + + +class TestMultithreaded(BaseDirectGCTest): +from rpython.memory.gc.incminimark import IncrementalMiniMarkGC as GCClass + +def test_malloc_fixedsize(self): +ts = ThreadSwitcher() +for i in range(1000): +p = self.malloc(S) +p.x = 42 +assert p.prev == lltype.nullptr(S) +assert p.next == lltype.nullptr(S) +ts.switch_thread(i & 1) +#... ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy nogil-unsafe-2: (fijal, arigo) Starting to copy some part of the logic from nogil-unsafe
Author: Armin RigoBranch: nogil-unsafe-2 Changeset: r90418:927663f424f4 Date: 2017-02-28 13:19 +0100 http://bitbucket.org/pypy/pypy/changeset/927663f424f4/ Log:(fijal, arigo) Starting to copy some part of the logic from nogil- unsafe diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py --- a/rpython/memory/gc/incminimark.py +++ b/rpython/memory/gc/incminimark.py @@ -71,7 +71,8 @@ from rpython.rlib.rarithmetic import ovfcheck, LONG_BIT, intmask, r_uint from rpython.rlib.rarithmetic import LONG_BIT_SHIFT from rpython.rlib.debug import ll_assert, debug_print, debug_start, debug_stop -from rpython.rlib.objectmodel import specialize +from rpython.rlib.objectmodel import specialize, we_are_translated +from rpython.rlib import rthread from rpython.memory.gc.minimarkpage import out_of_memory # @@ -188,6 +189,10 @@ FORWARDSTUBPTR = lltype.Ptr(FORWARDSTUB) NURSARRAY = lltype.Array(llmemory.Address) +NURSERY_FREE = rthread.ThreadLocalField(llmemory.Address, 'nursery_free') +NURSERY_TOP = rthread.ThreadLocalField(llmemory.Address, 'nursery_top') +NEXT_NUBLOCK = rthread.ThreadLocalField(llmemory.Address, 'next_nublock') + # class IncrementalMiniMarkGC(MovingGCBase): @@ -263,10 +268,19 @@ "card_page_indices": 128, # Objects whose total size is at least 'large_object' bytes are -# allocated out of the nursery immediately, as old objects. The -# minimal allocated size of the nursery is 2x the following -# number (by default, at least 132KB on 32-bit and 264KB on 64-bit). -"large_object": (16384+512)*WORD, +# allocated out of the nursery immediately, as old objects. +"large_object": 26000, + +# Thread-local Block size: the nursery is divided into blocks of +# at most this size each, and allocations go on in a +# thread-local manner inside each block. "large_object" must be +# significantly smaller, but at the same time the total nursery +# size must be many times bigger than "tl_block_size"; the minimum +# allocated nursery size is 2 times "tl_block_size". +# "cache_line_min" is used to round the actual thread-local +# blocks to a cache line, to avoid pointless cache conflicts. +"tl_block_size": 65536, +"cache_line_min": 256, } def __init__(self, config, @@ -280,6 +294,8 @@ growth_rate_max=2.5, # for tests card_page_indices=0, large_object=8*WORD, + tl_block_size=9*WORD, + cache_line_min=1*WORD, ArenaCollectionClass=None, **kwds): "NOT_RPYTHON" @@ -307,10 +323,12 @@ # 'large_object' limit how big objects can be in the nursery, so # it gives a lower bound on the allowed size of the nursery. self.nonlarge_max = large_object - 1 +self.tl_block_size = tl_block_size +self.cache_line_min = cache_line_min # self.nursery = llmemory.NULL -self.nursery_free = llmemory.NULL -self.nursery_top = llmemory.NULL +self.nublocks = llmemory.NULL # <= linked list of threadlocal_base + # for all active nursery consumers self.debug_tiny_nursery = -1 self.debug_rotating_nurseries = lltype.nullptr(NURSARRAY) self.extra_threshold = 0 @@ -431,7 +449,7 @@ else: # defaultsize = self.nursery_size -minsize = 2 * (self.nonlarge_max + 1) +minsize = 2 * self.tl_block_size self.nursery_size = minsize self.allocate_nursery() # @@ -507,6 +525,13 @@ # Estimate this number conservatively bigobj = self.nonlarge_max + 1 self.max_number_of_pinned_objects = self.nursery_size / (bigobj * 2) +# +# Round up +ll_assert((self.cache_line_min & (self.cache_line_min - 1)) == 0, + "cache_line_min is not a power a two") +self.tl_block_size = ((self.tl_block_size + self.cache_line_min - 1) + & ~(self.cache_line_min - 1)) + def _nursery_memory_size(self): extra = self.nonlarge_max + 1 @@ -526,10 +551,6 @@ debug_start("gc-set-nursery-size") debug_print("nursery size:", self.nursery_size) self.nursery = self._alloc_nursery() -# the current position in the nursery: -self.nursery_free = self.nursery -# the end of the nursery: -self.nursery_top = self.nursery + self.nursery_size # initialize the threshold self.min_heap_size = max(self.min_heap_size, self.nursery_size * self.major_collection_threshold) @@ -602,12 +623,27 @@ #
[pypy-commit] pypy py3.5-text-utf8: close branch
Author: Richard PlanggerBranch: py3.5-text-utf8 Changeset: r90417:136caa31d4f8 Date: 2017-02-28 11:43 +0100 http://bitbucket.org/pypy/pypy/changeset/136caa31d4f8/ Log:close branch ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: merge heads
Author: Richard PlanggerBranch: py3.5 Changeset: r90416:38f6842e3229 Date: 2017-02-28 11:39 +0100 http://bitbucket.org/pypy/pypy/changeset/38f6842e3229/ Log:merge heads diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py --- a/pypy/objspace/std/typeobject.py +++ b/pypy/objspace/std/typeobject.py @@ -631,7 +631,7 @@ if w_newdescr is None:# see test_crash_mro_without_object_1 raise oefmt(space.w_TypeError, "cannot create '%N' instances", self) -w_newfunc = space.get(w_newdescr, self) +w_newfunc = space.get(w_newdescr, space.w_None, w_type=self) if (space.config.objspace.std.newshortcut and not we_are_jitted() and isinstance(w_newtype, W_TypeObject)): diff --git a/pypy/objspace/test/test_descriptor.py b/pypy/objspace/test/test_descriptor.py --- a/pypy/objspace/test/test_descriptor.py +++ b/pypy/objspace/test/test_descriptor.py @@ -152,3 +152,13 @@ assert hash(myfloat(-1.0)) == -2 assert hash(myHashClass()) == -2 assert hash(myHashClass3()) == hash(-10**100) + +def test_descr_funny_new(self): +class C(object): +@classmethod +def __new__(*args): +return args + +assert C.__new__(1,2) == (C, 1, 2) +assert C(1,2) == (C, C, 1, 2) + ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: document branch
Author: Richard PlanggerBranch: py3.5 Changeset: r90415:51f8b20c486b Date: 2017-02-28 11:38 +0100 http://bitbucket.org/pypy/pypy/changeset/51f8b20c486b/ Log:document branch 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 @@ -172,3 +172,7 @@ .. branch: fix_bool_restype Fix for ``ctypes.c_bool``-returning ctypes functions + +.. branch: py3.5-text-utf8 + +space.text_w now encodes to utf-8 not preserving surrogates. ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: (ronan, plan_rich) fix descriptor invocation inside the descr_call of W_TypeObject
Author: Richard PlanggerBranch: py3.5 Changeset: r90413:411407ffbeac Date: 2017-02-27 18:55 +0100 http://bitbucket.org/pypy/pypy/changeset/411407ffbeac/ Log:(ronan, plan_rich) fix descriptor invocation inside the descr_call of W_TypeObject diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py --- a/pypy/objspace/std/typeobject.py +++ b/pypy/objspace/std/typeobject.py @@ -631,7 +631,7 @@ if w_newdescr is None:# see test_crash_mro_without_object_1 raise oefmt(space.w_TypeError, "cannot create '%N' instances", self) -w_newfunc = space.get(w_newdescr, self) +w_newfunc = space.get(w_newdescr, space.w_None, w_type=self) if (space.config.objspace.std.newshortcut and not we_are_jitted() and isinstance(w_newtype, W_TypeObject)): diff --git a/pypy/objspace/test/test_descriptor.py b/pypy/objspace/test/test_descriptor.py --- a/pypy/objspace/test/test_descriptor.py +++ b/pypy/objspace/test/test_descriptor.py @@ -152,3 +152,13 @@ assert hash(myfloat(-1.0)) == -2 assert hash(myHashClass()) == -2 assert hash(myHashClass3()) == hash(-10**100) + +def test_descr_funny_new(self): +class C(object): +@classmethod +def __new__(*args): +return args + +assert C.__new__(1,2) == (C, 1, 2) +assert C(1,2) == (C, C, 1, 2) + ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: merge py3.5-text-utf8
Author: Richard PlanggerBranch: py3.5 Changeset: r90414:ee44cdf8b435 Date: 2017-02-28 11:36 +0100 http://bitbucket.org/pypy/pypy/changeset/ee44cdf8b435/ Log:merge py3.5-text-utf8 diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py --- a/pypy/module/imp/importing.py +++ b/pypy/module/imp/importing.py @@ -67,7 +67,7 @@ lib_pypy = os.path.join(os.path.dirname(__file__), '..', '..', '..', 'lib_pypy') -@unwrap_spec(modulename='text0', level=int) +@unwrap_spec(modulename='fsencode', level=int) def importhook(space, modulename, w_globals=None, w_locals=None, w_fromlist=None, level=0): # A minimal version, that can only import builtin and lib_pypy modules! assert w_locals is w_globals diff --git a/pypy/module/imp/interp_imp.py b/pypy/module/imp/interp_imp.py --- a/pypy/module/imp/interp_imp.py +++ b/pypy/module/imp/interp_imp.py @@ -5,6 +5,7 @@ from pypy.interpreter.pycode import PyCode from pypy.module._io.interp_iobase import W_IOBase from pypy.interpreter.streamutil import wrap_streamerror +from pypy.interpreter.error import OperationError def extension_suffixes(space): @@ -72,7 +73,11 @@ return None def is_builtin(space, w_name): -name = space.text0_w(w_name) +try: +name = space.text0_w(w_name) +except OperationError: +return space.newint(0) + if name not in space.builtin_modules: return space.newint(0) if space.finditem(space.sys.get('modules'), w_name) is not None: diff --git a/pypy/module/imp/test/test_import.py b/pypy/module/imp/test/test_import.py --- a/pypy/module/imp/test/test_import.py +++ b/pypy/module/imp/test/test_import.py @@ -255,6 +255,10 @@ def test_import_keywords(self): __import__(name='sys', level=0) +def test_import_nonutf8_encodable(self): +exc = raises(ImportError, __import__, '\ud800') +assert exc.value.args[0].startswith("No module named ") + def test_import_by_filename(self): import pkg.a filename = pkg.a.__file__ diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py --- a/pypy/objspace/std/test/test_unicodeobject.py +++ b/pypy/objspace/std/test/test_unicodeobject.py @@ -35,8 +35,7 @@ w_uni = space.wrap(u'abcd') assert space.text_w(w_uni) == 'abcd' w_uni = space.wrap(unichr(0xd921) + unichr(0x)) -assert space.text_w(w_uni) == '\xed\xa4\xa1\xed\xb7\x9d' -# ^^^ and not the 4-bytes combined character +raises(UnicodeEncodeError, space.text_w, w_uni) class AppTestUnicodeStringStdOnly: diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py --- a/pypy/objspace/std/unicodeobject.py +++ b/pypy/objspace/std/unicodeobject.py @@ -8,7 +8,7 @@ from rpython.rlib.runicode import ( make_unicode_escape_function, str_decode_ascii, str_decode_utf_8, unicode_encode_ascii, unicode_encode_utf_8, fast_str_decode_ascii, -unicode_encode_utf8sp) +unicode_encode_utf8_forbid_surrogates, SurrogateError) from rpython.rlib import jit from pypy.interpreter import unicodehelper @@ -81,8 +81,16 @@ return self._value def text_w(self, space): -identifier = jit.conditional_call_elidable( -self._utf8, g_encode_utf8, self._value) +try: +identifier = jit.conditional_call_elidable( +self._utf8, g_encode_utf8, self._value) +except SurrogateError as e: +raise OperationError(space.w_UnicodeEncodeError, +space.newtuple([space.newtext('utf-8'), +self, +space.newint(e.index-1), +space.newint(e.index), +space.newtext("surrogates not allowed")])) if not jit.isconstant(self): self._utf8 = identifier return identifier @@ -1257,7 +1265,7 @@ @jit.elidable def g_encode_utf8(value): """This is a global function because of jit.conditional_call_value""" -return unicode_encode_utf8sp(value, len(value)) +return unicode_encode_utf8_forbid_surrogates(value, len(value)) _repr_function, _ = make_unicode_escape_function( pass_printable=True, unicode_output=True, quotes=True, prefix='') diff --git a/rpython/rlib/runicode.py b/rpython/rlib/runicode.py --- a/rpython/rlib/runicode.py +++ b/rpython/rlib/runicode.py @@ -433,7 +433,9 @@ return result.build() class SurrogateError(Exception): -pass +def __init__(self, char, index): +self.char = char +self.index = index def unicode_encode_utf8_forbid_surrogates(s, size): # Strict surrogate-forbidding utf-8 encoding. Any surrogate character @@ -454,7 +456,7 @@ result.append(chr((0x80 | (ch & 0x3f elif ch <
[pypy-commit] pypy py3.5-fix-globals: (stevie, robert-zaremba) Fix symtable for nonlocal
Author: Robert ZarembaBranch: py3.5-fix-globals Changeset: r90411:802f8b2e090c Date: 2017-02-27 17:56 +0100 http://bitbucket.org/pypy/pypy/changeset/802f8b2e090c/ Log:(stevie, robert-zaremba) Fix symtable for nonlocal Added tests and updated functionality for symtable construction for nonlocal declarations. diff --git a/pypy/interpreter/astcompiler/symtable.py b/pypy/interpreter/astcompiler/symtable.py --- a/pypy/interpreter/astcompiler/symtable.py +++ b/pypy/interpreter/astcompiler/symtable.py @@ -8,7 +8,7 @@ # These are for internal use only: SYM_BLANK = 0 SYM_GLOBAL = 1 -SYM_ASSIGNED = 2 # Or deleted actually. +SYM_ASSIGNED = 2 # (DEF_LOCAL in CPython3). Or deleted actually. SYM_PARAM = 2 << 1 SYM_NONLOCAL = 2 << 2 SYM_USED = 2 << 3 @@ -123,9 +123,6 @@ def _finalize_name(self, name, flags, local, bound, free, globs): """Decide on the scope of a name.""" if flags & SYM_GLOBAL: -if flags & SYM_NONLOCAL: -err = "name '%s' is nonlocal and global" % (name,) -raise SyntaxError(err, self.lineno, self.col_offset) self.symbols[name] = SCOPE_GLOBAL_EXPLICIT globs[name] = None if bound: @@ -134,12 +131,6 @@ except KeyError: pass elif flags & SYM_NONLOCAL: -if flags & SYM_PARAM: -err = "name '%s' is parameter and nonlocal" % (name,) -raise SyntaxError(err, self.lineno, self.col_offset) -if bound is None: -err = "nonlocal declaration not allowed at module level" -raise SyntaxError(err, self.lineno, self.col_offset) if name not in bound: err = "no binding for nonlocal '%s' found" % (name,) raise SyntaxError(err, self.lineno, self.col_offset) @@ -497,6 +488,9 @@ if old_role & SYM_PARAM: msg = "name '%s' is parameter and global" % (name,) raise SyntaxError(msg, glob.lineno, glob.col_offset) +if old_role & SYM_NONLOCAL: +msg = "name '%s' is nonlocal and global" % (name,) +raise SyntaxError(msg, glob.lineno, glob.col_offset) if old_role & (SYM_USED | SYM_ASSIGNED): if old_role & SYM_ASSIGNED: @@ -513,6 +507,16 @@ def visit_Nonlocal(self, nonl): for name in nonl.names: old_role = self.scope.lookup_role(name) +msg = "" +if old_role & SYM_GLOBAL: +msg = "name '%s' is nonlocal and global" % (name,) +if old_role & SYM_PARAM: +msg = "name '%s' is parameter and nonlocal" % (name,) +if type(self.scope) == ModuleScope: +msg = "nonlocal declaration not allowed at module level" +if msg is not "": +raise SyntaxError(msg, nonl.lineno, nonl.col_offset) + if (old_role & (SYM_USED | SYM_ASSIGNED) and not (name == '__class__' and self.scope._hide_bound_from_nested_scopes)): @@ -525,6 +529,7 @@ misc.syntax_warning(self.space, msg, self.compile_info.filename, nonl.lineno, nonl.col_offset) + self.note_symbol(name, SYM_NONLOCAL) def visit_Lambda(self, lamb): diff --git a/pypy/interpreter/astcompiler/test/test_symtable.py b/pypy/interpreter/astcompiler/test/test_symtable.py --- a/pypy/interpreter/astcompiler/test/test_symtable.py +++ b/pypy/interpreter/astcompiler/test/test_symtable.py @@ -295,17 +295,17 @@ assert xscp.lookup("y") == symtable.SCOPE_GLOBAL_EXPLICIT assert zscp.lookup("y") == symtable.SCOPE_FREE -code = "def f(x):\n global x" -exc = py.test.raises(SyntaxError, self.func_scope, code).value +src = "def f(x):\n global x" +exc = py.test.raises(SyntaxError, self.func_scope, src).value assert exc.lineno == 2 assert exc.msg == "name 'x' is parameter and global" def test_global_nested(self): -code = """ +src = """ def f(x): def g(x): global x""" -exc = py.test.raises(SyntaxError, self.func_scope, code).value +exc = py.test.raises(SyntaxError, self.func_scope, src).value assert exc.lineno == 4 assert exc.msg == "name 'x' is parameter and global" @@ -319,14 +319,13 @@ assert x == symtable.SYM_GLOBAL def test_nonlocal(self): -src = str(py.code.Source(""" - def f(): - nonlocal x - global x - """)) +src = """ +x = 1 +def f(): +nonlocal x""" exc = py.test.raises(SyntaxError, self.func_scope, src).value -assert exc.msg == "name 'x' is nonlocal and global" -# +assert
[pypy-commit] pypy py3.5: Merged in robert-zaremba/pypy/py3.5-fix-globals (pull request #521)
Author: Ronan LamyBranch: py3.5 Changeset: r90412:0436a099e10a Date: 2017-02-28 09:58 + http://bitbucket.org/pypy/pypy/changeset/0436a099e10a/ Log:Merged in robert-zaremba/pypy/py3.5-fix-globals (pull request #521) (stevie, robert-zaremba) Approved-by: Richard Plangger diff --git a/pypy/interpreter/astcompiler/symtable.py b/pypy/interpreter/astcompiler/symtable.py --- a/pypy/interpreter/astcompiler/symtable.py +++ b/pypy/interpreter/astcompiler/symtable.py @@ -8,7 +8,7 @@ # These are for internal use only: SYM_BLANK = 0 SYM_GLOBAL = 1 -SYM_ASSIGNED = 2 # Or deleted actually. +SYM_ASSIGNED = 2 # (DEF_LOCAL in CPython3). Or deleted actually. SYM_PARAM = 2 << 1 SYM_NONLOCAL = 2 << 2 SYM_USED = 2 << 3 @@ -123,12 +123,6 @@ def _finalize_name(self, name, flags, local, bound, free, globs): """Decide on the scope of a name.""" if flags & SYM_GLOBAL: -if flags & SYM_PARAM: -err = "name '%s' is parameter and global" % (name,) -raise SyntaxError(err, self.lineno, self.col_offset) -if flags & SYM_NONLOCAL: -err = "name '%s' is nonlocal and global" % (name,) -raise SyntaxError(err, self.lineno, self.col_offset) self.symbols[name] = SCOPE_GLOBAL_EXPLICIT globs[name] = None if bound: @@ -137,12 +131,6 @@ except KeyError: pass elif flags & SYM_NONLOCAL: -if flags & SYM_PARAM: -err = "name '%s' is parameter and nonlocal" % (name,) -raise SyntaxError(err, self.lineno, self.col_offset) -if bound is None: -err = "nonlocal declaration not allowed at module level" -raise SyntaxError(err, self.lineno, self.col_offset) if name not in bound: err = "no binding for nonlocal '%s' found" % (name,) raise SyntaxError(err, self.lineno, self.col_offset) @@ -293,7 +281,8 @@ def _pass_on_bindings(self, local, bound, globs, new_bound, new_globs): new_bound.update(local) -Scope._pass_on_bindings(self, local, bound, globs, new_bound, new_globs) +Scope._pass_on_bindings(self, local, bound, globs, new_bound, +new_globs) def _finalize_cells(self, free): for name, role in self.symbols.iteritems(): @@ -496,20 +485,38 @@ "implemented in PyPy") raise SyntaxError(msg, glob.lineno, glob.col_offset, filename=self.compile_info.filename) +if old_role & SYM_PARAM: +msg = "name '%s' is parameter and global" % (name,) +raise SyntaxError(msg, glob.lineno, glob.col_offset) +if old_role & SYM_NONLOCAL: +msg = "name '%s' is nonlocal and global" % (name,) +raise SyntaxError(msg, glob.lineno, glob.col_offset) + if old_role & (SYM_USED | SYM_ASSIGNED): if old_role & SYM_ASSIGNED: -msg = "name '%s' is assigned to before global declaration" \ +msg = "name '%s' is assigned to before global declaration"\ % (name,) else: msg = "name '%s' is used prior to global declaration" % \ (name,) -misc.syntax_warning(self.space, msg, self.compile_info.filename, +misc.syntax_warning(self.space, msg, +self.compile_info.filename, glob.lineno, glob.col_offset) self.note_symbol(name, SYM_GLOBAL) def visit_Nonlocal(self, nonl): for name in nonl.names: old_role = self.scope.lookup_role(name) +msg = "" +if old_role & SYM_GLOBAL: +msg = "name '%s' is nonlocal and global" % (name,) +if old_role & SYM_PARAM: +msg = "name '%s' is parameter and nonlocal" % (name,) +if type(self.scope) == ModuleScope: +msg = "nonlocal declaration not allowed at module level" +if msg is not "": +raise SyntaxError(msg, nonl.lineno, nonl.col_offset) + if (old_role & (SYM_USED | SYM_ASSIGNED) and not (name == '__class__' and self.scope._hide_bound_from_nested_scopes)): @@ -519,8 +526,10 @@ else: msg = "name '%s' is used prior to nonlocal declaration" % \ (name,) -misc.syntax_warning(self.space, msg, self.compile_info.filename, +misc.syntax_warning(self.space, msg, +self.compile_info.filename, nonl.lineno, nonl.col_offset) +
[pypy-commit] pypy py3.5-fix-globals: (stevie, robert-zaremba)
Author: Robert ZarembaBranch: py3.5-fix-globals Changeset: r90410:baf2561c870c Date: 2017-02-27 13:36 +0100 http://bitbucket.org/pypy/pypy/changeset/baf2561c870c/ Log:(stevie, robert-zaremba) Test and fix global variable reporting error. diff --git a/pypy/interpreter/astcompiler/symtable.py b/pypy/interpreter/astcompiler/symtable.py --- a/pypy/interpreter/astcompiler/symtable.py +++ b/pypy/interpreter/astcompiler/symtable.py @@ -8,7 +8,7 @@ # These are for internal use only: SYM_BLANK = 0 SYM_GLOBAL = 1 -SYM_ASSIGNED = 2 # Or deleted actually. +SYM_ASSIGNED = 2 # Or deleted actually. SYM_PARAM = 2 << 1 SYM_NONLOCAL = 2 << 2 SYM_USED = 2 << 3 @@ -123,9 +123,6 @@ def _finalize_name(self, name, flags, local, bound, free, globs): """Decide on the scope of a name.""" if flags & SYM_GLOBAL: -if flags & SYM_PARAM: -err = "name '%s' is parameter and global" % (name,) -raise SyntaxError(err, self.lineno, self.col_offset) if flags & SYM_NONLOCAL: err = "name '%s' is nonlocal and global" % (name,) raise SyntaxError(err, self.lineno, self.col_offset) @@ -293,7 +290,8 @@ def _pass_on_bindings(self, local, bound, globs, new_bound, new_globs): new_bound.update(local) -Scope._pass_on_bindings(self, local, bound, globs, new_bound, new_globs) +Scope._pass_on_bindings(self, local, bound, globs, new_bound, +new_globs) def _finalize_cells(self, free): for name, role in self.symbols.iteritems(): @@ -496,14 +494,19 @@ "implemented in PyPy") raise SyntaxError(msg, glob.lineno, glob.col_offset, filename=self.compile_info.filename) +if old_role & SYM_PARAM: +msg = "name '%s' is parameter and global" % (name,) +raise SyntaxError(msg, glob.lineno, glob.col_offset) + if old_role & (SYM_USED | SYM_ASSIGNED): if old_role & SYM_ASSIGNED: -msg = "name '%s' is assigned to before global declaration" \ +msg = "name '%s' is assigned to before global declaration"\ % (name,) else: msg = "name '%s' is used prior to global declaration" % \ (name,) -misc.syntax_warning(self.space, msg, self.compile_info.filename, +misc.syntax_warning(self.space, msg, +self.compile_info.filename, glob.lineno, glob.col_offset) self.note_symbol(name, SYM_GLOBAL) @@ -519,7 +522,8 @@ else: msg = "name '%s' is used prior to nonlocal declaration" % \ (name,) -misc.syntax_warning(self.space, msg, self.compile_info.filename, +misc.syntax_warning(self.space, msg, +self.compile_info.filename, nonl.lineno, nonl.col_offset) self.note_symbol(name, SYM_NONLOCAL) @@ -589,7 +593,7 @@ def visit_arguments(self, arguments): scope = self.scope -assert isinstance(scope, FunctionScope) # Annotator hint. +assert isinstance(scope, FunctionScope) # Annotator hint. if arguments.args: self._handle_params(arguments.args, True) if arguments.kwonlyargs: diff --git a/pypy/interpreter/astcompiler/test/test_symtable.py b/pypy/interpreter/astcompiler/test/test_symtable.py --- a/pypy/interpreter/astcompiler/test/test_symtable.py +++ b/pypy/interpreter/astcompiler/test/test_symtable.py @@ -283,7 +283,6 @@ def test_global(self): scp = self.func_scope("def f():\n global x\n x = 4") assert scp.lookup("x") == symtable.SCOPE_GLOBAL_EXPLICIT -input = "def f(x):\n global x" scp = self.func_scope("""def f(): y = 3 def x(): @@ -295,9 +294,30 @@ xscp, zscp = scp.children assert xscp.lookup("y") == symtable.SCOPE_GLOBAL_EXPLICIT assert zscp.lookup("y") == symtable.SCOPE_FREE -exc = py.test.raises(SyntaxError, self.func_scope, input).value + +code = "def f(x):\n global x" +exc = py.test.raises(SyntaxError, self.func_scope, code).value +assert exc.lineno == 2 assert exc.msg == "name 'x' is parameter and global" +def test_global_nested(self): +code = """ +def f(x): +def g(x): +global x""" +exc = py.test.raises(SyntaxError, self.func_scope, code).value +assert exc.lineno == 4 +assert exc.msg == "name 'x' is parameter and global" + +scp = self.func_scope(""" +def f(x): +def g(): +global x""") +g = scp.children[0] +assert g.name
[pypy-commit] cffi default: Document more explicitly the difference between CompiledFFI and FFI.
Author: Armin RigoBranch: Changeset: r2895:46f49821e351 Date: 2017-02-28 09:10 +0100 http://bitbucket.org/cffi/cffi/changeset/46f49821e351/ Log:Document more explicitly the difference between CompiledFFI and FFI. diff --git a/doc/source/ref.rst b/doc/source/ref.rst --- a/doc/source/ref.rst +++ b/doc/source/ref.rst @@ -8,6 +8,14 @@ FFI Interface - +*This page documents the runtime interface of the two types "FFI" and +"CompiledFFI". These two types are very similar to each other. You get +a CompiledFFI object if you import an out-of-line module. You get a FFI +object from explicitly writing cffi.FFI(). Unlike CompiledFFI, the type +FFI has also got additional methods documented on the* `next page`__. + +.. __: cdef.html + ffi.NULL ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit