[pypy-commit] pypy py3.7: merge py3.6

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: py3.7
Changeset: r98611:d024eab5de59
Date: 2020-01-31 14:07 +0100
http://bitbucket.org/pypy/pypy/changeset/d024eab5de59/

Log:merge py3.6

diff --git a/pypy/module/mmap/interp_mmap.py b/pypy/module/mmap/interp_mmap.py
--- a/pypy/module/mmap/interp_mmap.py
+++ b/pypy/module/mmap/interp_mmap.py
@@ -190,8 +190,10 @@
 return space.newbytes(self.mmap.getslice(start, length))
 else:
 b = StringBuilder(length)
-for i in range(start, stop, step):
-b.append(self.mmap.getitem(i))
+index = start
+for i in range(length):
+b.append(self.mmap.getitem(index))
+index += step
 return space.newbytes(b.build())
 
 def descr_setitem(self, w_index, w_value):
diff --git a/pypy/module/mmap/test/test_mmap.py 
b/pypy/module/mmap/test/test_mmap.py
--- a/pypy/module/mmap/test/test_mmap.py
+++ b/pypy/module/mmap/test/test_mmap.py
@@ -431,6 +431,15 @@
 m.close()
 f.close()
 
+def test_get_crash(self):
+import sys
+from mmap import mmap
+s = b'hallo!!!'
+m = mmap(-1, len(s))
+m[:] = s
+assert m[1:None:sys.maxsize] == b'a'
+m.close()
+
 def test_set_item(self):
 import mmap
 
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy py3.6: merge default

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: py3.6
Changeset: r98610:f0843db5a3a6
Date: 2020-01-31 14:06 +0100
http://bitbucket.org/pypy/pypy/changeset/f0843db5a3a6/

Log:merge default

diff --git a/pypy/module/mmap/interp_mmap.py b/pypy/module/mmap/interp_mmap.py
--- a/pypy/module/mmap/interp_mmap.py
+++ b/pypy/module/mmap/interp_mmap.py
@@ -190,8 +190,10 @@
 return space.newbytes(self.mmap.getslice(start, length))
 else:
 b = StringBuilder(length)
-for i in range(start, stop, step):
-b.append(self.mmap.getitem(i))
+index = start
+for i in range(length):
+b.append(self.mmap.getitem(index))
+index += step
 return space.newbytes(b.build())
 
 def descr_setitem(self, w_index, w_value):
diff --git a/pypy/module/mmap/test/test_mmap.py 
b/pypy/module/mmap/test/test_mmap.py
--- a/pypy/module/mmap/test/test_mmap.py
+++ b/pypy/module/mmap/test/test_mmap.py
@@ -431,6 +431,15 @@
 m.close()
 f.close()
 
+def test_get_crash(self):
+import sys
+from mmap import mmap
+s = b'hallo!!!'
+m = mmap(-1, len(s))
+m[:] = s
+assert m[1:None:sys.maxsize] == b'a'
+m.close()
+
 def test_set_item(self):
 import mmap
 
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy py3.6: merge default

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: py3.6
Changeset: r98605:0115587c02f4
Date: 2020-01-30 14:45 +0100
http://bitbucket.org/pypy/pypy/changeset/0115587c02f4/

Log:merge default

diff --git a/pypy/objspace/std/newformat.py b/pypy/objspace/std/newformat.py
--- a/pypy/objspace/std/newformat.py
+++ b/pypy/objspace/std/newformat.py
@@ -802,7 +802,7 @@
 digits = self._upcase_string(digits)
 out.append(digits)
 if spec.n_decimal:
-out.append(self._lit(".")[0])
+out.append(self._lit(self._loc_dec)[0])
 if spec.n_remainder:
 out.append(num[to_remainder:])
 if spec.n_rpadding:
diff --git a/pypy/objspace/std/test/test_newformat.py 
b/pypy/objspace/std/test/test_newformat.py
--- a/pypy/objspace/std/test/test_newformat.py
+++ b/pypy/objspace/std/test/test_newformat.py
@@ -404,6 +404,24 @@
 finally:
 locale.setlocale(locale.LC_NUMERIC, 'C')
 
+def test_locale_german(self):
+import locale
+for name in ['de_DE', 'de_DE.utf8']:
+try:
+locale.setlocale(locale.LC_NUMERIC, name)
+break
+except locale.Error:
+pass
+else:
+skip("no german locale")
+x = 1234.567890
+try:
+assert locale.format('%g', x, grouping=True) == '1.234,57'
+assert format(x, 'n') == '1.234,57'
+assert format(12345678901234, 'n') == '12.345.678.901.234'
+finally:
+locale.setlocale(locale.LC_NUMERIC, 'C')
+
 def test_dont_switch_to_g(self):
 skip("must fix when float formatting is figured out")
 assert len(format(1.1234e90, "f")) == 98
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy py3.7: make get/set_coroutine_wrapper emit a DeprecationWarning

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: py3.7
Changeset: r98607:66293dfd6fd3
Date: 2020-01-30 15:41 +0100
http://bitbucket.org/pypy/pypy/changeset/66293dfd6fd3/

Log:make get/set_coroutine_wrapper emit a DeprecationWarning

diff --git a/pypy/interpreter/test/apptest_coroutine.py 
b/pypy/interpreter/test/apptest_coroutine.py
--- a/pypy/interpreter/test/apptest_coroutine.py
+++ b/pypy/interpreter/test/apptest_coroutine.py
@@ -123,6 +123,18 @@
 sys.set_coroutine_wrapper(None)
 assert sys.get_coroutine_wrapper() is None
 
+def test_get_set_coroutine_wrapper_deprecated():
+import warnings
+def my_wrapper(cr):
+return 1
+with warnings.catch_warnings(record=True) as l:
+warnings.simplefilter('always', category=DeprecationWarning)
+sys.get_coroutine_wrapper()
+sys.set_coroutine_wrapper(my_wrapper)
+sys.set_coroutine_wrapper(None)
+print(l)
+assert len(l) == 3
+
 def test_async_with():
 seen = []
 class X:
diff --git a/pypy/module/sys/vm.py b/pypy/module/sys/vm.py
--- a/pypy/module/sys/vm.py
+++ b/pypy/module/sys/vm.py
@@ -343,12 +343,14 @@
 
 def get_coroutine_wrapper(space):
 "Return the wrapper for coroutine objects set by 
sys.set_coroutine_wrapper."
+space.warn(space.newtext("get_coroutine_wrapper is deprecated"), 
space.w_DeprecationWarning)
 ec = space.getexecutioncontext()
 if ec.w_coroutine_wrapper_fn is None:
 return space.w_None
 return ec.w_coroutine_wrapper_fn
 
 def set_coroutine_wrapper(space, w_wrapper):
+space.warn(space.newtext("set_coroutine_wrapper is deprecated"), 
space.w_DeprecationWarning)
 "Set a wrapper for coroutine objects."
 ec = space.getexecutioncontext()
 if space.is_w(w_wrapper, space.w_None):
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy py3.7: only async *generator* expressions should work, not other comprehensions!

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: py3.7
Changeset: r98608:30f0db9aea2b
Date: 2020-01-30 16:00 +0100
http://bitbucket.org/pypy/pypy/changeset/30f0db9aea2b/

Log:only async *generator* expressions should work, not other
comprehensions!

diff --git a/pypy/interpreter/astcompiler/codegen.py 
b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -1567,7 +1567,11 @@
 def _compile_comprehension(self, node, name, sub_scope):
 is_async_function = self.scope.is_coroutine
 code, qualname = self.sub_scope(sub_scope, name, node, node.lineno)
-is_async_generator = self.symbols.find_scope(node).is_coroutine
+is_async_comprehension = self.symbols.find_scope(node).is_coroutine
+if is_async_comprehension and not is_async_function:
+if not isinstance(node, ast.GeneratorExp):
+self.error("asynchronous comprehension outside of "
+   "an asynchronous function", node)
 
 self.update_position(node.lineno)
 self._make_function(code, qualname=qualname)
@@ -1581,7 +1585,7 @@
 else:
 self.emit_op(ops.GET_ITER)
 self.emit_op_arg(ops.CALL_FUNCTION, 1)
-if is_async_generator and sub_scope is not GenExpCodeGenerator:
+if is_async_comprehension and sub_scope is not GenExpCodeGenerator:
 self.emit_op(ops.GET_AWAITABLE)
 self.load_const(self.space.w_None)
 self.emit_op(ops.YIELD_FROM)
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py 
b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -1231,6 +1231,33 @@
 """
 e = py.test.raises(SyntaxError, self.simple_test, source, "None", None)
 
+def test_async_in_nested(self):
+source = """if 1:
+async def foo():
+def bar():
+[i async for i in items]
+"""
+e = py.test.raises(SyntaxError, self.simple_test, source, "None", None)
+source = """if 1:
+async def foo():
+def bar():
+{i async for i in items}
+"""
+e = py.test.raises(SyntaxError, self.simple_test, source, "None", None)
+source = """if 1:
+async def foo():
+def bar():
+{i: i+1 async for i in items}
+"""
+e = py.test.raises(SyntaxError, self.simple_test, source, "None", None)
+source = """if 1:
+async def foo():
+def bar():
+(i async for i in items)
+"""
+# ok!
+self.simple_test(source, "None", None)
+
 def test_load_classderef(self):
 source = """if 1:
 def f():
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy py3.7: merge py3.6

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: py3.7
Changeset: r98606:c5c4cd76ef44
Date: 2020-01-30 14:45 +0100
http://bitbucket.org/pypy/pypy/changeset/c5c4cd76ef44/

Log:merge py3.6

diff --git a/pypy/objspace/std/newformat.py b/pypy/objspace/std/newformat.py
--- a/pypy/objspace/std/newformat.py
+++ b/pypy/objspace/std/newformat.py
@@ -802,7 +802,7 @@
 digits = self._upcase_string(digits)
 out.append(digits)
 if spec.n_decimal:
-out.append(self._lit(".")[0])
+out.append(self._lit(self._loc_dec)[0])
 if spec.n_remainder:
 out.append(num[to_remainder:])
 if spec.n_rpadding:
diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py
--- a/pypy/objspace/std/setobject.py
+++ b/pypy/objspace/std/setobject.py
@@ -247,10 +247,16 @@
 return space.w_NotImplemented
 return self.difference(w_other)
 
+def descr_rsub(self, space, w_other):
+if not isinstance(w_other, W_BaseSetObject):
+return space.w_NotImplemented
+return w_other.difference(self)
+
 def descr_and(self, space, w_other):
 if not isinstance(w_other, W_BaseSetObject):
 return space.w_NotImplemented
 return self.intersect(w_other)
+descr_rand = descr_and # symmetric
 
 def descr_or(self, space, w_other):
 if not isinstance(w_other, W_BaseSetObject):
@@ -258,11 +264,13 @@
 w_copy = self.copy_real()
 w_copy.update(w_other)
 return w_copy
+descr_ror = descr_or # symmetric
 
 def descr_xor(self, space, w_other):
 if not isinstance(w_other, W_BaseSetObject):
 return space.w_NotImplemented
 return self.symmetric_difference(w_other)
+descr_rxor = descr_xor # symmetric
 
 def descr_inplace_sub(self, space, w_other):
 if not isinstance(w_other, W_BaseSetObject):
@@ -528,9 +536,13 @@
 __iter__ = gateway.interp2app(W_BaseSetObject.descr_iter),
 __contains__ = gateway.interp2app(W_BaseSetObject.descr_contains),
 __sub__ = gateway.interp2app(W_BaseSetObject.descr_sub),
+__rsub__ = gateway.interp2app(W_BaseSetObject.descr_rsub),
 __and__ = gateway.interp2app(W_BaseSetObject.descr_and),
+__rand__ = gateway.interp2app(W_BaseSetObject.descr_rand),
 __or__ = gateway.interp2app(W_BaseSetObject.descr_or),
+__ror__ = gateway.interp2app(W_BaseSetObject.descr_ror),
 __xor__ = gateway.interp2app(W_BaseSetObject.descr_xor),
+__rxor__ = gateway.interp2app(W_BaseSetObject.descr_rxor),
 
 # mutating operators
 __isub__ = gateway.interp2app(W_BaseSetObject.descr_inplace_sub),
@@ -644,9 +656,13 @@
 __iter__ = gateway.interp2app(W_BaseSetObject.descr_iter),
 __contains__ = gateway.interp2app(W_BaseSetObject.descr_contains),
 __sub__ = gateway.interp2app(W_BaseSetObject.descr_sub),
+__rsub__ = gateway.interp2app(W_BaseSetObject.descr_rsub),
 __and__ = gateway.interp2app(W_BaseSetObject.descr_and),
+__rand__ = gateway.interp2app(W_BaseSetObject.descr_rand),
 __or__ = gateway.interp2app(W_BaseSetObject.descr_or),
+__ror__ = gateway.interp2app(W_BaseSetObject.descr_ror),
 __xor__ = gateway.interp2app(W_BaseSetObject.descr_xor),
+__rxor__ = gateway.interp2app(W_BaseSetObject.descr_rxor),
 
 # non-mutating methods
 __reduce__ = gateway.interp2app(W_BaseSetObject.descr_reduce),
diff --git a/pypy/objspace/std/test/test_newformat.py 
b/pypy/objspace/std/test/test_newformat.py
--- a/pypy/objspace/std/test/test_newformat.py
+++ b/pypy/objspace/std/test/test_newformat.py
@@ -404,6 +404,24 @@
 finally:
 locale.setlocale(locale.LC_NUMERIC, 'C')
 
+def test_locale_german(self):
+import locale
+for name in ['de_DE', 'de_DE.utf8']:
+try:
+locale.setlocale(locale.LC_NUMERIC, name)
+break
+except locale.Error:
+pass
+else:
+skip("no german locale")
+x = 1234.567890
+try:
+assert locale.format('%g', x, grouping=True) == '1.234,57'
+assert format(x, 'n') == '1.234,57'
+assert format(12345678901234, 'n') == '12.345.678.901.234'
+finally:
+locale.setlocale(locale.LC_NUMERIC, 'C')
+
 def test_dont_switch_to_g(self):
 skip("must fix when float formatting is figured out")
 assert len(format(1.1234e90, "f")) == 98
diff --git a/pypy/objspace/std/test/test_setobject.py 
b/pypy/objspace/std/test/test_setobject.py
--- a/pypy/objspace/std/test/test_setobject.py
+++ b/pypy/objspace/std/test/test_setobject.py
@@ -650,6 +650,40 @@
 assert type(t) is base
 assert not hasattr(t, 'x')
 
+def test_reverse_ops(self):
+assert set.__rxor__
+assert frozenset.__rxor__
+assert set.__ror__
+assert frozenset.__ror__
+assert set.__rand__
+ 

[pypy-commit] pypy default: merge heads

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: 
Changeset: r98612:39bcfae01bee
Date: 2020-01-31 14:10 +0100
http://bitbucket.org/pypy/pypy/changeset/39bcfae01bee/

Log:merge heads

diff --git a/pypy/module/mmap/interp_mmap.py b/pypy/module/mmap/interp_mmap.py
--- a/pypy/module/mmap/interp_mmap.py
+++ b/pypy/module/mmap/interp_mmap.py
@@ -177,8 +177,10 @@
 return space.newbytes(self.mmap.getslice(start, length))
 else:
 b = StringBuilder(length)
-for i in range(start, stop, step):
-b.append(self.mmap.getitem(i))
+index = start
+for i in range(length):
+b.append(self.mmap.getitem(index))
+index += step
 return space.newbytes(b.build())
 
 def descr_setitem(self, w_index, w_value):
diff --git a/pypy/module/mmap/test/test_mmap.py 
b/pypy/module/mmap/test/test_mmap.py
--- a/pypy/module/mmap/test/test_mmap.py
+++ b/pypy/module/mmap/test/test_mmap.py
@@ -433,6 +433,15 @@
 m.close()
 f.close()
 
+def test_get_crash(self):
+import sys
+from mmap import mmap
+s = b'hallo!!!'
+m = mmap(-1, len(s))
+m[:] = s
+assert m[1:None:sys.maxsize] == b'a'
+m.close()
+
 def test_set_item(self):
 import mmap
 
diff --git a/pypy/objspace/std/newformat.py b/pypy/objspace/std/newformat.py
--- a/pypy/objspace/std/newformat.py
+++ b/pypy/objspace/std/newformat.py
@@ -772,7 +772,7 @@
 digits = self._upcase_string(digits)
 out.append(digits)
 if spec.n_decimal:
-out.append(self._lit(".")[0])
+out.append(self._lit(self._loc_dec)[0])
 if spec.n_remainder:
 out.append(num[to_remainder:])
 if spec.n_rpadding:
diff --git a/pypy/objspace/std/test/test_newformat.py 
b/pypy/objspace/std/test/test_newformat.py
--- a/pypy/objspace/std/test/test_newformat.py
+++ b/pypy/objspace/std/test/test_newformat.py
@@ -389,6 +389,24 @@
 finally:
 locale.setlocale(locale.LC_NUMERIC, 'C')
 
+def test_locale_german(self):
+import locale
+for name in ['de_DE', 'de_DE.utf8']:
+try:
+locale.setlocale(locale.LC_NUMERIC, name)
+break
+except locale.Error:
+pass
+else:
+skip("no german locale")
+x = 1234.567890
+try:
+assert locale.format('%g', x, grouping=True) == '1.234,57'
+assert format(x, 'n') == '1.234,57'
+assert format(12345678901234, 'n') == '12.345.678.901.234'
+finally:
+locale.setlocale(locale.LC_NUMERIC, 'C')
+
 def test_dont_switch_to_g(self):
 skip("must fix when float formatting is figured out")
 assert len(format(1.1234e90, "f")) == 98
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy default: argh, fix bug in locale-specific string formatting: the thousands separator was always '.' :-(

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: 
Changeset: r98604:b6af70ef2dfb
Date: 2020-01-30 14:44 +0100
http://bitbucket.org/pypy/pypy/changeset/b6af70ef2dfb/

Log:argh, fix bug in locale-specific string formatting: the thousands
separator was always '.' :-(

diff --git a/pypy/objspace/std/newformat.py b/pypy/objspace/std/newformat.py
--- a/pypy/objspace/std/newformat.py
+++ b/pypy/objspace/std/newformat.py
@@ -772,7 +772,7 @@
 digits = self._upcase_string(digits)
 out.append(digits)
 if spec.n_decimal:
-out.append(self._lit(".")[0])
+out.append(self._lit(self._loc_dec)[0])
 if spec.n_remainder:
 out.append(num[to_remainder:])
 if spec.n_rpadding:
diff --git a/pypy/objspace/std/test/test_newformat.py 
b/pypy/objspace/std/test/test_newformat.py
--- a/pypy/objspace/std/test/test_newformat.py
+++ b/pypy/objspace/std/test/test_newformat.py
@@ -389,6 +389,24 @@
 finally:
 locale.setlocale(locale.LC_NUMERIC, 'C')
 
+def test_locale_german(self):
+import locale
+for name in ['de_DE', 'de_DE.utf8']:
+try:
+locale.setlocale(locale.LC_NUMERIC, name)
+break
+except locale.Error:
+pass
+else:
+skip("no german locale")
+x = 1234.567890
+try:
+assert locale.format('%g', x, grouping=True) == '1.234,57'
+assert format(x, 'n') == '1.234,57'
+assert format(12345678901234, 'n') == '12.345.678.901.234'
+finally:
+locale.setlocale(locale.LC_NUMERIC, 'C')
+
 def test_dont_switch_to_g(self):
 skip("must fix when float formatting is figured out")
 assert len(format(1.1234e90, "f")) == 98
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy default: issue #3065 strikes again! fix segfault in mmap

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: 
Changeset: r98609:d22a7659ed80
Date: 2020-01-31 14:04 +0100
http://bitbucket.org/pypy/pypy/changeset/d22a7659ed80/

Log:issue #3065 strikes again! fix segfault in mmap

diff --git a/pypy/module/mmap/interp_mmap.py b/pypy/module/mmap/interp_mmap.py
--- a/pypy/module/mmap/interp_mmap.py
+++ b/pypy/module/mmap/interp_mmap.py
@@ -177,8 +177,10 @@
 return space.newbytes(self.mmap.getslice(start, length))
 else:
 b = StringBuilder(length)
-for i in range(start, stop, step):
-b.append(self.mmap.getitem(i))
+index = start
+for i in range(length):
+b.append(self.mmap.getitem(index))
+index += step
 return space.newbytes(b.build())
 
 def descr_setitem(self, w_index, w_value):
diff --git a/pypy/module/mmap/test/test_mmap.py 
b/pypy/module/mmap/test/test_mmap.py
--- a/pypy/module/mmap/test/test_mmap.py
+++ b/pypy/module/mmap/test/test_mmap.py
@@ -433,6 +433,15 @@
 m.close()
 f.close()
 
+def test_get_crash(self):
+import sys
+from mmap import mmap
+s = b'hallo!!!'
+m = mmap(-1, len(s))
+m[:] = s
+assert m[1:None:sys.maxsize] == b'a'
+m.close()
+
 def test_set_item(self):
 import mmap
 
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy py3.7: kill dead attributes

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: py3.7
Changeset: r98614:784f171f4094
Date: 2020-01-31 15:38 +0100
http://bitbucket.org/pypy/pypy/changeset/784f171f4094/

Log:kill dead attributes

diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -301,7 +301,6 @@
 class GeneratorIterator(GeneratorOrCoroutine):
 "An iterator created by a generator."
 KIND = "generator"
-KIND_U = u"generator"
 
 def descr__iter__(self):
 """Implement iter(self)."""
@@ -348,7 +347,6 @@
 class Coroutine(GeneratorOrCoroutine):
 "A coroutine object."
 KIND = "coroutine"
-KIND_U = u"coroutine"
 
 def descr__await__(self, space):
 return CoroutineWrapper(self)
@@ -502,7 +500,6 @@
 class AsyncGenerator(GeneratorOrCoroutine):
 "An async generator (i.e. a coroutine with a 'yield')"
 KIND = "async generator"
-KIND_U = u"async_generator"
 
 def __init__(self, frame, name=None, qualname=None):
 self.hooks_inited = False
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy py3.7: generator_stop is not the default

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: py3.7
Changeset: r98613:cac6a157cae7
Date: 2020-01-31 15:37 +0100
http://bitbucket.org/pypy/pypy/changeset/cac6a157cae7/

Log:generator_stop is not the default

diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -163,23 +163,14 @@
 self.frame.w_yielding_from = w_delegate
 
 def _leak_stopiteration(self, e):
-# Check for __future__ generator_stop and conditionally turn
-# a leaking StopIteration into RuntimeError (with its cause
-# set appropriately).
+# turn a leaking StopIteration into RuntimeError (with its cause set
+# appropriately).
 space = self.space
-if self.pycode.co_flags & (consts.CO_FUTURE_GENERATOR_STOP |
-   consts.CO_COROUTINE |
-   consts.CO_ITERABLE_COROUTINE |
-   consts.CO_ASYNC_GENERATOR):
-e2 = OperationError(space.w_RuntimeError,
-space.newtext("%s raised StopIteration" %
-  self.KIND))
-e2.chain_exceptions_from_cause(space, e)
-raise e2
-else:
-space.warn(space.newtext("generator '%s' raised StopIteration"
-% self.get_qualname()),
-   space.w_DeprecationWarning)
+e2 = OperationError(space.w_RuntimeError,
+space.newtext("%s raised StopIteration" %
+  self.KIND))
+e2.chain_exceptions_from_cause(space, e)
+raise e2
 
 def _leak_stopasynciteration(self, e):
 space = self.space
diff --git a/pypy/interpreter/test/apptest_generator.py 
b/pypy/interpreter/test/apptest_generator.py
--- a/pypy/interpreter/test/apptest_generator.py
+++ b/pypy/interpreter/test/apptest_generator.py
@@ -221,16 +221,6 @@
 g = f()
 assert g.close() is None
 
-def test_close2():
-def f():
-try:
-yield 1
-except GeneratorExit:
-raise StopIteration
-g = f()
-next(g)
-assert g.close() is None
-
 def test_close3():
 def f():
 try:
@@ -275,21 +265,6 @@
 with raises(TypeError):
 g.send(1)  # not started, must send None
 
-def test_generator_explicit_stopiteration():
-def f():
-yield 1
-raise StopIteration
-g = f()
-assert [x for x in g] == [1]
-
-def test_generator_propagate_stopiteration():
-def f():
-it = iter([1])
-while 1:
-yield next(it)
-g = f()
-assert [x for x in g] == [1]
-
 def test_generator_restart():
 def g():
 i = next(me)
@@ -325,12 +300,6 @@
 assert set(g) == set()
 assert set(i for i in range(0)) == set()
 
-def test_explicit_stop_iteration_unpackiterable():
-def f():
-yield 1
-raise StopIteration
-assert tuple(f()) == (1,)
-
 def test_exception_is_cleared_by_yield():
 def f():
 try:
@@ -826,34 +795,18 @@
 assert isinstance(excinfo.value.__context__, ValueError)
 
 
-def test_past_generator_stop():
-# how it works without 'from __future__' import generator_stop
-def f(x):
-raise StopIteration
+def test_stopiteration_turned_into_runtime_error():
+def badgenerator(x):
+if x == 5:
+raise StopIteration
 yield x
-with raises(StopIteration):
-next(f(5))
-
-def test_future_generator_stop():
-d = {}
-exec("""from __future__ import generator_stop
-
-def f(x):
-raise StopIteration
-yield x
-""", d)
-f = d['f']
 with raises(RuntimeError):
-next(f(5))
+next(badgenerator(5))
 
 def test_generator_stop_cause():
-d = {}
-exec("""from __future__ import generator_stop
-
-def gen1():
-yield 42
-""", d)
-my_gen = d['gen1']()
+def gen1():
+yield 42
+my_gen = gen1()
 assert next(my_gen) == 42
 stop_exc = StopIteration('spam')
 with raises(RuntimeError) as e:
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy py3.7: implement coroutine origin tracking

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: py3.7
Changeset: r98615:5c1dc1c61dcc
Date: 2020-01-31 20:28 +0100
http://bitbucket.org/pypy/pypy/changeset/5c1dc1c61dcc/

Log:implement coroutine origin tracking

diff --git a/pypy/interpreter/executioncontext.py 
b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -45,6 +45,7 @@
 self.w_asyncgen_firstiter_fn = None
 self.w_asyncgen_finalizer_fn = None
 self.contextvar_context = None
+self.coroutine_origin_tracking_depth = 0
 
 @staticmethod
 def _mark_thread_disappeared(space):
diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -348,17 +348,42 @@
 "A coroutine object."
 KIND = "coroutine"
 
+def __init__(self, frame, name=None, qualname=None):
+GeneratorOrCoroutine.__init__(self, frame, name, qualname)
+self.w_cr_origin = self.space.w_None
+
+def capture_origin(self, ec):
+if not ec.coroutine_origin_tracking_depth:
+return
+self._capture_origin(ec)
+
+def _capture_origin(self, ec):
+space = self.space
+frames_w = []
+frame = ec.gettopframe_nohidden()
+for i in range(ec.coroutine_origin_tracking_depth):
+frames_w.append(
+space.newtuple([
+frame.pycode.w_filename,
+frame.fget_f_lineno(space),
+space.newtext(frame.pycode.co_name)]))
+frame = ec.getnextframe_nohidden(frame)
+if frame is None:
+break
+self.w_cr_origin = space.newtuple(frames_w)
+
 def descr__await__(self, space):
 return CoroutineWrapper(self)
 
 def _finalize_(self):
 # If coroutine was never awaited on issue a RuntimeWarning.
-if self.pycode is not None and \
-   self.frame is not None and \
-   self.frame.last_instr == -1:
+if (self.pycode is not None and
+self.frame is not None and
+self.frame.last_instr == -1):
 space = self.space
-msg = "coroutine '%s' was never awaited" % self.get_qualname()
-space.warn(space.newtext(msg), space.w_RuntimeWarning)
+w_mod = space.getbuiltinmodule("_warnings")
+w_f = space.getattr(w_mod, 
space.newtext("_warn_unawaited_coroutine"))
+space.call_function(w_f, self)
 GeneratorOrCoroutine._finalize_(self)
 
 
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -266,6 +266,7 @@
 gen = Coroutine(self, name, qualname)
 ec = space.getexecutioncontext()
 w_wrapper = ec.w_coroutine_wrapper_fn
+gen.capture_origin(ec)
 elif flags & pycode.CO_ASYNC_GENERATOR:
 from pypy.interpreter.generator import AsyncGenerator
 gen = AsyncGenerator(self, name, qualname)
diff --git a/pypy/interpreter/test/apptest_coroutine.py 
b/pypy/interpreter/test/apptest_coroutine.py
--- a/pypy/interpreter/test/apptest_coroutine.py
+++ b/pypy/interpreter/test/apptest_coroutine.py
@@ -840,3 +840,65 @@
 assert finalized == 2
 finally:
 sys.set_asyncgen_hooks(*old_hooks)
+
+def test_coroutine_capture_origin():
+import contextlib
+
+def here():
+f = sys._getframe().f_back
+return (f.f_code.co_filename, f.f_lineno)
+
+try:
+async def corofn():
+pass
+
+with contextlib.closing(corofn()) as coro:
+assert coro.cr_origin is None
+
+sys.set_coroutine_origin_tracking_depth(1)
+
+fname, lineno = here()
+with contextlib.closing(corofn()) as coro:
+print(coro.cr_origin)
+assert coro.cr_origin == (
+(fname, lineno + 1, "test_coroutine_capture_origin"),)
+
+
+sys.set_coroutine_origin_tracking_depth(2)
+
+def nested():
+return (here(), corofn())
+fname, lineno = here()
+((nested_fname, nested_lineno), coro) = nested()
+with contextlib.closing(coro):
+print(coro.cr_origin)
+assert coro.cr_origin == (
+(nested_fname, nested_lineno, "nested"),
+(fname, lineno + 1, "test_coroutine_capture_origin"))
+
+# Check we handle running out of frames correctly
+sys.set_coroutine_origin_tracking_depth(1000)
+with contextlib.closing(corofn()) as coro:
+print(coro.cr_origin)
+assert 1 <= len(coro.cr_origin) < 1000
+finally:
+sys.set_coroutine_origin_tracking_depth(0)
+
+def test_runtime_warning_origin_tracking():
+import gc, warnings  # XXX: importing warnings is expensive untranslated
+async def foobaz():
+pass
+gc.collect()  

[pypy-commit] pypy py3.7: slight variant in error msg

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: py3.7
Changeset: r98620:8d3b5e787554
Date: 2020-01-31 22:33 +0100
http://bitbucket.org/pypy/pypy/changeset/8d3b5e787554/

Log:slight variant in error msg

diff --git a/lib-python/3/test/test_dataclasses.py 
b/lib-python/3/test/test_dataclasses.py
--- a/lib-python/3/test/test_dataclasses.py
+++ b/lib-python/3/test/test_dataclasses.py
@@ -3015,7 +3015,7 @@
   lambda x:x,
   ]:
 with self.subTest(bad_field=bad_field):
-with self.assertRaisesRegex(TypeError, r'has no len\(\)'):
+with self.assertRaisesRegex(TypeError, r'has no len.*'):
 make_dataclass('C', ['a', bad_field])
 
 def test_duplicate_field_names(self):
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy py3.7: skip cpython only test

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: py3.7
Changeset: r98616:98cbf9a6e204
Date: 2020-01-31 21:22 +0100
http://bitbucket.org/pypy/pypy/changeset/98cbf9a6e204/

Log:skip cpython only test

diff --git a/lib-python/3/test/test_coroutines.py 
b/lib-python/3/test/test_coroutines.py
--- a/lib-python/3/test/test_coroutines.py
+++ b/lib-python/3/test/test_coroutines.py
@@ -2276,6 +2276,7 @@
 finally:
 sys.set_coroutine_origin_tracking_depth(orig_depth)
 
+@support.cpython_only # pypy has this function in _warnings
 def test_unawaited_warning_when_module_broken(self):
 # Make sure we don't blow up too bad if
 # warnings._warn_unawaited_coroutine is broken somehow (e.g. because
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy py3.7: fix error msg

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: py3.7
Changeset: r98619:4e018a19da74
Date: 2020-01-31 22:31 +0100
http://bitbucket.org/pypy/pypy/changeset/4e018a19da74/

Log:fix error msg

diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -598,6 +598,8 @@
 left, right = specialnames
 op = getattr(operator, left)
 def comparison_impl(space, w_obj1, w_obj2):
+w_orig_obj1 = w_obj1
+w_orig_obj2 = w_obj2
 w_typ1 = space.type(w_obj1)
 w_typ2 = space.type(w_obj2)
 w_left_src, w_left_impl = space.lookup_in_type_where(w_typ1, left)
@@ -637,7 +639,7 @@
 # if we arrived here, they are unorderable
 raise oefmt(space.w_TypeError,
 "'%s' not supported between instances of '%T' and '%T'",
-symbol, w_obj1, w_obj2)
+symbol, w_orig_obj1, w_orig_obj2)
 
 return func_with_new_name(comparison_impl, 
'comparison_%s_impl'%left.strip('_'))
 
diff --git a/pypy/objspace/test/test_descroperation.py 
b/pypy/objspace/test/test_descroperation.py
--- a/pypy/objspace/test/test_descroperation.py
+++ b/pypy/objspace/test/test_descroperation.py
@@ -343,6 +343,19 @@
 raises(TypeError, "0.0 < zz()")
 raises(TypeError, "0j < zz()")
 
+def test_correct_order_error_msg(self):
+class A(object):
+def __lt__(self, other):
+return NotImplemented
+__gt__ = __lt__
+
+class B(A):
+pass
+
+with raises(TypeError) as e:
+A() < B()
+assert str(e.value) == "'<' not supported between instances of 'A' and 
'B'"
+
 def test_equality_among_different_types(self):
 class A(object): pass
 class zz(object): pass
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy py3.7: implement opcode tracing, make it possible to turn off line tracing

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: py3.7
Changeset: r98617:e446a354c3d0
Date: 2020-01-31 22:04 +0100
http://bitbucket.org/pypy/pypy/changeset/e446a354c3d0/

Log:implement opcode tracing, make it possible to turn off line tracing

diff --git a/pypy/interpreter/executioncontext.py 
b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -183,7 +183,8 @@
 if d.instr_lb <= frame.last_instr < d.instr_ub:
 if frame.last_instr < d.instr_prev_plus_one:
 # We jumped backwards in the same line.
-self._trace(frame, 'line', self.space.w_None)
+if d.f_trace_lines:
+self._trace(frame, 'line', self.space.w_None)
 else:
 size = len(code.co_lnotab) / 2
 addr = 0
@@ -219,7 +220,10 @@
 
 if d.instr_lb == frame.last_instr: # At start of line!
 d.f_lineno = line
-self._trace(frame, 'line', self.space.w_None)
+if d.f_trace_lines:
+self._trace(frame, 'line', self.space.w_None)
+if d.f_trace_opcodes:
+self._trace(frame, 'opcode', self.space.w_None)
 
 d.instr_prev_plus_one = frame.last_instr + 1
 
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -36,6 +36,8 @@
 f_lineno = 0  # current lineno for tracing
 is_being_profiled= False
 is_in_line_tracing   = False
+f_trace_lines= True
+f_trace_opcodes  = False
 w_locals = None
 hidden_operationerr  = None
 
@@ -148,6 +150,18 @@
 return None
 return d.w_locals
 
+def get_f_trace_lines(self):
+d = self.getdebug()
+if d is None:
+return True
+return d.f_trace_lines
+
+def get_f_trace_opcodes(self):
+d = self.getdebug()
+if d is None:
+return False
+return d.f_trace_opcodes
+
 @not_rpython
 def __repr__(self):
 # useful in tracebacks
@@ -898,10 +912,17 @@
 def fdel_f_trace(self, space):
 self.getorcreatedebug().w_f_trace = None
 
-def fget_f_restricted(self, space):
-if space.config.objspace.honor__builtins__:
-return space.newbool(self.builtin is not space.builtin)
-return space.w_False
+def fget_f_trace_lines(self, space):
+return space.newbool(self.get_f_trace_lines())
+
+def fset_f_trace_lines(self, space, w_trace):
+self.getorcreatedebug().f_trace_lines = space.is_true(w_trace)
+
+def fget_f_trace_opcodes(self, space):
+return space.newbool(self.get_f_trace_opcodes())
+
+def fset_f_trace_opcodes(self, space, w_trace):
+self.getorcreatedebug().f_trace_opcodes = space.is_true(w_trace)
 
 def get_generator(self):
 if self.space.config.translation.rweakref:
diff --git a/pypy/interpreter/test/apptest_pyframe.py 
b/pypy/interpreter/test/apptest_pyframe.py
--- a/pypy/interpreter/test/apptest_pyframe.py
+++ b/pypy/interpreter/test/apptest_pyframe.py
@@ -584,6 +584,63 @@
 sys.settrace(None)
 assert res == 10
 
+def test_disable_line_tracing():
+import sys
+assert sys._getframe().f_trace_lines
+
+l = []
+def trace(frame, event, arg):
+l.append((frame.f_code.co_name, event, arg, frame.f_lineno - 
frame.f_code.co_firstlineno))
+frame.f_trace_lines = False
+return trace
+def g(n):
+return n + 2
+def f(n):
+n = g(n)
+return n * 7
+sys.settrace(trace)
+x = f(4)
+sys.settrace(None)
+print(l)
+assert l == [('f', 'call', None, 0), ('g', 'call', None, 0), ('g', 
'return', 6, 1), ('f', 'return', 42, 2)]
+
+test_disable_line_tracing()
+
+def test_opcode_tracing():
+import sys
+assert not sys._getframe().f_trace_opcodes
+
+l = []
+def trace(frame, event, arg):
+l.append((frame.f_code.co_name, event, arg, frame.f_lasti, 
frame.f_lineno - frame.f_code.co_firstlineno))
+frame.f_trace_opcodes = True
+return trace
+def g(n):
+return n + 2
+def f(n):
+return g(n)
+sys.settrace(trace)
+x = f(4)
+sys.settrace(None)
+print(l)
+assert l == [
+('f', 'call', None, -1, 0),
+('f', 'line', None, 0, 1),
+('f', 'opcode', None, 0, 1),
+('f', 'opcode', None, 2, 1),
+('f', 'opcode', None, 4, 1),
+('g', 'call', None, -1, 0),
+('g', 'line', None, 0, 1),
+('g', 'opcode', None, 0, 1),
+('g', 'opcode', None, 2, 1),
+('g', 'opcode', None, 4, 1),
+('g', 'opcode', None, 6, 1),
+('g', 'return', 6, 6, 1),
+('f', 'opcode', None, 6, 1),
+('f', 'return', 6, 6, 1)]
+
+test_opcode_tracing()
+
 def test_preserve_exc_state_in_generators():

[pypy-commit] pypy py3.7: we happily pass these...

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: py3.7
Changeset: r98618:bf0519b39ac6
Date: 2020-01-31 22:11 +0100
http://bitbucket.org/pypy/pypy/changeset/bf0519b39ac6/

Log:we happily pass these...

diff --git a/lib-python/3/test/test_sys_settrace.py 
b/lib-python/3/test/test_sys_settrace.py
--- a/lib-python/3/test/test_sys_settrace.py
+++ b/lib-python/3/test/test_sys_settrace.py
@@ -473,7 +473,6 @@
 return Tracer(trace_line_events=False)
 
 
-@support.cpython_only
 class TraceOpcodesTestCase(TraceTestCase):
 """Repeat the trace tests, but with per-opcodes events enabled"""
 
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy py3.7: skip an implementation detail

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: py3.7
Changeset: r98621:cd4e6f012629
Date: 2020-01-31 22:52 +0100
http://bitbucket.org/pypy/pypy/changeset/cd4e6f012629/

Log:skip an implementation detail

diff --git a/lib-python/3/test/test_types.py b/lib-python/3/test/test_types.py
--- a/lib-python/3/test/test_types.py
+++ b/lib-python/3/test/test_types.py
@@ -590,6 +590,7 @@
 self.assertIsInstance(object().__lt__, types.MethodWrapperType)
 self.assertIsInstance((42).__lt__, types.MethodWrapperType)
 
+@impl_detail
 def test_method_descriptor_types(self):
 self.assertIsInstance(str.join, types.MethodDescriptorType)
 self.assertIsInstance(list.append, types.MethodDescriptorType)
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy py3.7: gah! turning StopIteration to RuntimeError in generators broke the applevel

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: py3.7
Changeset: r98622:7a0cdcf24b94
Date: 2020-01-31 23:01 +0100
http://bitbucket.org/pypy/pypy/changeset/7a0cdcf24b94/

Log:gah! turning StopIteration to RuntimeError in generators broke the
applevel implementation of iter with sentinel!

diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -163,6 +163,7 @@
 self.frame.w_yielding_from = w_delegate
 
 def _leak_stopiteration(self, e):
+import pdb; pdb.set_trace()
 # turn a leaking StopIteration into RuntimeError (with its cause set
 # appropriately).
 space = self.space
diff --git a/pypy/interpreter/test/apptest_generator.py 
b/pypy/interpreter/test/apptest_generator.py
--- a/pypy/interpreter/test/apptest_generator.py
+++ b/pypy/interpreter/test/apptest_generator.py
@@ -803,6 +803,21 @@
 with raises(RuntimeError):
 next(badgenerator(5))
 
+def test_stopiteration_can_be_caught():
+def g():
+raise StopIteration
+def finegenerator(x):
+yield x
+if x == 5:
+try:
+g()
+except StopIteration:
+pass
+yield x
+gen = finegenerator(5)
+next(gen) # fine
+next(gen) # fine
+
 def test_generator_stop_cause():
 def gen1():
 yield 42
diff --git a/pypy/module/__builtin__/operation.py 
b/pypy/module/__builtin__/operation.py
--- a/pypy/module/__builtin__/operation.py
+++ b/pypy/module/__builtin__/operation.py
@@ -126,7 +126,10 @@
 
 def iter_generator(callable_, sentinel):
 while 1:
-result = callable_()
+try:
+result = callable_()
+except StopIteration:
+return
 if result == sentinel:
 return
 yield result
diff --git a/pypy/module/__builtin__/test/test_builtin.py 
b/pypy/module/__builtin__/test/test_builtin.py
--- a/pypy/module/__builtin__/test/test_builtin.py
+++ b/pypy/module/__builtin__/test/test_builtin.py
@@ -286,17 +286,20 @@
 self.value = 0
 def __call__(self):
 self.value += 1
+if self.value > 10:
+raise StopIteration
 return self.value
-# XXX Raising errors is quite slow --
-#uncomment these lines when fixed
-#self.assertRaises(TypeError,iter,3,5)
-#self.assertRaises(TypeError,iter,[],5)
-#self.assertRaises(TypeError,iter,{},5)
+with raises(TypeError):
+iter(3, 5)
+
 x = iter(count(),3)
 assert next(x) ==1
 assert next(x) ==2
 raises(StopIteration, next, x)
 
+# a case that runs till the end
+assert list(iter(count(), 100)) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+
 def test_enumerate(self):
 import sys
 seq = range(2,4)
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy py3.7: make putenv complain about bad names (test already existed)

2020-01-31 Thread cfbolz
Author: Carl Friedrich Bolz-Tereick 
Branch: py3.7
Changeset: r98624:89255ed57e9f
Date: 2020-01-31 23:29 +0100
http://bitbucket.org/pypy/pypy/changeset/89255ed57e9f/

Log:make putenv complain about bad names (test already existed)

diff --git a/pypy/module/posix/interp_posix.py 
b/pypy/module/posix/interp_posix.py
--- a/pypy/module/posix/interp_posix.py
+++ b/pypy/module/posix/interp_posix.py
@@ -935,9 +935,21 @@
 def putenv(space, w_name, w_value):
 """Change or add an environment variable."""
 try:
-dispatch_filename_2(rposix.putenv)(space, w_name, w_value)
+dispatch_filename_2(putenv_impl)(space, w_name, w_value)
 except OSError as e:
 raise wrap_oserror(space, e, eintr_retry=False)
+except ValueError:
+raise oefmt(space.w_ValueError,
+"illegal environment variable name")
+
+@specialize.argtype(0, 1)
+def putenv_impl(name, value):
+from rpython.rlib.rposix import _as_bytes
+name = _as_bytes(name)
+value = _as_bytes(value)
+if "=" in name:
+raise ValueError
+return rposix.putenv(name, value)
 
 def unsetenv(space, w_name):
 """Delete an environment variable."""
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit