From 5fb7e935090cc8adcd4ee714a69d732b2b711cf9 Mon Sep 17 00:00:00 2001 From: Erkan Ozgur Yilmaz Date: Wed, 5 Jun 2024 12:48:43 +0100 Subject: [PATCH] [#367] Fixed encoding errors in `DisplayCAL.worker.exec_cmd()` for Windows by setting the `PYTHONLEGACYWINDOWSSTDIO` environment variable. This is a temporary fix and the neccessary changes to allow `utf-8` encoding. [#367] Fixed `DisplayCAL.worker._safe_send()` for Windows. [#367] Updated `README.md` for Windows install instructions. --- DisplayCAL/display_cal.py | 1 + DisplayCAL/main.py | 4 +- DisplayCAL/wexpect.py | 211 +++++++++--------- DisplayCAL/worker.py | 102 ++++----- DisplayCAL/wxScriptingClient.py | 1 + DisplayCAL/wxenhancedplot.py | 12 +- DisplayCAL/wxwindows.py | 1 + README.md | 28 ++- misc/DisplayCAL.pyi.spec | 4 +- requirements-dev.txt | 4 +- requirements.txt | 3 + .../Python_3.10_Installation_Windows.jpg | Bin 0 -> 44545 bytes .../Python_3.9_Installation_Windows.jpg | Bin 0 -> 43819 bytes setup.cfg | 3 + setup.py | 1 + 15 files changed, 207 insertions(+), 168 deletions(-) create mode 100644 screenshots/Python_3.10_Installation_Windows.jpg create mode 100644 screenshots/Python_3.9_Installation_Windows.jpg diff --git a/DisplayCAL/display_cal.py b/DisplayCAL/display_cal.py index 8ce0e45b..0e4c3d3b 100644 --- a/DisplayCAL/display_cal.py +++ b/DisplayCAL/display_cal.py @@ -113,6 +113,7 @@ elif sys.platform == "darwin": from DisplayCAL import util_mac from DisplayCAL import wexpect +# import wexpect from DisplayCAL.argyll_cgats import ( cal_to_fake_profile, can_update_cal, diff --git a/DisplayCAL/main.py b/DisplayCAL/main.py index 2fe91119..d7fa7327 100644 --- a/DisplayCAL/main.py +++ b/DisplayCAL/main.py @@ -218,7 +218,7 @@ def _main(module, name, app_lock_file_name, probe_ports=True): lockfile.unlock() except EnvironmentError as exception: # This shouldn't happen - print("Warning - could not read lockfile %s:" % lockfilename, exception) + print(f"Warning - could not read lockfile {lockfilename}:", exception) if module not in multi_instance: # Check lockfile(s) and probe port(s) for lockfilename in [app_lock_file_name]: @@ -228,7 +228,7 @@ def _main(module, name, app_lock_file_name, probe_ports=True): pid, port = pids_ports[0] appsocket = AppSocket() if appsocket and port: - print("Connecting to %s..." % port) + print(f"Connecting to {port}...") if appsocket.connect(host, port): print("Connected to", port) # Other instance already running? diff --git a/DisplayCAL/wexpect.py b/DisplayCAL/wexpect.py index e25382f9..4be53930 100644 --- a/DisplayCAL/wexpect.py +++ b/DisplayCAL/wexpect.py @@ -64,18 +64,21 @@ $Id: pexpect.py 507 2007-12-27 02:40:52Z noah $ """ +import copy +import errno +import logging +import re import os -import sys -import time import select +import signal import string -import re import struct -import types -import errno -import traceback -import signal import subprocess +import sys +import tempfile +import time +import traceback +import types if sys.platform != "win32": import pty @@ -89,10 +92,55 @@ import pywintypes from win32com.shell.shellcon import CSIDL_APPDATA from win32com.shell.shell import SHGetSpecialFolderPath - from win32console import * - from win32process import * - from win32con import * - from win32gui import * + from win32console import ( + AllocConsole, + AttachConsole, + FreeConsole, + GetConsoleProcessList, + GetConsoleWindow, + GetStdHandle, + KEY_EVENT, + PyConsoleScreenBufferType, + PyCOORDType, + PyINPUT_RECORDType, + PySMALL_RECTType, + SetConsoleOutputCP, + SetConsoleTitle, + STD_INPUT_HANDLE + ) + from win32process import ( + CreateProcess, + GetCurrentProcessId, + GetExitCodeProcess, + GetStartupInfo, + GetWindowThreadProcessId, + ResumeThread, + SuspendThread, + TerminateProcess, + ) + from win32con import ( + CREATE_NEW_CONSOLE, + CREATE_NEW_PROCESS_GROUP, + CTRL_BREAK_EVENT, + FILE_SHARE_READ, + FILE_SHARE_WRITE, + GENERIC_READ, + GENERIC_WRITE, + OPEN_EXISTING, + PM_REMOVE, + PROCESS_QUERY_INFORMATION, + PROCESS_TERMINATE, + SW_HIDE, + SW_SHOW, + STARTF_USESHOWWINDOW, + STILL_ACTIVE, + THREAD_SUSPEND_RESUME, + WM_USER, + ) + from win32gui import ( + PeekMessage, + ShowWindow, + ) import win32api import win32file import winerror @@ -121,7 +169,6 @@ class ExceptionPexpect(Exception): """Base class for all exceptions raised by this module.""" def __init__(self, value): - self.value = value def __str__(self): @@ -248,7 +295,6 @@ def print_ticks(d): the child. 'extra_args' is not used by directly run(). It provides a way to pass data to a callback function through run() through the locals dictionary passed to a callback.""" - if timeout == -1: child = spawn(command, maxread=2000, logfile=logfile, cwd=cwd, env=env) else: @@ -313,15 +359,17 @@ def spawn( args = [] log("=" * 80) - log("Buffer size: %s" % maxread) + log(f"Buffer size: {maxread}") if searchwindowsize: - log("Search window size: %s" % searchwindowsize) - log("Timeout: %ss" % timeout) + log(f"Search window size: {searchwindowsize}") + log(f"Timeout: {timeout}s") if env: log("Environment:") for name in env: - log("\t%s=%s" % (name, env[name])) + log(f"\t{name}={env[name]}") if cwd: + if isinstance(cwd, bytes): + cwd = cwd.decode("utf-8") log(f"Working directory: {cwd}") log("Spawning {}".format(join_args([command] + args))) if sys.platform == "win32": @@ -505,7 +553,7 @@ def __init__( self.delayafterclose = 0.1 # Sets delay in close() method to allow kernel time to update process status. Time in seconds. self.delayafterterminate = 0.1 # Sets delay in terminate() method to allow kernel time to update process status. Time in seconds. self.softspace = False # File-like object. - self.name = "<" + repr(self) + ">" # File-like object. + self.name = f"<{repr(self)}>" # File-like object. self.encoding = None # File-like object. self.closed = True # File-like object. self.ocwd = os.getcwd() @@ -536,7 +584,6 @@ def __del__(self): objects, so they must be handled explicitly. If the child file descriptor was opened outside this class (passed to the constructor) then this does not close it.""" - if not self.closed: # It is possible for __del__ methods to execute during the # teardown of the Python VM itself. Thus, self.close() may @@ -695,7 +742,6 @@ def __fork_pty(self): http://mail.python.org/pipermail/python-dev/2003-May/035281.html """ - parent_fd, child_fd = os.openpty() if parent_fd < 0 or child_fd < 0: raise ExceptionPexpect("Error! Could not open pty with os.openpty().") @@ -725,7 +771,6 @@ def __pty_make_controlling_tty(self, tty_fd): """This makes the pseudo-terminal the controlling tty. This should be more portable than the pty.fork() function. Specifically, this should work on Solaris.""" - child_name = os.ttyname(tty_fd) # Disconnect from controlling tty if still connected. @@ -764,7 +809,6 @@ def __pty_make_controlling_tty(self, tty_fd): def fileno(self): # File-like object. """This returns the file descriptor of the pty for the child.""" - return self.child_fd def close(self, force=True): # File-like object. @@ -774,7 +818,6 @@ def close(self, force=True): # File-like object. behavior with files. Set force to True if you want to make sure that the child is terminated (SIGKILL is sent if the child ignores SIGHUP and SIGINT).""" - if not self.closed: self.flush() os.close(self.child_fd) @@ -794,14 +837,12 @@ def flush(self): # File-like object. """This does nothing. It is here to support the interface for a File-like object.""" - pass def isatty(self): # File-like object. """This returns True if the file descriptor is open and connected to a tty(-like) device, else False.""" - return os.isatty(self.child_fd) def waitnoecho(self, timeout=-1): @@ -822,7 +863,6 @@ def waitnoecho(self, timeout=-1): False. """ - if timeout == -1: timeout = self.timeout if timeout is not None: @@ -841,7 +881,6 @@ def getecho(self): """This returns the terminal echo mode. This returns True if echo is on or False if echo is off. Child applications that are expecting you to enter a password often set ECHO False. See waitnoecho().""" - attr = termios.tcgetattr(self.child_fd) if attr[3] & termios.ECHO: return True @@ -877,7 +916,6 @@ def setecho(self, state): p.expect (['abcd']) p.expect (['wxyz']) """ - self.child_fd attr = termios.tcgetattr(self.child_fd) if state: @@ -909,7 +947,6 @@ def read_nonblocking(self, size=1, timeout=-1): This is a wrapper around os.read(). It uses select.select() to implement the timeout.""" - if self.closed: raise ValueError("I/O operation on closed file in read_nonblocking().") @@ -982,7 +1019,6 @@ def read(self, size=-1): # File-like object. omitted, read all data until EOF is reached. The bytes are returned as a string object. An empty string is returned when EOF is encountered immediately.""" - if size == 0: return "" if size < 0: @@ -1011,7 +1047,6 @@ def readline(self, size=-1): # File-like object. is returned when EOF is hit immediately. Currently, the size argument is mostly ignored, so this behavior is not standard for a file-like object. If size is 0 then an empty string is returned.""" - if size == 0: return "" index = self.expect(["\r\n", self.delimiter]) # delimiter default is EOF @@ -1058,7 +1093,6 @@ def send(self, s): """This sends a string to the child process. This returns the number of bytes written. If a log file was set then the data is also written to the log.""" - time.sleep(self.delaybeforesend) if self.logfile is not None: self.logfile.write(s) @@ -1162,7 +1196,6 @@ def terminate(self, force=False): SIGHUP and SIGINT. If "force" is True then moves onto SIGKILL. This returns True if the child was terminated. This returns False if the child could not be terminated.""" - if not self.isalive(): return True try: @@ -1203,7 +1236,6 @@ def wait(self): child has unread output and has terminated. In other words, the child may have printed output then called exit(); but, technically, the child is still alive until its output is read.""" - if self.isalive(): pid, status = os.waitpid(self.pid, 0) else: @@ -1232,7 +1264,6 @@ def isalive(self): exitstatus or signalstatus of the child. This returns True if the child process appears to be running or False if not. It can take literally SECONDS for Solaris to return the right status.""" - if self.terminated: return False @@ -1300,17 +1331,14 @@ def isalive(self): return False def kill(self, sig): - """This sends the given signal to the child application. In keeping with UNIX tradition it has a misleading name. It does not necessarily kill the child unless you send the right signal.""" - # Same as os.kill, but the pid is given for you. if self.isalive(): os.kill(self.pid, sig) def compile_pattern_list(self, patterns): - """This compiles a pattern-string or a list of pattern-strings. Patterns must be a StringType, EOF, TIMEOUT, SRE_Pattern, or a list of those. Patterns may also be None which results in an empty list (you @@ -1333,7 +1361,6 @@ def compile_pattern_list(self, patterns): i = self.expect_list(clp, timeout) ... """ - if patterns is None: return [] if not isinstance(patterns, list): @@ -1435,7 +1462,6 @@ def expect(self, pattern, timeout=-1, searchwindowsize=None): If you are trying to optimize for speed then see expect_list(). """ - compiled_pattern_list = self.compile_pattern_list(pattern) return self.expect_list(compiled_pattern_list, timeout, searchwindowsize) @@ -1475,7 +1501,6 @@ def expect_loop(self, searcher, timeout=-1, searchwindowsize=-1): to search for in the input. See expect() for other arguments, return value and exceptions.""" - self.searcher = searcher end_time = -1 @@ -1506,7 +1531,7 @@ def expect_loop(self, searcher, timeout=-1, searchwindowsize=-1): c = self.read_nonblocking(self.maxread, timeout) freshlen = len(c) time.sleep(0.0001) - incoming = incoming + c.decode() + incoming = incoming + c #.decode() if timeout is not None: timeout = end_time - time.time() except EOF as e: @@ -1556,7 +1581,6 @@ def setwinsize(self, r, c): physical window size. It changes the size reported to TTY-aware applications like vi or curses -- applications that respond to the SIGWINCH signal.""" - # Check for buggy platforms. Some Python versions on some platforms # (notably OSF1 Alpha and RedHat 7.1) truncate the value for # termios.TIOCSWINSZ. It is not clear why this happens. @@ -1635,7 +1659,6 @@ def __interact_copy( self, escape_character=None, input_filter=None, output_filter=None ): """This is used by the ``interact()`` method.""" - while self.isalive(): r, w, e = self.__select([self.child_fd, self.STDIN_FILENO], [], []) if self.child_fd in r: @@ -1665,7 +1688,6 @@ def __select(self, iwtd, owtd, ewtd, timeout=None): select.select raises a select.error exception and errno is an EINTR error then it is ignored. Mainly this is used to ignore sigwinch (terminal resize).""" - # if select() is interrupted by a signal (errno==EINTR) then # we loop back and enter the select() again. end_time = -1 @@ -1753,7 +1775,7 @@ def __init__( self.delayafterclose = 0.1 # Sets delay in close() method to allow kernel time to update process status. Time in seconds. self.delayafterterminate = 0.1 # Sets delay in terminate() method to allow kernel time to update process status. Time in seconds. self.softspace = False # File-like object. - self.name = "<" + repr(self) + ">" # File-like object. + self.name = f"<{repr(self)}>" # File-like object. self.encoding = None # File-like object. self.closed = True # File-like object. self.ocwd = os.getcwd() @@ -1762,6 +1784,7 @@ def __init__( self.codepage = codepage self.columns = columns self.rows = rows + self.wtty = None if args is None: args = [] @@ -1791,7 +1814,6 @@ def _spawn(self, command, args=None): fork/exec type of stuff for a pty. This is called by __init__. If args is empty then command will be parsed (split on spaces) and args will be set to parsed arguments.""" - if args is None: args = [] @@ -1832,7 +1854,7 @@ def _spawn(self, command, args=None): self.command = command_with_path self.args[0] = self.command - self.name = "<" + " ".join(self.args) + ">" + self.name = f'<{" ".join(self.args)}>' # assert self.pid is None, 'The pid member should be None.' # assert self.command is not None, 'The command member should not be None.' @@ -1905,7 +1927,6 @@ def read_nonblocking(self, size=1, timeout=-1): timeout = self.timeout s = self.wtty.read_nonblocking(timeout, size) - if s == "": if not self.wtty.isalive(): self.flag_eof = True @@ -1956,7 +1977,6 @@ def sendintr(self): def terminate(self, force=False): """Terminate the child. Force not used.""" - if not self.isalive(): return True @@ -1969,7 +1989,6 @@ def terminate(self, force=False): def kill(self, sig): """Sig == sigint for ctrl-c otherwise the child is terminated.""" - if sig == signal.SIGINT: self.wtty.sendintr() else: @@ -1982,7 +2001,6 @@ def wait(self): may have printed output then called exit(); but, technically, the child is still alive until its output is read. """ - if not self.isalive(): raise ExceptionPexpect("Cannot wait for dead child process.") @@ -1996,7 +2014,6 @@ def wait(self): def isalive(self): """Determines if the child is still alive.""" - if self.terminated: return False @@ -2030,12 +2047,9 @@ def stop_interact(self): self.wtty.stop_interact() -############################################################################## -# End of spawn_windows class -############################################################################## - +class Wtty(object): + """""" -class Wtty: def __init__(self, timeout=30, codepage=None, columns=None, rows=None, cwd=None): self.__buffer = StringIO() self.__bufferY = 0 @@ -2051,8 +2065,10 @@ def __init__(self, timeout=30, codepage=None, columns=None, rows=None, cwd=None) or windll.kernel32.GetConsoleOutputCP() or windll.kernel32.GetOEMCP() ) - log("Code page: %s" % self.codepage) + log(f"Code page: {self.codepage}") self.columns = columns + if isinstance(cwd, bytes): + cwd = cwd.decode("utf-8") self.cwd = cwd self.rows = rows self.console = False @@ -2094,12 +2110,10 @@ def spawn(self, command, args=None, env=None): time.sleep(0.05) if not self.__childProcess: - raise ExceptionPexpect("The process " + args[0] + " could not be started.") + raise ExceptionPexpect(f"The process {args[0]} could not be started.") winHandle = int(GetConsoleWindow()) - self.__switch = True - if winHandle != 0: self.__parentPid = GetWindowThreadProcessId(winHandle)[1] # Do we have a console attached? Do not rely on winHandle, because @@ -2117,7 +2131,7 @@ def spawn(self, command, args=None, env=None): def startChild(self, args, env): si = GetStartupInfo() si.dwFlags = STARTF_USESHOWWINDOW - si.wShowWindow = SW_HIDE + si.wShowWindow = SW_HIDE # SW_SHOW # Determine the directory of wexpect.py or, if we are running 'frozen' # (eg. py2exe deployment), of the packed executable dirname = os.path.dirname( @@ -2157,7 +2171,8 @@ def startChild(self, args, env): " ".join(pyargs), "import sys; sys.path = %s + sys.path;" "args = %s; from DisplayCAL import wexpect;" - "wexpect.ConsoleReader(wexpect.join_args(args), %i, %i, cp=%i, c=%s, r=%s, logdir=%r)" + # "args = %s; import wexpect;" + "wexpect.ConsoleReader(wexpect.join_args(args), %i, %i, cp='%s', c=%s, r=%s, logdir=%r)" % ( ("%r" % spath).replace('"', r"\""), ("%r" % args).replace('"', r"\""), @@ -2172,12 +2187,19 @@ def startChild(self, args, env): log(commandLine) self.__oproc, _, self.conpid, self.__otid = CreateProcess( - None, commandLine, None, None, False, CREATE_NEW_CONSOLE, env, self.cwd, si + None, + commandLine, + None, + None, + False, + CREATE_NEW_CONSOLE, + env, + self.cwd, + si ) def switchTo(self, attached=True): - """Releases from the current console and attatches - to the childs.""" + """Release from the current console and attatches to the childs.""" if not self.__switch or not self.__oproc_isalive(): return @@ -2191,7 +2213,6 @@ def switchTo(self, attached=True): def switchBack(self): """Releases from the current console and attaches to the parents.""" - if not self.__switch or not self.__oproc_isalive(): return @@ -2237,7 +2258,6 @@ def terminate_child(self): def createKeyEvent(self, char): """Creates a single key record corresponding to the ascii character char.""" - evt = PyINPUT_RECORDType(KEY_EVENT) evt.KeyDown = True evt.Char = char @@ -2248,7 +2268,6 @@ def createKeyEvent(self, char): def write(self, s): """Writes input into the child consoles input buffer.""" - if len(s) == 0: return 0 records = [self.createKeyEvent(c) for c in str(s)] @@ -2275,8 +2294,7 @@ def getOffset(self, x, y): return x + y * consinfo["Size"].X def readConsole(self, startCo, endCo): - """Reads the console area from startCo to endCo and returns it - as a string.""" + """Reads the console area from startCo to endCo and returns it as a string.""" buff = [] self.lastRead = 0 @@ -2301,7 +2319,7 @@ def readConsole(self, startCo, endCo): self.totalRead += ln buff.append(s) - startCo.X, startCo.Y = endPoint[0], endPoint[1] + startCo.X, startCo.Y = int(endPoint[0]), int(endPoint[1]) if readlen <= 0 or (startCo.X >= endX and startCo.Y >= endY): break @@ -2311,7 +2329,6 @@ def parseData(self, s): """Ensures that special characters are interpreted as newlines or blanks, depending on if there written over characters or screen-buffer-fill characters.""" - consinfo = self.__consout.GetConsoleScreenBufferInfo() strlist = [] for i, c in enumerate(s): @@ -2321,12 +2338,12 @@ def parseData(self, s): s = "\r\n".join([line.rstrip(" ") for line in "".join(strlist).split("\r\n")]) try: - return s.encode("cp%i" % self.codepage, "replace") + return s #.encode("cp%i" % self.codepage, "replace") except LookupError: - return s.encode( - getattr(sys.stdout, "encoding", None) or sys.getdefaultencoding(), - "replace", - ) + return s #.encode( + # getattr(sys.stdout, "encoding", None) or sys.getdefaultencoding(), + # "replace", + #) def readConsoleToCursor(self): """Reads from the current read position to the current cursor @@ -2437,7 +2454,7 @@ def read_nonblocking(self, timeout, size): reset = True time.sleep(0.2) - start = time.clock() + start = time.time() s = self.readConsoleToCursor() if reset: @@ -2465,7 +2482,7 @@ def read_nonblocking(self, timeout, size): time.sleep(0.1) time.sleep(0.001) - end = time.clock() + end = time.time() timeout -= end - start except Exception as e: @@ -2478,7 +2495,6 @@ def refreshConsole(self): """Clears the console after pausing the child and reading all the data currently on the console. The last line before clearing becomes the first line after clearing.""" - consinfo = self.__consout.GetConsoleScreenBufferInfo() cursorPos = consinfo["CursorPosition"] startCo = PyCOORDType(0, cursorPos.Y) @@ -2514,7 +2530,6 @@ def setecho(self, state): def getecho(self): """Returns the echo mode of the child console.""" - self.switchTo() try: mode = self.__consin.GetConsoleMode() @@ -2528,7 +2543,6 @@ def getecho(self): def getwinsize(self): """Returns the size of the child console as a tuple of (rows, columns).""" - self.switchTo() try: size = self.__consout.GetConsoleScreenBufferInfo()["Size"] @@ -2595,23 +2609,22 @@ class ConsoleReader(object): def __init__(self, path, pid, tid, env=None, cp=None, c=None, r=None, logdir=None): self.logdir = logdir log("=" * 80, "consolereader", logdir) - log("OEM code page: %s" % windll.kernel32.GetOEMCP(), "consolereader", logdir) + log(f"OEM code page: {windll.kernel32.GetOEMCP()}", "consolereader", logdir) consolecp = windll.kernel32.GetConsoleOutputCP() - log("Console output code page: %s" % consolecp, "consolereader", logdir) + log(f"Console output code page: {consolecp}", "consolereader", logdir) if consolecp != cp: - log("Setting console output code page to %s" % cp, "consolereader", logdir) + log(f"Setting console output code page to {cp}", "consolereader", logdir) try: SetConsoleOutputCP(cp) except Exception as e: log(e, "consolereader_exceptions", logdir) else: log( - "Console output code page: %s" - % windll.kernel32.GetConsoleOutputCP(), + f"Console output code page: {windll.kernel32.GetConsoleOutputCP()}", "consolereader", logdir, ) - log("Spawning %s" % path, "consolereader", logdir) + log(f"Spawning {path}", "consolereader", logdir) try: try: consout = self.getConsoleOut() @@ -2619,13 +2632,15 @@ def __init__(self, path, pid, tid, env=None, cp=None, c=None, r=None, logdir=Non SetConsoleTitle(path) si = GetStartupInfo() + # si.dwFlags = STARTF_USESHOWWINDOW + # si.wShowWindow = SW_SHOW self.__childProcess, _, childPid, self.__tid = CreateProcess( None, path, None, None, False, - CREATE_NEW_PROCESS_GROUP, + CREATE_NEW_PROCESS_GROUP, # | CREATE_NEW_CONSOLE, None, None, si, @@ -2665,7 +2680,7 @@ def __init__(self, path, pid, tid, env=None, cp=None, c=None, r=None, logdir=Non # log('suspendThread', 'consolereader', logdir) self.suspendThread() paused = True - SetConsoleTitle(path + " (suspended)") + SetConsoleTitle(f"{path} (suspended)") # Hide cursor consout.SetConsoleCursorInfo(cursorinfo[0], 0) @@ -2683,7 +2698,7 @@ def __init__(self, path, pid, tid, env=None, cp=None, c=None, r=None, logdir=Non # Only let child react to CTRL+C, ignore in ConsoleReader pass - SetConsoleTitle(path + " (terminated)") + SetConsoleTitle(f"ConsoleReader: {path} (terminated)") consout.SetConsoleCursorInfo(cursorinfo[0], 0) # Hide cursor while GetExitCodeProcess(parent) == STILL_ACTIVE: @@ -2691,7 +2706,7 @@ def __init__(self, path, pid, tid, env=None, cp=None, c=None, r=None, logdir=Non except Exception as e: log(e, "consolereader_exceptions", logdir) - def handler(self, sig): + def handler(self, sig, logdir): log(sig, "consolereader", logdir) return False @@ -2726,13 +2741,11 @@ def initConsole(self, consout, c=None, r=None): def suspendThread(self): """Pauses the main thread of the child process.""" - handle = windll.kernel32.OpenThread(THREAD_SUSPEND_RESUME, 0, self.__tid) SuspendThread(handle) def resumeThread(self): """Un-pauses the main thread of the child process.""" - handle = windll.kernel32.OpenThread(THREAD_SUSPEND_RESUME, 0, self.__tid) ResumeThread(handle) @@ -2757,7 +2770,6 @@ def __init__(self, strings): """This creates an instance of searcher_string. This argument 'strings' may be a list; a sequence of strings; or the EOF or TIMEOUT types. """ - self.eof_index = -1 self.timeout_index = -1 self._strings = [] @@ -2793,7 +2805,6 @@ def search(self, buffer, freshlen, searchwindowsize=None): If there is a match this returns the index of that string, and sets 'start', 'end' and 'match'. Otherwise, this returns -1.""" - absurd_match = len(buffer) first_match = absurd_match @@ -2891,7 +2902,8 @@ def search(self, buffer, freshlen, searchwindowsize=None): See class spawn for the 'searchwindowsize' argument. If there is a match this returns the index of that string, and sets - 'start', 'end' and 'match'. Otherwise, returns -1.""" + 'start', 'end' and 'match'. Otherwise, returns -1. + """ absurd_match = len(buffer) first_match = absurd_match the_match = None @@ -3005,7 +3017,6 @@ def which(filename): then checks if it is executable. This returns the full path to the filename if found and executable. Otherwise this returns None. """ - # Special case where filename already contains a path. if os.path.dirname(filename) != "": if os.access(filename, os.X_OK): diff --git a/DisplayCAL/worker.py b/DisplayCAL/worker.py index 05aaa407..448db267 100644 --- a/DisplayCAL/worker.py +++ b/DisplayCAL/worker.py @@ -75,6 +75,7 @@ from DisplayCAL import imfile from DisplayCAL import localization as lang from DisplayCAL import wexpect +# import wexpect from DisplayCAL.argyll_cgats import ( add_dispcal_options_to_cal, add_options_to_ti3, @@ -2395,7 +2396,7 @@ def add_measurement_features( if ( (self.argyll_version <= [1, 0, 4] and not get_arg("-p", args)) or (self.argyll_version > [1, 0, 4] and not get_arg("-P", args)) - and "-d%s" % self.argyll_virtual_display not in args + and f"-d{self.argyll_virtual_display}" not in args ): if ( config.get_display_name() == "Resolve" or non_argyll_prisma @@ -3328,7 +3329,7 @@ def check_instrument_sensor_position(self, txt): if "read failed due to the sensor being in the wrong position" in txt.lower(): self.instrument_sensor_position_msg = True if self.instrument_sensor_position_msg and " or q to " in txt.lower(): - self.log("%s: Detected read failed due to wrong sensor position" % appname) + self.log(f"{appname}: Detected read failed due to wrong sensor position") self.instrument_sensor_position_msg = False self.instrument_reposition_sensor() @@ -6898,7 +6899,7 @@ def exec_cmd( "Warning - error during shell script creation:", str(exception) ) cmdline = [safe_str(arg, fs_enc) for arg in cmdline] - working_dir = None if not working_dir else working_dir.encode(fs_enc) + working_dir = None if not working_dir else working_dir try: if not self.measure_cmd and self.argyll_version >= [1, 2]: # Argyll tools will no longer respond to keys @@ -6920,41 +6921,37 @@ def exec_cmd( ("MIN_DISPLAY_UPDATE_DELAY_MS", [1, 5]), ("DISPLAY_SETTLE_TIME_MULT", [1, 7]), ): - backup = os.getenv("ARGYLL_%s_BACKUP" % name) + backup = os.getenv(f"ARGYLL_{name}_BACKUP") value = None if ( - getcfg("measure.override_%s" % name.lower()) + getcfg(f"measure.override_{name.lower()}") and self.argyll_version >= version ): if backup is None: # Backup current value if any - current = os.getenv("ARGYLL_%s" % name, "") - os.environ["ARGYLL_%s_BACKUP" % name] = current + current = os.getenv(f"ARGYLL_{name}", "") + os.environ[f"ARGYLL_{name}_BACKUP"] = current else: current = backup if current: - self.log( - "%s: Overriding ARGYLL_%s %s" % (appname, name, current) - ) + self.log(f"{appname}: Overriding ARGYLL_{name} {current}") # Override - value = str(getcfg("measure.%s" % name.lower())) - self.log("%s: Setting ARGYLL_%s %s" % (appname, name, value)) + value = str(getcfg(f"measure.{name.lower()}")) + self.log(f"{appname}: Setting ARGYLL_{name} {value}") elif backup is not None: value = backup - del os.environ["ARGYLL_%s_BACKUP" % name] + del os.environ[f"ARGYLL_{name}_BACKUP"] if value: - self.log( - "%s: Restoring ARGYLL_%s %s" % (appname, name, value) - ) - elif "ARGYLL_%s" % name in os.environ: - del os.environ["ARGYLL_%s" % name] - elif "ARGYLL_%s" % name in os.environ: + self.log(f"{appname}: Restoring ARGYLL_{name} {value}") + elif f"ARGYLL_{name}" in os.environ: + del os.environ[f"ARGYLL_{name}"] + elif f"ARGYLL_{name}" in os.environ: self.log( - "%s: ARGYLL_%s" % (appname, name), - os.getenv("ARGYLL_%s" % name), + f"{appname}: ARGYLL_{name}", + os.getenv(f"ARGYLL_{name}"), ) if value: - os.environ["ARGYLL_%s" % name] = value + os.environ[f"ARGYLL_{name}"] = value elif cmdname in ( get_argyll_utilname("iccgamut"), get_argyll_utilname("tiffgamut"), @@ -6993,6 +6990,8 @@ def exec_cmd( data_encoding = self.pty_encoding kwargs = dict(timeout=20, cwd=working_dir, env=os.environ) if sys.platform == "win32": + # FIX: stdio cp1252 vs utf-8 issue under Windows 10/11+ + os.environ["PYTHONLEGACYWINDOWSSTDIO"] = "1" kwargs["codepage"] = windll.kernel32.GetACP() # As Windows' console always hard wraps at the # rightmost column, increase the buffer width @@ -7078,13 +7077,17 @@ def exec_cmd( # Minimum Windows version: XP or Server 2003 if sys.platform == "win32" and sys.getwindowsversion() < (5, 1): raise Error(lang.getstr("windows.version.unsupported")) + try: + # print(f"cmdline: {cmdline}") + # print(f"kwargs : {kwargs}") self.subprocess = wexpect.spawn( cmdline[0], cmdline[1:], **kwargs ) except wexpect.ExceptionPexpect as exception: self.retcode = -1 raise Error(str(exception)) + if sys.platform == "darwin" and self.measure_cmd: # Caffeinate (prevent sleep/screensaver) caffeinate = which("caffeinate") @@ -7140,10 +7143,10 @@ def caffeinate_wait(): if self.measure_cmd: keyhit_strs = [" or Q to ", r"8\) Exit"] patterns = keyhit_strs + ["Current", r" \d+ of \d+"] - self.log("%s: Starting interaction with subprocess" % appname) + self.log(f"{appname}: Starting interaction with subprocess") else: patterns = [] - self.log("%s: Waiting for EOF" % appname) + self.log(f"{appname}: Waiting for EOF") loop = 0 pwdsent = False authfailed = False @@ -7159,12 +7162,12 @@ def caffeinate_wait(): curpatterns + [wexpect.EOF, wexpect.TIMEOUT], timeout=1 ) if self.subprocess.after is wexpect.EOF: - self.log("%s: Reached EOF (OK)" % appname) + self.log(f"{appname}: Reached EOF (OK)") break elif self.subprocess.after is wexpect.TIMEOUT: if not self.subprocess.isalive(): self.log( - "%s: Subprocess no longer alive (timeout)" % appname + f"{appname}: Subprocess no longer alive (timeout)" ) if eof: break @@ -7185,25 +7188,22 @@ def caffeinate_wait(): break continue elif self.measure_cmd: - if [ keyhit_str for keyhit_str in keyhit_strs if re.search(keyhit_str, self.subprocess.after) ]: # Wait for the keypress - self.log("%s: Waiting for send buffer" % appname) + self.log(f"{appname}: Waiting for send buffer") while not self.send_buffer: if not self.subprocess.isalive(): self.log( - "%s: Subprocess no longer alive (unknown reason)" - % appname + f"{appname}: Subprocess no longer alive (unknown reason)" ) break sleep(0.05) self.log( - "%s: Send buffer received: %s" - % (appname, self.send_buffer) + f"{appname}: Send buffer received: {self.send_buffer}" ) if ( self.send_buffer is not None @@ -7216,10 +7216,7 @@ def caffeinate_wait(): ): # Restore madTPG OSD and fullscreen self.madtpg_restore_settings(False) - self.log( - "%s: Sending buffer: %r" - % (appname, self.send_buffer) - ) + self.log(f"{appname}: Sending buffer: {self.send_buffer}") self._safe_send(self.send_buffer) self.send_buffer = None if not self.subprocess.isalive(): @@ -7229,10 +7226,10 @@ def caffeinate_wait(): # We can't use wait() because it might block in the # case of a timeout if self.subprocess.isalive(): - self.log("%s: Checking subprocess status" % appname) + self.log(f"{appname}: Checking subprocess status") while self.subprocess.isalive(): sleep(0.1) - self.log("%s: Subprocess no longer alive (OK)" % appname) + self.log(f"{appname}: Subprocess no longer alive (OK)") self.retcode = self.subprocess.exitstatus if authfailed: raise Error(lang.getstr("auth.failed")) @@ -7410,13 +7407,13 @@ def caffeinate_wait(): self.log(cd_exception) profiling_inhibit = False else: - self.log(appname + ": Uninhibited display device") + self.log(f"{appname}: Uninhibited display device") if not profiling_inhibit: # Fallback - restore display profile - self.log(appname + ": Re-assigning display profile...") + self.log(f"{appname}: Re-assigning display profile...") cdinstall = self._attempt_install_profile_colord(display_profile) if cdinstall is True: - self.log(appname + ": Successfully re-assigned display profile") + self.log(f"{appname}: Successfully re-assigned display profile") elif not cdinstall: self.log(lang.getstr("calibration.load_error")) # Remove temp sRGB profile @@ -8769,7 +8766,6 @@ def get_display(self): """Get the currently configured display. Returned is the Argyll CMS dispcal/dispread -d argument - """ display_name = config.get_display_name(None, True) if display_name == "Web @ localhost": @@ -13510,8 +13506,9 @@ def prepare_dispcal(self, calibrate=True, verify=False, dry_run=False): else: args.append("-w%s,%s" % (whitepoint_x, whitepoint_y)) luminance = getcfg("calibration.luminance", False) - if luminance: - args.append("-b%s" % luminance) + self.log(f"{appname}: luminance: {luminance}") + if luminance is not None: + args.append("-b{luminance}") if getcfg("trc"): args.append("-" + getcfg("trc.type") + str(getcfg("trc"))) args.append("-f%s" % getcfg("calibration.black_output_offset")) @@ -13550,7 +13547,9 @@ def prepare_dispcal(self, calibrate=True, verify=False, dry_run=False): # above zero device input if set up correctly. Using this option # with a display that is not well behaved may result in a loss # of shadow detail. - args.append("-b") + self.log("skipping -b parameter") + # args.append("-b") + pass if verify: if calibrate and type(verify) == int: args.append("-e%s" % verify) # Verify final computed curves @@ -13588,7 +13587,6 @@ def prepare_dispread(self, apply_calibration=True): either the previously by dispcal created one by passing in True, by passing in a valid path to a .cal file, or by passing in None (current video card gamma table). - """ self.lastcmdname = get_argyll_utilname("dispread") inoutfile = self.setup_inout() @@ -14447,7 +14445,7 @@ def safe_send(self, bytes_): return True def _safe_send(self, bytes_, retry=3, obfuscate=False): - """Safely send a keystroke to the current subprocess""" + """Safely send a keystroke to the current subprocess.""" for i in range(0, retry): if obfuscate: logbytes = "***" @@ -14455,11 +14453,15 @@ def _safe_send(self, bytes_, retry=3, obfuscate=False): logbytes = bytes_ self.logger.info("Sending key(s) %r (%i)" % (logbytes, i + 1)) try: - self.subprocess.send(bytes_.encode()) + if sys.platform == "win32": + # directly send the bytes_ without encoding to anything + self.subprocess.send(bytes_) + else: + # for Linux and MacOS encode to bytes + self.subprocess.send(bytes_.encode()) except Exception as exception: self.logger.exception("Exception: %s" % str(exception)) else: - # if wrote == len(bytes_): return True sleep(0.25) return False @@ -17029,7 +17031,7 @@ def wrapup(self, copy=True, remove=True, dst_path=None, ext_filter=None): ) else: if verbose >= 2: - print(appname + ": Removing temporary file", src) + print(f"{appname}: Removing temporary file", src) try: os.remove(src) except Exception as exception: diff --git a/DisplayCAL/wxScriptingClient.py b/DisplayCAL/wxScriptingClient.py index 0904ec25..5f6b8d88 100644 --- a/DisplayCAL/wxScriptingClient.py +++ b/DisplayCAL/wxScriptingClient.py @@ -12,6 +12,7 @@ from DisplayCAL.meta import name as appname from DisplayCAL.util_str import safe_str, universal_newlines from DisplayCAL.wexpect import split_command_line +# from wexpect import split_command_line from DisplayCAL.wxaddons import wx from DisplayCAL.wxfixes import GenBitmapButton from DisplayCAL.wxwindows import BaseApp, SimpleTerminal, numpad_keycodes diff --git a/DisplayCAL/wxenhancedplot.py b/DisplayCAL/wxenhancedplot.py index 0314c383..0c569293 100755 --- a/DisplayCAL/wxenhancedplot.py +++ b/DisplayCAL/wxenhancedplot.py @@ -807,10 +807,10 @@ def getTitle(self, title=""): def draw(self, dc): for o in self.objects: - # t=_time.clock() # profile info + # t=_time.time() # profile info o._pointSize = self._pointSize o.draw(dc, self.printerScale) - # dt= _time.clock()-t + # dt= _time.time() - t # print o, "time=", dt def getSymExtent(self, printerScale): @@ -1790,7 +1790,7 @@ def _Draw(self, graphics, xAxis=None, yAxis=None, dc=None): # Draw extras self._drawExtras(dc, p1, p2, scale, shift) # Draw the lines and markers - # start = _time.clock() + # start = _time.time() graphics.draw(dc) # draw legend makers and text (if inside) so that it overlaps graphics @@ -1800,7 +1800,7 @@ def _Draw(self, graphics, xAxis=None, yAxis=None, dc=None): dc, graphics, rhsW, topH, legendBoxWH, legendSymExt, legendTextExt ) - # print "entire graphics drawing took: %f second"%(_time.clock() - start) + # print "entire graphics drawing took: %f second"%(_time.time() - start) # remove the clipping region dc.DestroyClippingRegion() @@ -3146,10 +3146,10 @@ def OnPlotDraw4(self, event): self.client.Draw(drawObj) # # profile - # start = _time.clock() + # start = _time.time() # for x in range(10): # self.client.Draw(drawObj) - # print "10 plots of Draw4 took: %f sec."%(_time.clock() - start) + # print "10 plots of Draw4 took: %f sec."%(_time.time() - start) # # profile end def OnPlotDraw5(self, event): diff --git a/DisplayCAL/wxwindows.py b/DisplayCAL/wxwindows.py index 49435bbf..270ff2f9 100644 --- a/DisplayCAL/wxwindows.py +++ b/DisplayCAL/wxwindows.py @@ -76,6 +76,7 @@ EVT_BETTERTIMER, ) from DisplayCAL.wexpect import split_command_line +# from wexpect import split_command_line from DisplayCAL.wxfixes import ( GenBitmapButton, GenButton, diff --git a/README.md b/README.md index 5ecccada..eb632efe 100644 --- a/README.md +++ b/README.md @@ -129,12 +129,20 @@ How To Install (Windows) Windows version is currently not working properly. But here is the installation procedure: -1- Download and install Python: +1- Download and install Python 3.9: - Preferrebly install Python 3.11: https://www.python.org/downloads/windows/ + Install Python 3.9: + https://www.python.org/ftp/python/3.9.13/python-3.9.13-amd64.exe + https://www.python.org/ftp/python/3.10.11/python-3.10.11-amd64.exe + + Wexpect (a Python library that DisplayCAL depends on) is not working properly with + newer Python versions like Python 3.11 and 3.12. So, stick with Python 3.9 until we + find a solution. Also don't forget to select "Add Python to environment variables" in the installer. + ![image](screenshots/Python_3.9_Installation_Windows.jpg) + 2- Download and install Visual Studio Build Tools: Download from https://visualstudio.microsoft.com/visual-cpp-build-tools/ @@ -157,6 +165,16 @@ Windows version is currently not working properly. But here is the installation python displaycal ``` +> [!Warning] +> Under Windows use the system Python installation instead of a virtual environment as +> Wexpect module cannot read ArgyllCMS command outputs from inside a virtual +> environment. + +> [!Warning] +> Under Windows don't run DisplayCAL inside the IDE (Vscode, Pycharm etc.) terminal as +> most of the IDE's are creating virtual terminals and it is not possible to capture the +> command outputs. + An installer will later be supplied for Windows. Manually Setup @@ -207,11 +225,9 @@ Here are some ideas on where to focus the future development effort: work, with the latest commits we have around 200 tests (which is super low, should be thousands) and the code coverage is around 26% (again this is super low, should be over 99%). -- Replace the ``wexpect.py`` with the latest release of ``Pexpect``. There is no comment +- Replace the ``wexpect.py`` with the latest release of ``Wexpect``. There is no comment in the code on why we have a ``wexpect.py`` instead of using the PyPI version of - ``Pexpect``. Update: we believe it is because ``Pexpect`` doesn't support Windows. - Then it is a good idea to port the DisplayCAL implementation to the ``Pexpect`` - project. + ``Wexpect``. - Replace ``os.path`` related code with ``pathlib.Path`` class. - Organize the module structure, move UI related stuff in to ``ui`` module etc., move data files into their own folders. diff --git a/misc/DisplayCAL.pyi.spec b/misc/DisplayCAL.pyi.spec index d779ccba..7423743e 100644 --- a/misc/DisplayCAL.pyi.spec +++ b/misc/DisplayCAL.pyi.spec @@ -124,8 +124,8 @@ if sys.platform == 'win32': python = os.path.join(build_dir, 'python') with open(python, 'wb') as py: py.write('\n'.join(['if __name__ == "__main__":', - ' import %s.wexpect' % appname, - ' sys.modules["wexpect"] = sys.modules["%s.wexpect"]' % appname, + f' import {appname}.wexpect', + f' sys.modules["wexpect"] = sys.modules["{appname}.wexpect"]', ' for i, arg in enumerate(sys.argv[1:]):', ' if arg == "-c":', ' exec("".join(sys.argv[i + 2]))'])) diff --git a/requirements-dev.txt b/requirements-dev.txt index 5fb5f3df..e52c6c81 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -10,7 +10,8 @@ flake8-pep3101 flake8-spellcheck matplotlib ppdir -py2app +py2app; sys_platform=='darwin' +py2exe; sys_platform=='win32' pyglet pytest pytest-cov @@ -19,5 +20,4 @@ pytest-xdist snowballstemmer twine yappi -py2app wheel diff --git a/requirements.txt b/requirements.txt index dda44726..2260e2a1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,13 @@ build certifi +comtypes; sys_platform=='win32' dbus-python; sys_platform=='linux' distro numpy Pillow PyChromecast +pywin32; sys_platform=='win32' Send2Trash +#wexpect; sys_platform=='win32' wxPython>=4.1.1 zeroconf diff --git a/screenshots/Python_3.10_Installation_Windows.jpg b/screenshots/Python_3.10_Installation_Windows.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3c378815cd848fdfc9574eb5abdd300800cb25a1 GIT binary patch literal 44545 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 QQ>?iM6f^Jx{A={z0Mv;BS^xk5 literal 0 HcmV?d00001 diff --git a/screenshots/Python_3.9_Installation_Windows.jpg b/screenshots/Python_3.9_Installation_Windows.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cdc4fd9f56d8549aa599ee55e0d4a8a135fa7af6 GIT binary patch literal 43819 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 literal 0 HcmV?d00001 diff --git a/setup.cfg b/setup.cfg index f9929b39..26259456 100644 --- a/setup.cfg +++ b/setup.cfg @@ -8,12 +8,15 @@ packages = find: install_requires = build certifi + comtypes; sys_platform=='win32' dbus-python;sys_platform == 'linux' distro numpy Pillow PyChromecast + pywin32; sys_platform=='win32' Send2Trash + #wexpect; sys_platform=='win32' wxPython zeroconf diff --git a/setup.py b/setup.py index ca67f5e6..025c13c7 100755 --- a/setup.py +++ b/setup.py @@ -1406,6 +1406,7 @@ def setup(): if passphrase_path.is_file(): from DisplayCAL import wexpect + # import wexpect with open(passphrase_path) as passphrase_file: passphrase = passphrase_file.read().strip()