[pypy-commit] pypy.org extradoc: update the values

2017-02-28 Thread arigo
Author: Armin Rigo 
Branch: 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

2017-02-28 Thread antocuni
Author: Antonio Cuni 
Branch: 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

2017-02-28 Thread antocuni
Author: Antonio Cuni 
Branch: 
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

2017-02-28 Thread antocuni
Author: Antonio Cuni 
Branch: 
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.

2017-02-28 Thread robert-zaremba
Author: Robert Zaremba 
Branch: 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

2017-02-28 Thread arigo
Author: Armin Rigo 
Branch: 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)

2017-02-28 Thread arigo
Author: Armin Rigo 
Branch: 
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

2017-02-28 Thread arigo
Author: Armin Rigo 
Branch: 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

2017-02-28 Thread arigo
Author: Armin Rigo 
Branch: 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)

2017-02-28 Thread robert-zaremba
Author: Robert Zaremba 
Branch: 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

2017-02-28 Thread robert-zaremba
Author: Robert Zaremba 
Branch: 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)

2017-02-28 Thread rlamy
Author: Ronan Lamy 
Branch: 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

2017-02-28 Thread arigo
Author: Armin Rigo 
Branch: 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

2017-02-28 Thread cfbolz
Author: Carl Friedrich Bolz 
Branch: 
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

2017-02-28 Thread arigo
Author: Armin Rigo 
Branch: 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

2017-02-28 Thread arigo
Author: Armin Rigo 
Branch: 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

2017-02-28 Thread arigo
Author: Armin Rigo 
Branch: 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

2017-02-28 Thread plan_rich
Author: Richard Plangger 
Branch: 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

2017-02-28 Thread plan_rich
Author: Richard Plangger 
Branch: 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

2017-02-28 Thread plan_rich
Author: Richard Plangger 
Branch: 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

2017-02-28 Thread plan_rich
Author: Richard Plangger 
Branch: 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

2017-02-28 Thread plan_rich
Author: Richard Plangger 
Branch: 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

2017-02-28 Thread robert-zaremba
Author: Robert Zaremba 
Branch: 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)

2017-02-28 Thread rlamy
Author: Ronan Lamy 
Branch: 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)

2017-02-28 Thread robert-zaremba
Author: Robert Zaremba 
Branch: 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.

2017-02-28 Thread arigo
Author: Armin Rigo 
Branch: 
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