diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2014-07-07 10:46:09 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2014-07-07 10:46:09 (GMT) |
commit | 3bc13cc8b0b85f989b8da9c5718fc5319ad06248 (patch) | |
tree | 52fc5995a7cc1ccafce61ef403b7dea1a4ff342d /Lib | |
parent | 667abc7d42e87b87338981276d0eac9895d4abf4 (diff) | |
parent | e50dafcd636ba32db890600164698bb070d40d97 (diff) | |
download | cpython-3bc13cc8b0b85f989b8da9c5718fc5319ad06248.zip cpython-3bc13cc8b0b85f989b8da9c5718fc5319ad06248.tar.gz cpython-3bc13cc8b0b85f989b8da9c5718fc5319ad06248.tar.bz2 |
Merge heads
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/asyncio/coroutines.py | 6 | ||||
-rw-r--r-- | Lib/asyncio/futures.py | 6 | ||||
-rw-r--r-- | Lib/asyncio/proactor_events.py | 2 | ||||
-rw-r--r-- | Lib/asyncio/queues.py | 2 | ||||
-rw-r--r-- | Lib/asyncio/selector_events.py | 5 | ||||
-rw-r--r-- | Lib/asyncio/tasks.py | 3 | ||||
-rw-r--r-- | Lib/asyncio/unix_events.py | 4 | ||||
-rw-r--r-- | Lib/distutils/sysconfig.py | 3 | ||||
-rw-r--r-- | Lib/distutils/tests/test_sysconfig.py | 22 | ||||
-rw-r--r-- | Lib/pathlib.py | 11 | ||||
-rw-r--r-- | Lib/test/test_asyncio/test_futures.py | 6 | ||||
-rw-r--r-- | Lib/test/test_asyncio/test_tasks.py | 4 | ||||
-rw-r--r-- | Lib/test/test_frame.py | 52 | ||||
-rw-r--r-- | Lib/test/test_pathlib.py | 14 |
14 files changed, 128 insertions, 12 deletions
diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py index 71a1ec4..7654a0b 100644 --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -64,6 +64,12 @@ class CoroWrapper: self.gen = gen self.func = func self._source_traceback = traceback.extract_stack(sys._getframe(1)) + # __name__, __qualname__, __doc__ attributes are set by the coroutine() + # decorator + + def __repr__(self): + return ('<%s %s>' + % (self.__class__.__name__, _format_coroutine(self))) def __iter__(self): return self diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py index fcc90d1..022fef7 100644 --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -316,6 +316,12 @@ class Future: # So-called internal methods (note: no set_running_or_notify_cancel()). + def _set_result_unless_cancelled(self, result): + """Helper setting the result only if the future was not cancelled.""" + if self.cancelled(): + return + self.set_result(result) + def set_result(self, result): """Mark the future done and set its result. diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index b76f69e..a80876f 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -38,7 +38,7 @@ class _ProactorBasePipeTransport(transports._FlowControlMixin, self._server.attach(self) self._loop.call_soon(self._protocol.connection_made, self) if waiter is not None: - self._loop.call_soon(waiter.set_result, None) + self._loop.call_soon(waiter._set_result_unless_cancelled, None) def _set_extra(self, sock): self._extra['pipe'] = sock diff --git a/Lib/asyncio/queues.py b/Lib/asyncio/queues.py index 57afb05..41551a9 100644 --- a/Lib/asyncio/queues.py +++ b/Lib/asyncio/queues.py @@ -173,7 +173,7 @@ class Queue: # run, we need to defer the put for a tick to ensure that # getters and putters alternate perfectly. See # ChannelTest.test_wait. - self._loop.call_soon(putter.set_result, None) + self._loop.call_soon(putter._set_result_unless_cancelled, None) return self._get() diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index df64aec..2a17034 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -481,7 +481,7 @@ class _SelectorSocketTransport(_SelectorTransport): self._loop.add_reader(self._sock_fd, self._read_ready) self._loop.call_soon(self._protocol.connection_made, self) if waiter is not None: - self._loop.call_soon(waiter.set_result, None) + self._loop.call_soon(waiter._set_result_unless_cancelled, None) def pause_reading(self): if self._closing: @@ -690,7 +690,8 @@ class _SelectorSslTransport(_SelectorTransport): self._loop.add_reader(self._sock_fd, self._read_ready) self._loop.call_soon(self._protocol.connection_made, self) if self._waiter is not None: - self._loop.call_soon(self._waiter.set_result, None) + self._loop.call_soon(self._waiter._set_result_unless_cancelled, + None) def pause_reading(self): # XXX This is a bit icky, given the comment at the top of diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index dd191e7..8c7217b 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -487,7 +487,8 @@ def as_completed(fs, *, loop=None, timeout=None): def sleep(delay, result=None, *, loop=None): """Coroutine that completes after a given time (in seconds).""" future = futures.Future(loop=loop) - h = future._loop.call_later(delay, future.set_result, result) + h = future._loop.call_later(delay, + future._set_result_unless_cancelled, result) try: return (yield from future) finally: diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index 5f728b5..535ea22 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -269,7 +269,7 @@ class _UnixReadPipeTransport(transports.ReadTransport): self._loop.add_reader(self._fileno, self._read_ready) self._loop.call_soon(self._protocol.connection_made, self) if waiter is not None: - self._loop.call_soon(waiter.set_result, None) + self._loop.call_soon(waiter._set_result_unless_cancelled, None) def _read_ready(self): try: @@ -353,7 +353,7 @@ class _UnixWritePipeTransport(transports._FlowControlMixin, self._loop.call_soon(self._protocol.connection_made, self) if waiter is not None: - self._loop.call_soon(waiter.set_result, None) + self._loop.call_soon(waiter._set_result_unless_cancelled, None) def get_write_buffer_size(self): return sum(len(data) for data in self._buffer) diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py index 75537db..5b94fa2 100644 --- a/Lib/distutils/sysconfig.py +++ b/Lib/distutils/sysconfig.py @@ -179,7 +179,8 @@ def customize_compiler(compiler): # version and build tools may not support the same set # of CPU architectures for universal builds. global _config_vars - if not _config_vars.get('CUSTOMIZED_OSX_COMPILER', ''): + # Use get_config_var() to ensure _config_vars is initialized. + if not get_config_var('CUSTOMIZED_OSX_COMPILER'): import _osx_support _osx_support.customize_compiler(_config_vars) _config_vars['CUSTOMIZED_OSX_COMPILER'] = 'True' diff --git a/Lib/distutils/tests/test_sysconfig.py b/Lib/distutils/tests/test_sysconfig.py index 95fa9dc..fc4d1de 100644 --- a/Lib/distutils/tests/test_sysconfig.py +++ b/Lib/distutils/tests/test_sysconfig.py @@ -1,6 +1,9 @@ """Tests for distutils.sysconfig.""" import os import shutil +import subprocess +import sys +import textwrap import unittest from distutils import sysconfig @@ -174,6 +177,25 @@ class SysconfigTestCase(support.EnvironGuard, unittest.TestCase): self.assertIsNotNone(vars['SO']) self.assertEqual(vars['SO'], vars['EXT_SUFFIX']) + def test_customize_compiler_before_get_config_vars(self): + # Issue #21923: test that a Distribution compiler + # instance can be called without an explicit call to + # get_config_vars(). + with open(TESTFN, 'w') as f: + f.writelines(textwrap.dedent('''\ + from distutils.core import Distribution + config = Distribution().get_command_obj('config') + # try_compile may pass or it may fail if no compiler + # is found but it should not raise an exception. + rc = config.try_compile('int x;') + ''')) + p = subprocess.Popen([str(sys.executable), TESTFN], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True) + outs, errs = p.communicate() + self.assertEqual(0, p.returncode, "Subprocess failed: " + outs) + def test_suite(): suite = unittest.TestSuite() diff --git a/Lib/pathlib.py b/Lib/pathlib.py index d3d1af8..48b7031 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -749,17 +749,20 @@ class PurePath(object): """Return a new path with the file name changed.""" if not self.name: raise ValueError("%r has an empty name" % (self,)) + drv, root, parts = self._flavour.parse_parts((name,)) + if (not name or name[-1] in [self._flavour.sep, self._flavour.altsep] + or drv or root or len(parts) != 1): + raise ValueError("Invalid name %r" % (name)) return self._from_parsed_parts(self._drv, self._root, self._parts[:-1] + [name]) def with_suffix(self, suffix): """Return a new path with the file suffix changed (or added, if none).""" # XXX if suffix is None, should the current suffix be removed? - drv, root, parts = self._flavour.parse_parts((suffix,)) - if drv or root or len(parts) != 1: + f = self._flavour + if f.sep in suffix or f.altsep and f.altsep in suffix: raise ValueError("Invalid suffix %r" % (suffix)) - suffix = parts[0] - if not suffix.startswith('.'): + if suffix and not suffix.startswith('.') or suffix == '.': raise ValueError("Invalid suffix %r" % (suffix)) name = self.name if not name: diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py index 96b41d6..a6071ea 100644 --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -343,6 +343,12 @@ class FutureTests(test_utils.TestCase): message = m_log.error.call_args[0][0] self.assertRegex(message, re.compile(regex, re.DOTALL)) + def test_set_result_unless_cancelled(self): + fut = asyncio.Future(loop=self.loop) + fut.cancel() + fut._set_result_unless_cancelled(2) + self.assertTrue(fut.cancelled()) + class FutureDoneCallbackTests(test_utils.TestCase): diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 83b7e61..eaef05b 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -211,6 +211,10 @@ class TaskTests(test_utils.TestCase): coro = ('%s() at %s:%s' % (coro_qualname, code.co_filename, code.co_firstlineno)) + # test repr(CoroWrapper) + if coroutines._DEBUG: + self.assertEqual(repr(gen), '<CoroWrapper %s>' % coro) + # test pending Task t = asyncio.Task(gen, loop=self.loop) t.add_done_callback(Dummy()) diff --git a/Lib/test/test_frame.py b/Lib/test/test_frame.py index 2dd5780..c402ec3 100644 --- a/Lib/test/test_frame.py +++ b/Lib/test/test_frame.py @@ -1,5 +1,6 @@ import gc import sys +import types import unittest import weakref @@ -109,6 +110,57 @@ class ClearTest(unittest.TestCase): self.assertIs(None, wr()) +class FrameLocalsTest(unittest.TestCase): + """ + Tests for the .f_locals attribute. + """ + + def make_frames(self): + def outer(): + x = 5 + y = 6 + def inner(): + z = x + 2 + 1/0 + t = 9 + return inner() + try: + outer() + except ZeroDivisionError as e: + tb = e.__traceback__ + frames = [] + while tb: + frames.append(tb.tb_frame) + tb = tb.tb_next + return frames + + def test_locals(self): + f, outer, inner = self.make_frames() + outer_locals = outer.f_locals + self.assertIsInstance(outer_locals.pop('inner'), types.FunctionType) + self.assertEqual(outer_locals, {'x': 5, 'y': 6}) + inner_locals = inner.f_locals + self.assertEqual(inner_locals, {'x': 5, 'z': 7}) + + def test_clear_locals(self): + # Test f_locals after clear() (issue #21897) + f, outer, inner = self.make_frames() + outer.clear() + inner.clear() + self.assertEqual(outer.f_locals, {}) + self.assertEqual(inner.f_locals, {}) + + def test_locals_clear_locals(self): + # Test f_locals before and after clear() (to exercise caching) + f, outer, inner = self.make_frames() + outer.f_locals + inner.f_locals + outer.clear() + inner.clear() + self.assertEqual(outer.f_locals, {}) + self.assertEqual(inner.f_locals, {}) + + def test_main(): support.run_unittest(__name__) diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 6378d8c..da001f0 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -540,6 +540,10 @@ class _BasePurePathTest(object): self.assertRaises(ValueError, P('').with_name, 'd.xml') self.assertRaises(ValueError, P('.').with_name, 'd.xml') self.assertRaises(ValueError, P('/').with_name, 'd.xml') + self.assertRaises(ValueError, P('a/b').with_name, '') + self.assertRaises(ValueError, P('a/b').with_name, '/c') + self.assertRaises(ValueError, P('a/b').with_name, 'c/') + self.assertRaises(ValueError, P('a/b').with_name, 'c/d') def test_with_suffix_common(self): P = self.cls @@ -547,6 +551,9 @@ class _BasePurePathTest(object): self.assertEqual(P('/a/b').with_suffix('.gz'), P('/a/b.gz')) self.assertEqual(P('a/b.py').with_suffix('.gz'), P('a/b.gz')) self.assertEqual(P('/a/b.py').with_suffix('.gz'), P('/a/b.gz')) + # Stripping suffix + self.assertEqual(P('a/b.py').with_suffix(''), P('a/b')) + self.assertEqual(P('/a/b').with_suffix(''), P('/a/b')) # Path doesn't have a "filename" component self.assertRaises(ValueError, P('').with_suffix, '.gz') self.assertRaises(ValueError, P('.').with_suffix, '.gz') @@ -554,9 +561,12 @@ class _BasePurePathTest(object): # Invalid suffix self.assertRaises(ValueError, P('a/b').with_suffix, 'gz') self.assertRaises(ValueError, P('a/b').with_suffix, '/') + self.assertRaises(ValueError, P('a/b').with_suffix, '.') self.assertRaises(ValueError, P('a/b').with_suffix, '/.gz') self.assertRaises(ValueError, P('a/b').with_suffix, 'c/d') self.assertRaises(ValueError, P('a/b').with_suffix, '.c/.d') + self.assertRaises(ValueError, P('a/b').with_suffix, './.d') + self.assertRaises(ValueError, P('a/b').with_suffix, '.d/.') def test_relative_to_common(self): P = self.cls @@ -950,6 +960,10 @@ class PureWindowsPathTest(_BasePurePathTest, unittest.TestCase): self.assertRaises(ValueError, P('c:').with_name, 'd.xml') self.assertRaises(ValueError, P('c:/').with_name, 'd.xml') self.assertRaises(ValueError, P('//My/Share').with_name, 'd.xml') + self.assertRaises(ValueError, P('c:a/b').with_name, 'd:') + self.assertRaises(ValueError, P('c:a/b').with_name, 'd:e') + self.assertRaises(ValueError, P('c:a/b').with_name, 'd:/e') + self.assertRaises(ValueError, P('c:a/b').with_name, '//My/Share') def test_with_suffix(self): P = self.cls |