diff --git a/test/bytecode_3.0_run/05_block_fallback.pyc b/test/bytecode_3.0_run/05_block_fallback.pyc new file mode 100644 index 00000000..b2f9418a Binary files /dev/null and b/test/bytecode_3.0_run/05_block_fallback.pyc differ diff --git a/test/bytecode_3.5_run/05_block_fallback.pyc b/test/bytecode_3.5_run/05_block_fallback.pyc new file mode 100644 index 00000000..186cc2c0 Binary files /dev/null and b/test/bytecode_3.5_run/05_block_fallback.pyc differ diff --git a/test/bytecode_3.7_run/05_block_fallback.pyc b/test/bytecode_3.7_run/05_block_fallback.pyc new file mode 100644 index 00000000..fd4692f7 Binary files /dev/null and b/test/bytecode_3.7_run/05_block_fallback.pyc differ diff --git a/test/simple_source/bug30/05_block_fallback.py b/test/simple_source/bug30/05_block_fallback.py new file mode 100644 index 00000000..ed1c979c --- /dev/null +++ b/test/simple_source/bug30/05_block_fallback.py @@ -0,0 +1,32 @@ +# Adapted from 3.7.6 test_contains +# The bug was in reconstructing something equivalent to +# "while False: yelid None" which is *needed* in __iter__(). +# Sheeh! + +# RUNNABLE! +def test_block_fallback(): + # blocking fallback with __contains__ = None + class ByContains(object): + def __contains__(self, other): + return False + c = ByContains() + class BlockContains(ByContains): + """Is not a container + + This class is a perfectly good iterable (as tested by + list(bc)), as well as inheriting from a perfectly good + container, but __contains__ = None prevents the usual + fallback to iteration in the container protocol. That + is, normally, 0 in bc would fall back to the equivalent + of any(x==0 for x in bc), but here it's blocked from + doing so. + """ + def __iter__(self): + while False: + yield None + __contains__ = None + bc = BlockContains() + assert not (0 in c) + assert not (0 in list(bc)) + +test_block_fallback() diff --git a/test/stdlib/3.7-exclude.sh b/test/stdlib/3.7-exclude.sh index 52bff135..2b1f0c19 100644 --- a/test/stdlib/3.7-exclude.sh +++ b/test/stdlib/3.7-exclude.sh @@ -30,7 +30,7 @@ SKIP_TESTS=( [test_compileall.py]=1 # fails on its own [test_compile.py]=1 # Code introspects on co_consts in a non-decompilable way [test_concurrent_futures.py]=1 # too long - [test_coroutines.py]=1 # test + [test_coroutines.py]=1 # parse error [test_codecs.py]=1 # test assert failures; encoding/decoding stuff [test_ctypes.py]=1 # it fails on its own [test_curses.py]=1 # probably byte string not handled properly diff --git a/uncompyle6/semantics/make_function3.py b/uncompyle6/semantics/make_function3.py index 66bc6fa3..fd61e9a7 100644 --- a/uncompyle6/semantics/make_function3.py +++ b/uncompyle6/semantics/make_function3.py @@ -677,7 +677,7 @@ def make_function3(self, node, is_lambda, nested=1, code_node=None): # add in "yield" just so that the compiler will mark # the GENERATOR bit of the function. See for example # Python 3.x's test_generator.py test program. - if code.co_flags & CO_GENERATOR: + if not is_lambda code.co_flags & CO_GENERATOR: need_bogus_yield = True for token in scanner_code._tokens: if token in ("YIELD_VALUE", "YIELD_FROM"): diff --git a/uncompyle6/semantics/make_function36.py b/uncompyle6/semantics/make_function36.py index f273f265..c696a508 100644 --- a/uncompyle6/semantics/make_function36.py +++ b/uncompyle6/semantics/make_function36.py @@ -356,7 +356,7 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None): # add in "yield" just so that the compiler will mark # the GENERATOR bit of the function. See for example # Python 3.x's test_connection.py and test_contexlib_async test programs. - if code.co_flags & (CO_GENERATOR | CO_ASYNC_GENERATOR): + if not is_lambda and code.co_flags & (CO_GENERATOR | CO_ASYNC_GENERATOR): need_bogus_yield = True for token in scanner_code._tokens: if token == "YIELD_VALUE":