Windows Support: Testing Suite integration

Broaden support for execution of the test suite
on Windows.
General bug and review fixups
This commit is contained in:
John Parent
2022-03-16 16:41:34 -04:00
committed by Peter Scheibel
parent e63b4f752a
commit 4aee27816e
102 changed files with 771 additions and 1066 deletions

View File

@@ -1094,12 +1094,23 @@ def remove_linked_tree(path):
Parameters:
path (str): Directory to be removed
"""
# On windows, cleaning a Git stage can be an issue
# as git leaves readonly files that Python handles
# poorly on Windows. Remove readonly status and try again
def onerror(func, path, exe_info):
os.chmod(path, stat.S_IWUSR)
try:
func(path)
except Exception as e:
tty.warn(e)
pass
if os.path.exists(path):
if os.path.islink(path):
shutil.rmtree(os.path.realpath(path), True)
shutil.rmtree(os.path.realpath(path), onerror=onerror)
os.unlink(path)
else:
shutil.rmtree(path, True)
shutil.rmtree(path, onerror=onerror)
@contextmanager
@@ -1237,9 +1248,6 @@ def find(root, files, recursive=True):
return _find_non_recursive(root, files)
# here and in _find_non_recursive below we only take the first
# index to check for system path safety as glob handles this
# w.r.t. search_files
@system_path_filter
def _find_recursive(root, search_files):

View File

@@ -191,6 +191,7 @@ def is_valid(op):
return op == LockType.READ \
or op == LockType.WRITE
class Lock(object):
"""This is an implementation of a filesystem lock using Python's lockf.
@@ -617,6 +618,12 @@ def release_write(self, release_fn=None):
else:
return False
def cleanup(self):
if self._reads == 0 and self._writes == 0:
os.unlink(self.path)
else:
raise LockError("Attempting to cleanup active lock.")
def _get_counts_desc(self):
return '(reads {0}, writes {1})'.format(self._reads, self._writes) \
if tty.is_verbose() else ''

View File

@@ -395,7 +395,7 @@ def ioctl_gwinsz(fd):
return int(rc[0]), int(rc[1])
else:
if sys.version_info[0] < 3:
raise RuntimeError("""Terminal size not obtainable on Windows with a
Python version older than 3""")
raise RuntimeError("Terminal size not obtainable on Windows with a\
Python version older than 3")
rc = (os.environ.get('LINES', 25), os.environ.get('COLUMNS', 80))
return int(rc[0]), int(rc[1])

View File

@@ -418,6 +418,7 @@ def log_output(*args, **kwargs):
with log_output('logfile.txt', echo=True):
# do things ... output will be logged and printed out
The following is available on Unix only. No-op on Windows.
And, if you just want to echo *some* stuff from the parent, use
``force_echo``::
@@ -427,20 +428,11 @@ def log_output(*args, **kwargs):
with logger.force_echo():
# things here will be echoed *and* logged
Under the hood, we spawn a daemon and set up a pipe between this
process and the daemon. The daemon writes our output to both the
file and to stdout (if echoing). The parent process can communicate
with the daemon to tell it when and when not to echo; this is what
force_echo does. You can also enable/disable echoing by typing 'v'.
We try to use OS-level file descriptors to do the redirection, but if
stdout or stderr has been set to some Python-level file object, we
use Python-level redirection instead. This allows the redirection to
work within test frameworks like nose and pytest.
See individual log classes for more information.
This method is actually a factory serving a per platform
(nix vs windows) log_output class
(unix vs windows) log_output class
"""
if sys.platform == 'win32':
return winlog(*args, **kwargs)
@@ -449,29 +441,7 @@ def log_output(*args, **kwargs):
class nixlog(object):
"""Context manager that logs its output to a file.
In the simplest case, the usage looks like this::
with log_output('logfile.txt'):
# do things ... output will be logged
Any output from the with block will be redirected to ``logfile.txt``.
If you also want the output to be echoed to ``stdout``, use the
``echo`` parameter::
with log_output('logfile.txt', echo=True):
# do things ... output will be logged and printed out
And, if you just want to echo *some* stuff from the parent, use
``force_echo``::
with log_output('logfile.txt', echo=False) as logger:
# do things ... output will be logged
with logger.force_echo():
# things here will be echoed *and* logged
"""
Under the hood, we spawn a daemon and set up a pipe between this
process and the daemon. The daemon writes our output to both the
file and to stdout (if echoing). The parent process can communicate
@@ -748,7 +718,6 @@ def __init__(self, sys_attr):
self.libc = libc
self.c_stream = c_stdout
else:
# The original fd stdout points to. Usually 1 on POSIX systems for stdout.
self.libc = ctypes.CDLL(None)
self.c_stream = ctypes.c_void_p.in_dll(self.libc, self.sys_attr)
self.sys_stream = getattr(sys, self.sys_attr)
@@ -793,6 +762,12 @@ def close(self):
class winlog(object):
"""
Similar to nixlog, with underlying
functionality ported to support Windows.
Does not support the use of 'v' toggling as nixlog does.
"""
def __init__(self, file_like=None, echo=False, debug=0, buffer=False,
env=None, filter_fn=None):
self.env = env