Skip to content

Commit eb66897

Browse files
[2.7] bpo-30366: Backport tests for test.support. (#1582)
Also backport new functions temp_dir() and python_is_optimized(). temp_cwd() now accepts None as a name (means using tempfile.mkdtemp). check_syntax_error() now accepts arguments lineno and offset. Use more specific error messages in get_attribute().
1 parent 982a17e commit eb66897

File tree

2 files changed

+452
-35
lines changed

2 files changed

+452
-35
lines changed

Lib/test/support/__init__.py

Lines changed: 86 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import time
2323
import struct
2424
import sysconfig
25+
import types
2526
try:
2627
import thread
2728
except ImportError:
@@ -155,8 +156,17 @@ def get_attribute(obj, name):
155156
try:
156157
attribute = getattr(obj, name)
157158
except AttributeError:
158-
raise unittest.SkipTest("module %s has no attribute %s" % (
159-
obj.__name__, name))
159+
if isinstance(obj, types.ModuleType):
160+
msg = "module %r has no attribute %r" % (obj.__name__, name)
161+
elif isinstance(obj, types.ClassType):
162+
msg = "class %s has no attribute %r" % (obj.__name__, name)
163+
elif isinstance(obj, types.InstanceType):
164+
msg = "%s instance has no attribute %r" % (obj.__class__.__name__, name)
165+
elif isinstance(obj, type):
166+
msg = "type object %r has no attribute %r" % (obj.__name__, name)
167+
else:
168+
msg = "%r object has no attribute %r" % (type(obj).__name__, name)
169+
raise unittest.SkipTest(msg)
160170
else:
161171
return attribute
162172

@@ -705,6 +715,49 @@ def u(s):
705715
# Save the initial cwd
706716
SAVEDCWD = os.getcwd()
707717

718+
@contextlib.contextmanager
719+
def temp_dir(path=None, quiet=False):
720+
"""Return a context manager that creates a temporary directory.
721+
722+
Arguments:
723+
724+
path: the directory to create temporarily. If omitted or None,
725+
defaults to creating a temporary directory using tempfile.mkdtemp.
726+
727+
quiet: if False (the default), the context manager raises an exception
728+
on error. Otherwise, if the path is specified and cannot be
729+
created, only a warning is issued.
730+
731+
"""
732+
dir_created = False
733+
if path is None:
734+
import tempfile
735+
path = tempfile.mkdtemp()
736+
dir_created = True
737+
path = os.path.realpath(path)
738+
else:
739+
if (have_unicode and isinstance(path, unicode) and
740+
not os.path.supports_unicode_filenames):
741+
try:
742+
path = path.encode(sys.getfilesystemencoding() or 'ascii')
743+
except UnicodeEncodeError:
744+
if not quiet:
745+
raise unittest.SkipTest('unable to encode the cwd name with '
746+
'the filesystem encoding.')
747+
try:
748+
os.mkdir(path)
749+
dir_created = True
750+
except OSError:
751+
if not quiet:
752+
raise
753+
warnings.warn('tests may fail, unable to create temp dir: ' + path,
754+
RuntimeWarning, stacklevel=3)
755+
try:
756+
yield path
757+
finally:
758+
if dir_created:
759+
rmtree(path)
760+
708761
@contextlib.contextmanager
709762
def change_cwd(path, quiet=False):
710763
"""Return a context manager that changes the current working directory.
@@ -735,38 +788,21 @@ def change_cwd(path, quiet=False):
735788
@contextlib.contextmanager
736789
def temp_cwd(name='tempcwd', quiet=False):
737790
"""
738-
Context manager that creates a temporary directory and set it as CWD.
791+
Context manager that temporarily creates and changes the CWD.
792+
793+
The function temporarily changes the current working directory
794+
after creating a temporary directory in the current directory with
795+
name *name*. If *name* is None, the temporary directory is
796+
created using tempfile.mkdtemp.
797+
798+
If *quiet* is False (default) and it is not possible to
799+
create or change the CWD, an error is raised. If *quiet* is True,
800+
only a warning is raised and the original CWD is used.
739801
740-
The new CWD is created in the current directory and it's named *name*.
741-
If *quiet* is False (default) and it's not possible to create or change
742-
the CWD, an error is raised. If it's True, only a warning is raised
743-
and the original CWD is used.
744802
"""
745-
if (have_unicode and isinstance(name, unicode) and
746-
not os.path.supports_unicode_filenames):
747-
try:
748-
name = name.encode(sys.getfilesystemencoding() or 'ascii')
749-
except UnicodeEncodeError:
750-
if not quiet:
751-
raise unittest.SkipTest('unable to encode the cwd name with '
752-
'the filesystem encoding.')
753-
saved_dir = os.getcwd()
754-
is_temporary = False
755-
try:
756-
os.mkdir(name)
757-
os.chdir(name)
758-
is_temporary = True
759-
except OSError:
760-
if not quiet:
761-
raise
762-
warnings.warn('tests may fail, unable to change the CWD to ' + name,
763-
RuntimeWarning, stacklevel=3)
764-
try:
765-
yield os.getcwd()
766-
finally:
767-
os.chdir(saved_dir)
768-
if is_temporary:
769-
rmtree(name)
803+
with temp_dir(path=name, quiet=quiet) as temp_path:
804+
with change_cwd(temp_path, quiet=quiet) as cwd_dir:
805+
yield cwd_dir
770806

771807
# TEST_HOME_DIR refers to the top level directory of the "test" package
772808
# that contains Python's regression test suite
@@ -810,9 +846,14 @@ def make_bad_fd():
810846
file.close()
811847
unlink(TESTFN)
812848

813-
def check_syntax_error(testcase, statement):
814-
testcase.assertRaises(SyntaxError, compile, statement,
815-
'<test string>', 'exec')
849+
def check_syntax_error(testcase, statement, lineno=None, offset=None):
850+
with testcase.assertRaises(SyntaxError) as cm:
851+
compile(statement, '<test string>', 'exec')
852+
err = cm.exception
853+
if lineno is not None:
854+
testcase.assertEqual(err.lineno, lineno)
855+
if offset is not None:
856+
testcase.assertEqual(err.offset, offset)
816857

817858
def open_urlresource(url, check=None):
818859
import urlparse, urllib2
@@ -1785,3 +1826,13 @@ def disable_gc():
17851826
finally:
17861827
if have_gc:
17871828
gc.enable()
1829+
1830+
1831+
def python_is_optimized():
1832+
"""Find if Python was built with optimizations."""
1833+
cflags = sysconfig.get_config_var('PY_CFLAGS') or ''
1834+
final_opt = ""
1835+
for opt in cflags.split():
1836+
if opt.startswith('-O'):
1837+
final_opt = opt
1838+
return final_opt not in ('', '-O0', '-Og')

0 commit comments

Comments
 (0)