diff -r 135e1a8144ec Lib/test/support/__init__.py --- a/Lib/test/support/__init__.py Mon Jan 09 11:21:37 2017 +0100 +++ b/Lib/test/support/__init__.py Mon Jan 09 16:17:46 2017 +0100 @@ -91,9 +91,10 @@ "requires_IEEE_754", "skip_unless_xattr", "requires_zlib", "anticipate_failure", "load_package_tests", "detect_api_mismatch", "check__all__", "requires_android_level", "requires_multiprocessing_queue", + "supported_operation", # sys "is_jython", "is_android", "check_impl_detail", "unix_shell", - "setswitchinterval", "android_not_root", + "setswitchinterval", # network "HOST", "IPV6_ENABLED", "find_unused_port", "bind_port", "open_urlresource", "bind_unix_socket", @@ -784,7 +785,6 @@ except AttributeError: # sys.getandroidapilevel() is only available on Android is_android = False -android_not_root = (is_android and os.geteuid() != 0) if sys.platform != 'win32': unix_shell = '/system/bin/sh' if is_android else '/bin/sh' @@ -1823,6 +1823,14 @@ msg = "requires a functioning shared semaphore implementation" return test if _have_mp_queue else unittest.skip(msg)(test) +@contextlib.contextmanager +def supported_operation(): + """Context manager to skip tests when the operation is not supported.""" + try: + yield + except PermissionError as e: + raise unittest.SkipTest(str(e)) + def _parse_guards(guards): # Returns a tuple ({platform_name: run_me}, default_value) if not guards: diff -r 135e1a8144ec Lib/test/test_os.py --- a/Lib/test/test_os.py Mon Jan 09 11:21:37 2017 +0100 +++ b/Lib/test/test_os.py Mon Jan 09 16:17:46 2017 +0100 @@ -1695,7 +1695,8 @@ def _test_link(self, file1, file2): create_file(file1) - os.link(file1, file2) + with support.supported_operation(): + os.link(file1, file2) with open(file1, "r") as f1, open(file2, "r") as f2: self.assertTrue(os.path.sameopenfile(f1.fileno(), f2.fileno())) @@ -2793,7 +2794,8 @@ """ try: size = subprocess.check_output(['stty', 'size']).decode().split() - except (FileNotFoundError, subprocess.CalledProcessError): + except (FileNotFoundError, subprocess.CalledProcessError, + PermissionError): self.skipTest("stty invocation failed") expected = (int(size[1]), int(size[0])) # reversed order @@ -3147,7 +3149,8 @@ os.mkdir(dirname) filename = self.create_file("file.txt") if link: - os.link(filename, os.path.join(self.path, "link_file.txt")) + with support.supported_operation(): + os.link(filename, os.path.join(self.path, "link_file.txt")) if symlink: os.symlink(dirname, os.path.join(self.path, "symlink_dir"), target_is_directory=True)