80 changed files with 3526 additions and 405 deletions
@ -0,0 +1,15 @@
|
||||
import importlib.util |
||||
import platform |
||||
|
||||
if importlib.util.find_spec('pyodideProxy'): |
||||
from .pyodide import * |
||||
from .term_pyodide import * |
||||
elif platform.system() == 'Linux': |
||||
from .unix import * |
||||
from .term_unix import * |
||||
elif platform.system() == 'Darwin': |
||||
from .unix import * |
||||
from .term_unix import * |
||||
elif platform.system() == 'Windows': |
||||
from .windows import * |
||||
from .term_windows import * |
||||
@ -0,0 +1,44 @@
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
__all__ = ['TTkSignalDriver','TTkInputDriver'] |
||||
|
||||
from pyodide import __version__ as pyodideVersion |
||||
|
||||
from TermTk.TTkCore.signal import pyTTkSignal |
||||
from TermTk.TTkCore.log import TTkLog |
||||
|
||||
class TTkInputDriver(): |
||||
def close(self): pass |
||||
def cont(self): pass |
||||
def read(self): pass |
||||
|
||||
|
||||
class TTkSignalDriver(): |
||||
sigStop = pyTTkSignal() |
||||
sigCont = pyTTkSignal() |
||||
sigInt = pyTTkSignal() |
||||
|
||||
@staticmethod |
||||
def init(): |
||||
TTkLog.info(f"Pyodide Version:\033[38;5;11m{pyodideVersion}") |
||||
def exit(): pass |
||||
@ -0,0 +1,74 @@
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2022 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
__all__ = ['TTkTerm'] |
||||
|
||||
import sys, os |
||||
from threading import Thread, Lock |
||||
|
||||
from ..TTkTerm.term_base import TTkTermBase |
||||
from TermTk.TTkCore.log import TTkLog |
||||
from .windows import * |
||||
|
||||
class TTkTerm(TTkTermBase): |
||||
@staticmethod |
||||
def _push(*args): |
||||
try: |
||||
sys.stdout.write(str(*args)) |
||||
sys.stdout.flush() |
||||
except BlockingIOError as e: |
||||
TTkLog.fatal(f"{e=} {e.characters_written=}") |
||||
except Exception as e: |
||||
TTkLog.fatal(e) |
||||
TTkTermBase.push = _push |
||||
|
||||
@staticmethod |
||||
def _flush(): |
||||
sys.stdout.flush() |
||||
TTkTermBase.flush = _flush |
||||
|
||||
@staticmethod |
||||
def _getTerminalSize(): |
||||
try: |
||||
return os.get_terminal_size() |
||||
except OSError as e: |
||||
print(f'ERROR: {e}') |
||||
TTkTermBase.getTerminalSize = _getTerminalSize |
||||
|
||||
_sigWinChMutex = Lock() |
||||
|
||||
@staticmethod |
||||
def _sigWinCh(w,h): |
||||
def _sigWinChThreaded(): |
||||
if not TTkTerm._sigWinChMutex.acquire(blocking=False): return |
||||
while (TTkTerm.width, TTkTerm.height) != (wh:=TTkTerm.getTerminalSize()): |
||||
TTkTerm.width, TTkTerm.height = wh |
||||
if TTkTerm._sigWinChCb is not None: |
||||
TTkTerm._sigWinChCb(TTkTerm.width, TTkTerm.height) |
||||
TTkTerm._sigWinChMutex.release() |
||||
Thread(target=_sigWinChThreaded).start() |
||||
|
||||
@staticmethod |
||||
def _registerResizeCb(callback): |
||||
TTkTerm._sigWinChCb = callback |
||||
TTkInputDriver.windowResized.connect(TTkTerm._sigWinCh) |
||||
TTkTermBase.registerResizeCb = _registerResizeCb |
||||
@ -0,0 +1,368 @@
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
__all__ = ['TTkSignalDriver','TTkInputDriver'] |
||||
|
||||
import signal |
||||
|
||||
from ctypes import Structure, Union, byref, wintypes, windll |
||||
|
||||
from TermTk.TTkCore.signal import pyTTkSignal, pyTTkSlot |
||||
|
||||
from TermTk.TTkCore.log import TTkLog |
||||
|
||||
# Based on the example ported from: |
||||
# https://learn.microsoft.com/en-us/windows/console/reading-input-buffer-events |
||||
# https://github.com/ceccopierangiolieugenio/pyTermTk -> tests/test.input.win.01.py |
||||
|
||||
# https://learn.microsoft.com/en-us/windows/console/getstdhandle |
||||
STD_INPUT_HANDLE = wintypes.DWORD(-10) # The standard input device. Initially, this is the console input buffer, CONIN$. |
||||
STD_OUTPUT_HANDLE = wintypes.DWORD(-11) # The standard output device. Initially, this is the active console screen buffer, CONOUT$. |
||||
STD_ERROR_HANDLE = wintypes.DWORD(-12) # The standard error device. Initially, this is the active console screen buffer, CONOUT$. |
||||
|
||||
INVALID_HANDLE_VALUE = -1 # WinBase.h |
||||
|
||||
# https://learn.microsoft.com/en-us/windows/console/SetConsoleMode |
||||
ENABLE_ECHO_INPUT = 0x0004 # Characters read by the ReadFile or ReadConsole function are written to the active screen buffer as they are typed into the console. This mode can be used only if the ENABLE_LINE_INPUT mode is also enabled. |
||||
ENABLE_INSERT_MODE = 0x0020 # When enabled, text entered in a console window will be inserted at the current cursor location and all text following that location will not be overwritten. When disabled, all following text will be overwritten. |
||||
ENABLE_LINE_INPUT = 0x0002 # The ReadFile or ReadConsole function returns only when a carriage return character is read. If this mode is disabled, the functions return when one or more characters are available. |
||||
ENABLE_MOUSE_INPUT = 0x0010 # If the mouse pointer is within the borders of the console window and the window has the keyboard focus, mouse events generated by mouse movement and button presses are placed in the input buffer. These events are discarded by ReadFile or ReadConsole, even when this mode is enabled. The ReadConsoleInput function can be used to read MOUSE_EVENT input records from the input buffer. |
||||
ENABLE_PROCESSED_INPUT = 0x0001 # CTRL+C is processed by the system and is not placed in the input buffer. If the input buffer is being read by ReadFile or ReadConsole, other control keys are processed by the system and are not returned in the ReadFile or ReadConsole buffer. If the ENABLE_LINE_INPUT mode is also enabled, backspace, carriage return, and line feed characters are handled by the system. |
||||
ENABLE_QUICK_EDIT_MODE = 0x0040 # This flag enables the user to use the mouse to select and edit text. To enable this mode, use ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS. To disable this mode, use ENABLE_EXTENDED_FLAGS without this flag. |
||||
ENABLE_WINDOW_INPUT = 0x0008 # User interactions that change the size of the console screen buffer are reported in the console's input buffer. Information about these events can be read from the input buffer by applications using the ReadConsoleInput function, but not by those using ReadFile or ReadConsole. |
||||
ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200 # Setting this flag directs the Virtual Terminal processing engine to convert user input received by the console window into Console Virtual Terminal Sequences that can be retrieved by a supporting application through ReadFile or ReadConsole functions. |
||||
|
||||
ENABLE_PROCESSED_OUTPUT = 0x0001 |
||||
ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002 |
||||
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004 |
||||
DISABLE_NEWLINE_AUTO_RETURN = 0x0008 |
||||
ENABLE_LVB_GRID_WORLDWIDE = 0x0010 |
||||
|
||||
# https://learn.microsoft.com/en-us/windows/console/input-record-str |
||||
FOCUS_EVENT = 0x0010 # The Event member contains a FOCUS_EVENT_RECORD structure. These events are used internally and should be ignored. |
||||
KEY_EVENT = 0x0001 # The Event member contains a KEY_EVENT_RECORD structure with information about a keyboard event. |
||||
MENU_EVENT = 0x0008 # The Event member contains a MENU_EVENT_RECORD structure. These events are used internally and should be ignored. |
||||
MOUSE_EVENT = 0x0002 # The Event member contains a MOUSE_EVENT_RECORD structure with information about a mouse movement or button press event. |
||||
WINDOW_BUFFER_SIZE_EVENT = 0x0004 # The Event member contains a WINDOW_BUFFER_SIZE_RECORD structure with information about the new size of the console screen buffer. |
||||
|
||||
# https://learn.microsoft.com/en-us/windows/console/mouse-event-record-str |
||||
# dwButtonState |
||||
FROM_LEFT_1ST_BUTTON_PRESSED = 0x0001 # The leftmost mouse button. |
||||
FROM_LEFT_2ND_BUTTON_PRESSED = 0x0004 # The second button fom the left. |
||||
FROM_LEFT_3RD_BUTTON_PRESSED = 0x0008 # The third button from the left. |
||||
FROM_LEFT_4TH_BUTTON_PRESSED = 0x0010 # The fourth button from the left. |
||||
RIGHTMOST_BUTTON_PRESSED = 0x0002 # The rightmost mouse button. |
||||
# dwControlKeyState |
||||
CAPSLOCK_ON = 0x0080 # The CAPS LOCK light is on. |
||||
ENHANCED_KEY = 0x0100 # The key is enhanced. See remarks. |
||||
LEFT_ALT_PRESSED = 0x0002 # The left ALT key is pressed. |
||||
LEFT_CTRL_PRESSED = 0x0008 # The left CTRL key is pressed. |
||||
NUMLOCK_ON = 0x0020 # The NUM LOCK light is on. |
||||
RIGHT_ALT_PRESSED = 0x0001 # The right ALT key is pressed. |
||||
RIGHT_CTRL_PRESSED = 0x0004 # The right CTRL key is pressed. |
||||
SCROLLLOCK_ON = 0x0040 # The SCROLL LOCK light is on. |
||||
SHIFT_PRESSED = 0x0010 # The SHIFT key is pressed. |
||||
# dwEventFlags |
||||
DOUBLE_CLICK = 0x0002 # The second click (button press) of a double-click occurred. The first click is returned as a regular button-press event. |
||||
MOUSE_HWHEELED = 0x0008 # The horizontal mouse wheel was moved. |
||||
# If the high word of the dwButtonState member contains a positive value, the wheel was rotated to the right. Otherwise, the wheel was rotated to the left. |
||||
MOUSE_MOVED = 0x0001 # A change in mouse position occurred. |
||||
MOUSE_WHEELED = 0x0004 # The vertical mouse wheel was moved. |
||||
# If the high word of the dwButtonState member contains a positive value, the wheel was rotated forward, away from the user. Otherwise, the wheel was rotated backward, toward the user. |
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/coord-str |
||||
# |
||||
# typedef struct _COORD { |
||||
# SHORT X; |
||||
# SHORT Y; |
||||
# } COORD, *PCOORD; |
||||
class COORD(Structure): |
||||
_fields_ = [ |
||||
("X", wintypes.SHORT), |
||||
("Y", wintypes.SHORT)] |
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/key-event-record-str |
||||
# |
||||
# typedef struct _KEY_EVENT_RECORD { |
||||
# BOOL bKeyDown; |
||||
# WORD wRepeatCount; |
||||
# WORD wVirtualKeyCode; |
||||
# WORD wVirtualScanCode; |
||||
# union { |
||||
# WCHAR UnicodeChar; |
||||
# CHAR AsciiChar; |
||||
# } uChar; |
||||
# DWORD dwControlKeyState; |
||||
# } KEY_EVENT_RECORD; |
||||
class KEY_EVENT_RECORD(Structure): |
||||
class _uChar(Union): |
||||
_fields_ = [ |
||||
("UnicodeChar", wintypes.WCHAR) , |
||||
("AsciiChar" , wintypes.CHAR ) ] |
||||
|
||||
_fields_ = [ |
||||
("bKeyDown" , wintypes.BOOL ), |
||||
("wRepeatCount" , wintypes.WORD ), |
||||
("wVirtualKeyCode" , wintypes.WORD ), |
||||
("wVirtualScanCode" , wintypes.WORD ), |
||||
("uChar" , _uChar ), |
||||
("dwControlKeyState", wintypes.DWORD)] |
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str |
||||
# |
||||
# typedef struct _MOUSE_EVENT_RECORD { |
||||
# COORD dwMousePosition; |
||||
# DWORD dwButtonState; |
||||
# DWORD dwControlKeyState; |
||||
# DWORD dwEventFlags; |
||||
# } MOUSE_EVENT_RECORD; |
||||
class MOUSE_EVENT_RECORD(Structure): |
||||
_fields_ = [ |
||||
("dwMousePosition" , COORD), |
||||
("dwButtonState" , wintypes.DWORD), |
||||
("dwControlKeyState", wintypes.DWORD), |
||||
("dwEventFlags" , wintypes.DWORD)] |
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/window-buffer-size-record-str |
||||
# |
||||
# typedef struct _WINDOW_BUFFER_SIZE_RECORD { |
||||
# COORD dwSize; |
||||
# } WINDOW_BUFFER_SIZE_RECORD; |
||||
class WINDOW_BUFFER_SIZE_RECORD(Structure): |
||||
_fields_ = [("dwSize", COORD)] |
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/menu-event-record-str |
||||
# |
||||
# typedef struct _MENU_EVENT_RECORD { |
||||
# UINT dwCommandId; |
||||
# } MENU_EVENT_RECORD, *PMENU_EVENT_RECORD; |
||||
class MENU_EVENT_RECORD(Structure): |
||||
_fields_ = [("dwCommandId", wintypes.UINT)] |
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/focus-event-record-str |
||||
# |
||||
# typedef struct _FOCUS_EVENT_RECORD { |
||||
# BOOL bSetFocus; |
||||
# } FOCUS_EVENT_RECORD; |
||||
class FOCUS_EVENT_RECORD(Structure): |
||||
_fields_ = [("bSetFocus", wintypes.BOOL)] |
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/input-record-str |
||||
# |
||||
# typedef struct _INPUT_RECORD { |
||||
# WORD EventType; |
||||
# union { |
||||
# KEY_EVENT_RECORD KeyEvent; |
||||
# MOUSE_EVENT_RECORD MouseEvent; |
||||
# WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent; |
||||
# MENU_EVENT_RECORD MenuEvent; |
||||
# FOCUS_EVENT_RECORD FocusEvent; |
||||
# } Event; |
||||
# } INPUT_RECORD; |
||||
class INPUT_RECORD(Structure): |
||||
class _Event(Union): |
||||
_fields_ = [ |
||||
("KeyEvent" , KEY_EVENT_RECORD ), |
||||
("MouseEvent" , MOUSE_EVENT_RECORD ), |
||||
("WindowBufferSizeEvent", WINDOW_BUFFER_SIZE_RECORD), |
||||
("MenuEvent" , MENU_EVENT_RECORD ), |
||||
("FocusEvent" , FOCUS_EVENT_RECORD )] |
||||
|
||||
_fields_ = [ |
||||
("EventType", wintypes.WORD), |
||||
("Event" , _Event )] |
||||
|
||||
|
||||
class TTkInputDriver(): |
||||
windowResized = pyTTkSignal(int,int) |
||||
def __init__(self): |
||||
self._run = True |
||||
self._initTerminal() |
||||
|
||||
def _initTerminal(self): |
||||
# Get the standard input handle. |
||||
# From: |
||||
# https://learn.microsoft.com/en-us/windows/console/getstdhandle |
||||
# |
||||
# HANDLE WINAPI GetStdHandle( |
||||
# _In_ DWORD nStdHandle |
||||
# ); |
||||
GetStdHandle = windll.kernel32.GetStdHandle |
||||
GetStdHandle.argtypes = [wintypes.DWORD] |
||||
GetStdHandle.restype = wintypes.HANDLE |
||||
|
||||
self._hStdIn = GetStdHandle(STD_INPUT_HANDLE) |
||||
if self._hStdIn == INVALID_HANDLE_VALUE: |
||||
raise Exception("GetStdHandle") |
||||
|
||||
self._hStdOut = GetStdHandle(STD_OUTPUT_HANDLE) |
||||
if self._hStdOut == INVALID_HANDLE_VALUE: |
||||
raise Exception("GetStdHandle") |
||||
|
||||
# Save the current input mode, to be restored on exit. |
||||
# From: |
||||
# https://learn.microsoft.com/en-us/windows/console/GetConsoleMode |
||||
# |
||||
# BOOL WINAPI GetConsoleMode( |
||||
# _In_ HANDLE hConsoleHandle, |
||||
# _Out_ LPDWORD lpMode |
||||
# ); |
||||
self._GetConsoleMode = windll.kernel32.GetConsoleMode |
||||
self._GetConsoleMode.argtypes = [wintypes.HANDLE, wintypes.LPDWORD] |
||||
self._GetConsoleMode.restype = wintypes.BOOL |
||||
|
||||
self._fdwSaveOldModeIn = wintypes.DWORD() |
||||
if not self._GetConsoleMode(self._hStdIn, byref(self._fdwSaveOldModeIn)): |
||||
raise Exception("GetConsoleMode") |
||||
|
||||
self._fdwSaveOldModeOut = wintypes.DWORD() |
||||
if not self._GetConsoleMode(self._hStdOut, byref(self._fdwSaveOldModeOut)): |
||||
raise Exception("GetConsoleMode") |
||||
|
||||
# TTkLog.debug(f"{fdwSaveOldModeIn.value=:02x}") |
||||
# TTkLog.debug(f"{fdwSaveOldModeOut.value=:02x}") |
||||
|
||||
# Enable the window and mouse input events. |
||||
# From: |
||||
# https://learn.microsoft.com/en-us/windows/console/SetConsoleMode |
||||
# |
||||
# BOOL WINAPI SetConsoleMode( |
||||
# _In_ HANDLE hConsoleHandle, |
||||
# _In_ DWORD dwMode |
||||
# ); |
||||
self._SetConsoleMode = windll.kernel32.SetConsoleMode |
||||
self._SetConsoleMode.argtypes = [wintypes.HANDLE, wintypes.DWORD] |
||||
self._SetConsoleMode.restype = wintypes.BOOL |
||||
|
||||
fdwModeIn = ENABLE_VIRTUAL_TERMINAL_INPUT |
||||
# fdwModeIn = ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT |
||||
# fdwModeIn = 0x0218 |
||||
if not self._SetConsoleMode(self._hStdIn, fdwModeIn): |
||||
raise Exception("SetConsoleMode") |
||||
|
||||
fdwModeOut = self._fdwSaveOldModeOut.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING |
||||
# fdwModeIn = 0x0218 |
||||
if not self._SetConsoleMode(self._hStdOut, fdwModeOut): |
||||
raise Exception("SetConsoleMode") |
||||
|
||||
# TTkLog.debug(f"{fdwModeIn=:02x}") |
||||
# TTkLog.debug(f"{fdwModeOut=:02x}") |
||||
|
||||
def close(self): |
||||
self._run = False |
||||
# Restore input mode on exit. |
||||
if not self._SetConsoleMode(self._hStdIn, self._fdwSaveOldModeIn): |
||||
raise Exception("SetConsoleMode") |
||||
|
||||
if not self._SetConsoleMode(self._hStdOut, self._fdwSaveOldModeOut): |
||||
raise Exception("SetConsoleMode") |
||||
|
||||
def cont(self): |
||||
pass |
||||
|
||||
def read(self) -> str|None: |
||||
# From: |
||||
# https://learn.microsoft.com/en-us/windows/console/ReadConsoleInput |
||||
# |
||||
# BOOL WINAPI ReadConsoleInput( |
||||
# _In_ HANDLE hConsoleInput, |
||||
# _Out_ PINPUT_RECORD lpBuffer, |
||||
# _In_ DWORD nLength, |
||||
# _Out_ LPDWORD lpNumberOfEventsRead |
||||
# ); |
||||
|
||||
ReadConsoleInput = windll.kernel32.ReadConsoleInputW # Unicode |
||||
# ReadConsoleInput = windll.kernel32.ReadConsoleInputA # ANSII |
||||
# ReadConsoleInput.argtypes = [wintypes.HANDLE, |
||||
# wintypes.LPINT, |
||||
# wintypes.DWORD, |
||||
# wintypes.LPWORD] |
||||
ReadConsoleInput.restype = wintypes.BOOL |
||||
|
||||
# DWORD cNumRead; |
||||
# INPUT_RECORD irInBuf[128]; |
||||
cNumRead = wintypes.DWORD(0) |
||||
irInBuf = (INPUT_RECORD * 256)() |
||||
|
||||
# Loop to read and handle the next 100 input events. |
||||
while self._run: |
||||
# Wait for the events. |
||||
if not ReadConsoleInput( |
||||
self._hStdIn, # input buffer handle |
||||
byref(irInBuf), # buffer to read into |
||||
256, # size of read buffer |
||||
byref(cNumRead)): # number of records read |
||||
raise Exception("ReadConsoleInput") |
||||
|
||||
# TTkLog.debug(f"{self._hStdIn=} {irInBuf=} {cNumRead=}") |
||||
# TTkLog.debug(f"{cNumRead=}") |
||||
|
||||
# Dispatch the events to the appropriate handler. |
||||
saveKeys = [] |
||||
for bb in irInBuf[:cNumRead.value]: |
||||
# if not bb.EventType: continue |
||||
# TTkLog.debug(f"{bb=} {bb.EventType=} {cNumRead.value=}") |
||||
|
||||
if bb.EventType == KEY_EVENT: |
||||
ke = bb.Event.KeyEvent |
||||
if ( not ke.bKeyDown or |
||||
ke.dwControlKeyState or |
||||
ke.wVirtualKeyCode ): |
||||
continue |
||||
saveKeys.append(ke.uChar.UnicodeChar) |
||||
elif bb.EventType == MOUSE_EVENT: |
||||
# It is not supposed to receive Mouse Events |
||||
# due to ENABLE_VIRTUAL_TERMINAL_PROCESSING |
||||
# everything is received as ANSI sequence |
||||
pass |
||||
elif bb.EventType == WINDOW_BUFFER_SIZE_EVENT: |
||||
# TTkLog.debug(f"{bb.Event.WindowBufferSizeEvent=}") |
||||
# TTkLog.debug(f"{bb.Event.WindowBufferSizeEvent.dwSize.X=}") |
||||
# TTkLog.debug(f"{bb.Event.WindowBufferSizeEvent.dwSize.Y=}") |
||||
TTkInputDriver.windowResized.emit(bb.Event.WindowBufferSizeEvent.dwSize.X, bb.Event.WindowBufferSizeEvent.dwSize.Y) |
||||
if saveKeys: |
||||
yield "".join(saveKeys).encode("utf-16", "surrogatepass").decode("utf-16") |
||||
|
||||
class TTkSignalDriver(): |
||||
sigStop = pyTTkSignal() |
||||
sigCont = pyTTkSignal() |
||||
sigInt = pyTTkSignal() |
||||
|
||||
@staticmethod |
||||
def init(): |
||||
# Register events |
||||
# signal.signal(signal.SIGTSTP, TTkSignalDriver._SIGSTOP) # Ctrl-Z |
||||
# signal.signal(signal.SIGCONT, TTkSignalDriver._SIGCONT) # Resume |
||||
signal.signal(signal.SIGINT, TTkSignalDriver._SIGINT) # Ctrl-C |
||||
|
||||
def exit(): |
||||
signal.signal(signal.SIGINT, signal.SIG_DFL) |
||||
|
||||
def _SIGSTOP(signum, frame): TTkSignalDriver.sigStop.emit() |
||||
def _SIGCONT(signum, frame): TTkSignalDriver.sigCont.emit() |
||||
def _SIGINT( signum, frame): TTkSignalDriver.sigInt.emit() |
||||
@ -1,33 +0,0 @@
|
||||
# from .about import |
||||
from .button import * |
||||
from .checkbox import * |
||||
from .combobox import * |
||||
from .container import * |
||||
from .frame import * |
||||
# from .graph import |
||||
# from .image import |
||||
from .label import * |
||||
from .lineedit import * |
||||
from .list_ import * |
||||
# from .listwidget import |
||||
# from .menubar import |
||||
from .menu import * |
||||
# from .progressbar import |
||||
from .radiobutton import * |
||||
from .resizableframe import * |
||||
# from .scrollarea import |
||||
from .scrollbar import * |
||||
# from .spacer import |
||||
from .spinbox import * |
||||
from .splitter import * |
||||
# from .tabwidget import |
||||
from .texedit import * |
||||
from .widget import * |
||||
from .window import * |
||||
|
||||
# Pickers |
||||
from .colorpicker import * |
||||
from .filepicker import * |
||||
|
||||
# Layouts |
||||
from .layout import * |
||||
@ -0,0 +1,36 @@
|
||||
# How it Was |
||||
TTk: |
||||
- __init__() |
||||
```python |
||||
self._input = TTkInput() |
||||
self._input.inputEvent.connect(self._processInput) |
||||
self._input.pasteEvent.connect(self._processPaste) |
||||
``` |
||||
- mainLoop() |
||||
```python |
||||
TTkTerm.registerResizeCb(self._win_resize_cb) |
||||
TTkTerm.init( |
||||
title=self._title, |
||||
sigmask=self._sigmask, |
||||
mouse=self._termMouse, |
||||
directMouse=self._termDirectMouse ) |
||||
``` |
||||
|
||||
# How it Should Be |
||||
- __init__() |
||||
```python |
||||
TTkInput.inputEvent.connect(self._processInput) |
||||
TTkInput.pasteEvent.connect(self._processPaste) |
||||
TTkSignalDriver.sigStop.connect(self._SIGSTOP) |
||||
TTkSignalDriver.sigCont.connect(self._SIGCONT) |
||||
TTkSignalDriver.sigInt.connect( self._SIGINT) |
||||
``` |
||||
- mainLoop() |
||||
```python |
||||
TTkInput.init( |
||||
mouse=self._termMouse, |
||||
directMouse=self._termDirectMouse) |
||||
TTkTerm.init( |
||||
title=self._title, |
||||
sigmask=self._sigmask) |
||||
``` |
||||
@ -0,0 +1,31 @@
|
||||
# Run Python - pyTermTk on Wine32: |
||||
```bash |
||||
# cmd in the terminal |
||||
~/.var/app/net.lutris.Lutris/data/lutris/runners/wine/lutris-GE-Proton8-5-x86_64/bin/wine cmd |
||||
# cmd in a wine window |
||||
~/.var/app/net.lutris.Lutris/data/lutris//runners/wine/lutris-GE-Proton8-5-x86_64/bin/wine wineconsole |
||||
|
||||
# Install python from https://www.python.org/downloads/windows/ |
||||
# Copy the pyTermTk demo and TermTk folder in |
||||
# ~/.wine/drive_c/users/one/AppData/Local/Programs/Python/Python310-32 |
||||
|
||||
C: |
||||
cd C:\users\one\AppData\Local\Programs\Python\Python310-32 |
||||
python.exe demo/demo.py |
||||
python.exe tests/test.input.win.py |
||||
``` |
||||
|
||||
# termios wrappers |
||||
- termiWin -> https://github.com/veeso/termiWin |
||||
|
||||
# Competitors with MS-Win support |
||||
|
||||
### Textual -> https://github.com/Textualize/textual |
||||
https://github.com/Textualize/textual/blob/main/src/textual/drivers/win32.py |
||||
|
||||
### TheVTPyProject -> https://github.com/srccircumflex/TheVTPyProject |
||||
|
||||
# Incompatible code (the one using termios): |
||||
- TermTk/TTkCore/TTkTerm/readinputlinux.py |
||||
- TermTk/TTkCore/TTkTerm/readinputlinux_thread.py |
||||
- TermTk/TTkCore/TTkTerm/term_unix.py |
||||
@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2021 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
import sys, os |
||||
|
||||
import curses |
||||
|
||||
print("Retrieve Keyboard, Mouse press/drag/wheel Events") |
||||
print("Press q or <ESC> to exit") |
||||
|
||||
def reset(): |
||||
# Reset |
||||
sys.stdout.write("\033[?1000l") |
||||
sys.stdout.write("\033[?1002l") |
||||
sys.stdout.write("\033[?1015l") |
||||
sys.stdout.write("\033[?1006l") |
||||
sys.stdout.write("\033[?1049l") # Switch to normal screen |
||||
sys.stdout.write("\033[?2004l") # Paste Bracketed mode |
||||
sys.stdout.flush() |
||||
|
||||
stdscr = curses.initscr() |
||||
|
||||
curses.curs_set(0) |
||||
stdscr.keypad(1) |
||||
curses.mousemask(curses.ALL_MOUSE_EVENTS | curses.REPORT_MOUSE_POSITION) |
||||
curses.mouseinterval(0) |
||||
print('\033[?1003h') |
||||
|
||||
# reset() |
||||
|
||||
while True: |
||||
c = stdscr.getch() |
||||
print(f"{c=}\r") |
||||
if c == ord('q'): |
||||
break # Exit the while loop |
||||
elif c == curses.KEY_HOME: |
||||
print("HOME\r") |
||||
elif c == curses.KEY_MOUSE: |
||||
m = curses.getmouse() |
||||
y, x = stdscr.getyx() |
||||
print(f"Mouse {m=} {(x,y)=}\r") |
||||
elif c == curses.KEY_RESIZE: |
||||
print(f"Resize\r") |
||||
|
||||
print('\033[?1003l') |
||||
curses.endwin() |
||||
curses.flushinp() |
||||
@ -0,0 +1,393 @@
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
import sys |
||||
|
||||
from ctypes import Structure, Union, byref, wintypes, windll |
||||
|
||||
# Example ported from: |
||||
# https://learn.microsoft.com/en-us/windows/console/reading-input-buffer-events |
||||
|
||||
# https://learn.microsoft.com/en-us/windows/console/getstdhandle |
||||
STD_INPUT_HANDLE = wintypes.DWORD(-10) # The standard input device. Initially, this is the console input buffer, CONIN$. |
||||
STD_OUTPUT_HANDLE = wintypes.DWORD(-11) # The standard output device. Initially, this is the active console screen buffer, CONOUT$. |
||||
STD_ERROR_HANDLE = wintypes.DWORD(-12) # The standard error device. Initially, this is the active console screen buffer, CONOUT$. |
||||
|
||||
INVALID_HANDLE_VALUE = -1 # WinBase.h |
||||
|
||||
# https://learn.microsoft.com/en-us/windows/console/SetConsoleMode |
||||
ENABLE_ECHO_INPUT = 0x0004 # Characters read by the ReadFile or ReadConsole function are written to the active screen buffer as they are typed into the console. This mode can be used only if the ENABLE_LINE_INPUT mode is also enabled. |
||||
ENABLE_INSERT_MODE = 0x0020 # When enabled, text entered in a console window will be inserted at the current cursor location and all text following that location will not be overwritten. When disabled, all following text will be overwritten. |
||||
ENABLE_LINE_INPUT = 0x0002 # The ReadFile or ReadConsole function returns only when a carriage return character is read. If this mode is disabled, the functions return when one or more characters are available. |
||||
ENABLE_MOUSE_INPUT = 0x0010 # If the mouse pointer is within the borders of the console window and the window has the keyboard focus, mouse events generated by mouse movement and button presses are placed in the input buffer. These events are discarded by ReadFile or ReadConsole, even when this mode is enabled. The ReadConsoleInput function can be used to read MOUSE_EVENT input records from the input buffer. |
||||
ENABLE_PROCESSED_INPUT = 0x0001 # CTRL+C is processed by the system and is not placed in the input buffer. If the input buffer is being read by ReadFile or ReadConsole, other control keys are processed by the system and are not returned in the ReadFile or ReadConsole buffer. If the ENABLE_LINE_INPUT mode is also enabled, backspace, carriage return, and line feed characters are handled by the system. |
||||
ENABLE_QUICK_EDIT_MODE = 0x0040 # This flag enables the user to use the mouse to select and edit text. To enable this mode, use ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS. To disable this mode, use ENABLE_EXTENDED_FLAGS without this flag. |
||||
ENABLE_WINDOW_INPUT = 0x0008 # User interactions that change the size of the console screen buffer are reported in the console's input buffer. Information about these events can be read from the input buffer by applications using the ReadConsoleInput function, but not by those using ReadFile or ReadConsole. |
||||
ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200 # Setting this flag directs the Virtual Terminal processing engine to convert user input received by the console window into Console Virtual Terminal Sequences that can be retrieved by a supporting application through ReadFile or ReadConsole functions. |
||||
|
||||
ENABLE_PROCESSED_OUTPUT = 0x0001 |
||||
ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002 |
||||
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004 |
||||
DISABLE_NEWLINE_AUTO_RETURN = 0x0008 |
||||
ENABLE_LVB_GRID_WORLDWIDE = 0x0010 |
||||
|
||||
# https://learn.microsoft.com/en-us/windows/console/input-record-str |
||||
FOCUS_EVENT = 0x0010 # The Event member contains a FOCUS_EVENT_RECORD structure. These events are used internally and should be ignored. |
||||
KEY_EVENT = 0x0001 # The Event member contains a KEY_EVENT_RECORD structure with information about a keyboard event. |
||||
MENU_EVENT = 0x0008 # The Event member contains a MENU_EVENT_RECORD structure. These events are used internally and should be ignored. |
||||
MOUSE_EVENT = 0x0002 # The Event member contains a MOUSE_EVENT_RECORD structure with information about a mouse movement or button press event. |
||||
WINDOW_BUFFER_SIZE_EVENT = 0x0004 # The Event member contains a WINDOW_BUFFER_SIZE_RECORD structure with information about the new size of the console screen buffer. |
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/coord-str |
||||
# |
||||
# typedef struct _COORD { |
||||
# SHORT X; |
||||
# SHORT Y; |
||||
# } COORD, *PCOORD; |
||||
class COORD(Structure): |
||||
_fields_ = [ |
||||
("X", wintypes.SHORT), |
||||
("Y", wintypes.SHORT)] |
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/key-event-record-str |
||||
# |
||||
# typedef struct _KEY_EVENT_RECORD { |
||||
# BOOL bKeyDown; |
||||
# WORD wRepeatCount; |
||||
# WORD wVirtualKeyCode; |
||||
# WORD wVirtualScanCode; |
||||
# union { |
||||
# WCHAR UnicodeChar; |
||||
# CHAR AsciiChar; |
||||
# } uChar; |
||||
# DWORD dwControlKeyState; |
||||
# } KEY_EVENT_RECORD; |
||||
class KEY_EVENT_RECORD(Structure): |
||||
class _uChar(Union): |
||||
_fields_ = [ |
||||
("UnicodeChar", wintypes.WCHAR) , |
||||
("AsciiChar" , wintypes.CHAR ) ] |
||||
|
||||
_fields_ = [ |
||||
("bKeyDown" , wintypes.BOOL ), |
||||
("wRepeatCount" , wintypes.WORD ), |
||||
("wVirtualKeyCode" , wintypes.WORD ), |
||||
("wVirtualScanCode" , wintypes.WORD ), |
||||
("uChar" , _uChar ), |
||||
("dwControlKeyState", wintypes.DWORD)] |
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str |
||||
# |
||||
# typedef struct _MOUSE_EVENT_RECORD { |
||||
# COORD dwMousePosition; |
||||
# DWORD dwButtonState; |
||||
# DWORD dwControlKeyState; |
||||
# DWORD dwEventFlags; |
||||
# } MOUSE_EVENT_RECORD; |
||||
class MOUSE_EVENT_RECORD(Structure): |
||||
_fields_ = [ |
||||
("dwMousePosition" , COORD), |
||||
("dwButtonState" , wintypes.DWORD), |
||||
("dwControlKeyState", wintypes.DWORD), |
||||
("dwEventFlags" , wintypes.DWORD)] |
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/window-buffer-size-record-str |
||||
# |
||||
# typedef struct _WINDOW_BUFFER_SIZE_RECORD { |
||||
# COORD dwSize; |
||||
# } WINDOW_BUFFER_SIZE_RECORD; |
||||
class WINDOW_BUFFER_SIZE_RECORD(Structure): |
||||
_fields_ = [("dwSize", COORD)] |
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/menu-event-record-str |
||||
# |
||||
# typedef struct _MENU_EVENT_RECORD { |
||||
# UINT dwCommandId; |
||||
# } MENU_EVENT_RECORD, *PMENU_EVENT_RECORD; |
||||
class MENU_EVENT_RECORD(Structure): |
||||
_fields_ = [("dwCommandId", wintypes.UINT)] |
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/focus-event-record-str |
||||
# |
||||
# typedef struct _FOCUS_EVENT_RECORD { |
||||
# BOOL bSetFocus; |
||||
# } FOCUS_EVENT_RECORD; |
||||
class FOCUS_EVENT_RECORD(Structure): |
||||
_fields_ = [("bSetFocus", wintypes.BOOL)] |
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/input-record-str |
||||
# |
||||
# typedef struct _INPUT_RECORD { |
||||
# WORD EventType; |
||||
# union { |
||||
# KEY_EVENT_RECORD KeyEvent; |
||||
# MOUSE_EVENT_RECORD MouseEvent; |
||||
# WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent; |
||||
# MENU_EVENT_RECORD MenuEvent; |
||||
# FOCUS_EVENT_RECORD FocusEvent; |
||||
# } Event; |
||||
# } INPUT_RECORD; |
||||
class INPUT_RECORD(Structure): |
||||
class _Event(Union): |
||||
_fields_ = [ |
||||
("KeyEvent" , KEY_EVENT_RECORD ), |
||||
("MouseEvent" , MOUSE_EVENT_RECORD ), |
||||
("WindowBufferSizeEvent", WINDOW_BUFFER_SIZE_RECORD), |
||||
("MenuEvent" , MENU_EVENT_RECORD ), |
||||
("FocusEvent" , FOCUS_EVENT_RECORD )] |
||||
|
||||
_fields_ = [ |
||||
("EventType", wintypes.WORD), |
||||
("Event" , _Event )] |
||||
|
||||
|
||||
def reset(): |
||||
# Reset |
||||
sys.stdout.write("\033[?1000l") |
||||
# sys.stdout.write("\033[?1002l") |
||||
sys.stdout.write("\033[?1003l") |
||||
sys.stdout.write("\033[?1006l") |
||||
sys.stdout.write("\033[?1015l") |
||||
# sys.stdout.write("\033[?1049l") # Switch to normal screen |
||||
# sys.stdout.write("\033[?2004l") # Paste Bracketed mode |
||||
sys.stdout.flush() |
||||
|
||||
def init(): |
||||
sys.stdout.write("\x1b[?1000h") |
||||
sys.stdout.write("\x1b[?1003h") |
||||
sys.stdout.write("\x1b[?1006h") |
||||
sys.stdout.write("\x1b[?1015h") |
||||
sys.stdout.flush() |
||||
|
||||
# DWORD cNumRead, fdwMode, i; |
||||
# INPUT_RECORD irInBuf[128]; |
||||
# int counter=0; |
||||
|
||||
# // Get the standard input handle. |
||||
# |
||||
# hStdIn = GetStdHandle(STD_INPUT_HANDLE); |
||||
# if (hStdIn == INVALID_HANDLE_VALUE) |
||||
# ErrorExit("GetStdHandle"); |
||||
# |
||||
# From: |
||||
# https://learn.microsoft.com/en-us/windows/console/getstdhandle |
||||
# |
||||
# HANDLE WINAPI GetStdHandle( |
||||
# _In_ DWORD nStdHandle |
||||
# ); |
||||
|
||||
GetStdHandle = windll.kernel32.GetStdHandle |
||||
GetStdHandle.argtypes = [wintypes.DWORD] |
||||
GetStdHandle.restype = wintypes.HANDLE |
||||
|
||||
hStdIn = GetStdHandle(STD_INPUT_HANDLE) |
||||
if hStdIn == INVALID_HANDLE_VALUE: |
||||
raise Exception("GetStdHandle") |
||||
|
||||
hStdOut = GetStdHandle(STD_OUTPUT_HANDLE) |
||||
if hStdOut == INVALID_HANDLE_VALUE: |
||||
raise Exception("GetStdHandle") |
||||
|
||||
# // Save the current input mode, to be restored on exit. |
||||
# |
||||
# if (! GetConsoleMode(hStdIn, &fdwSaveOldModeIn) ) |
||||
# ErrorExit("GetConsoleMode"); |
||||
# |
||||
# From: |
||||
# https://learn.microsoft.com/en-us/windows/console/GetConsoleMode |
||||
# |
||||
# BOOL WINAPI GetConsoleMode( |
||||
# _In_ HANDLE hConsoleHandle, |
||||
# _Out_ LPDWORD lpMode |
||||
# ); |
||||
|
||||
GetConsoleMode = windll.kernel32.GetConsoleMode |
||||
GetConsoleMode.argtypes = [wintypes.HANDLE, wintypes.LPDWORD] |
||||
GetConsoleMode.restype = wintypes.BOOL |
||||
|
||||
fdwSaveOldModeIn = wintypes.DWORD() |
||||
if not GetConsoleMode(hStdIn, byref(fdwSaveOldModeIn)): |
||||
raise Exception("GetConsoleMode") |
||||
|
||||
fdwSaveOldModeOut = wintypes.DWORD() |
||||
if not GetConsoleMode(hStdOut, byref(fdwSaveOldModeOut)): |
||||
raise Exception("GetConsoleMode") |
||||
|
||||
print(f"{fdwSaveOldModeIn.value=:02x}") |
||||
print(f"{fdwSaveOldModeOut.value=:02x}") |
||||
|
||||
# // Enable the window and mouse input events. |
||||
# |
||||
# fdwMode = ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT; |
||||
# if (! SetConsoleMode(hStdIn, fdwMode) ) |
||||
# ErrorExit("SetConsoleMode"); |
||||
# |
||||
# From: |
||||
# https://learn.microsoft.com/en-us/windows/console/SetConsoleMode |
||||
# |
||||
# BOOL WINAPI SetConsoleMode( |
||||
# _In_ HANDLE hConsoleHandle, |
||||
# _In_ DWORD dwMode |
||||
# ); |
||||
|
||||
SetConsoleMode = windll.kernel32.SetConsoleMode |
||||
SetConsoleMode.argtypes = [wintypes.HANDLE, wintypes.DWORD] |
||||
SetConsoleMode.restype = wintypes.BOOL |
||||
|
||||
fdwModeIn = ENABLE_VIRTUAL_TERMINAL_INPUT |
||||
# fdwModeIn = 0x0218 |
||||
if not SetConsoleMode(hStdIn, fdwModeIn): |
||||
raise Exception("SetConsoleMode") |
||||
|
||||
fdwModeOut = fdwSaveOldModeOut.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING |
||||
# fdwModeIn = 0x0218 |
||||
if not SetConsoleMode(hStdOut, fdwModeOut): |
||||
raise Exception("SetConsoleMode") |
||||
|
||||
print(f"{fdwModeIn=:02x}") |
||||
print(f"{fdwModeOut=:02x}") |
||||
|
||||
init() |
||||
|
||||
# From: |
||||
# https://learn.microsoft.com/en-us/windows/console/ReadConsoleInput |
||||
# |
||||
# BOOL WINAPI ReadConsoleInput( |
||||
# _In_ HANDLE hConsoleInput, |
||||
# _Out_ PINPUT_RECORD lpBuffer, |
||||
# _In_ DWORD nLength, |
||||
# _Out_ LPDWORD lpNumberOfEventsRead |
||||
# ); |
||||
|
||||
ReadConsoleInput = windll.kernel32.ReadConsoleInputW # Unicode |
||||
# ReadConsoleInput = windll.kernel32.ReadConsoleInputA # ANSII |
||||
# ReadConsoleInput.argtypes = [wintypes.HANDLE, |
||||
# wintypes.LPINT, |
||||
# wintypes.DWORD, |
||||
# wintypes.LPWORD] |
||||
ReadConsoleInput.restype = wintypes.BOOL |
||||
|
||||
|
||||
# DWORD cNumRead; |
||||
# INPUT_RECORD irInBuf[128]; |
||||
cNumRead = wintypes.DWORD(0) |
||||
irInBuf = (INPUT_RECORD * 256)() |
||||
|
||||
# // Loop to read and handle the next 100 input events. |
||||
# |
||||
# while (counter++ <= 100) |
||||
# { |
||||
for _ in range(50): |
||||
# // Wait for the events. |
||||
# |
||||
# if (! ReadConsoleInput( |
||||
# hStdIn, // input buffer handle |
||||
# irInBuf, // buffer to read into |
||||
# 128, // size of read buffer |
||||
# &cNumRead) ) // number of records read |
||||
# ErrorExit("ReadConsoleInput"); |
||||
if not ReadConsoleInput( |
||||
hStdIn, # input buffer handle |
||||
byref(irInBuf), # buffer to read into |
||||
256, # size of read buffer |
||||
byref(cNumRead)): # number of records read |
||||
raise Exception("ReadConsoleInput") |
||||
|
||||
# print(f"{hStdIn=} {irInBuf=} {cNumRead=}") |
||||
print(f"{cNumRead=}") |
||||
|
||||
# // Dispatch the events to the appropriate handler. |
||||
# |
||||
# for (i = 0; i < cNumRead; i++) |
||||
# { |
||||
for bb in irInBuf[:cNumRead.value]: |
||||
# if not bb.EventType: continue |
||||
print(f"{bb=} {bb.EventType=}") |
||||
|
||||
|
||||
# switch(irInBuf[i].EventType) |
||||
# { |
||||
# case KEY_EVENT: // keyboard input |
||||
# KeyEventProc(irInBuf[i].Event.KeyEvent); |
||||
# break; |
||||
if bb.EventType == KEY_EVENT: |
||||
print(f"{bb.Event.KeyEvent=}") |
||||
print(f"{bb.Event.KeyEvent.bKeyDown=}") |
||||
print(f"{bb.Event.KeyEvent.wRepeatCount=}") |
||||
print(f"{bb.Event.KeyEvent.wVirtualKeyCode=}") |
||||
print(f"{bb.Event.KeyEvent.wVirtualScanCode=}") |
||||
print(f"{bb.Event.KeyEvent.uChar.UnicodeChar=}") |
||||
print(f"{bb.Event.KeyEvent.uChar.AsciiChar=}") |
||||
print(f"{bb.Event.KeyEvent.dwControlKeyState=}") |
||||
|
||||
# case MOUSE_EVENT: // mouse input |
||||
# MouseEventProc(irInBuf[i].Event.MouseEvent); |
||||
# break; |
||||
elif bb.EventType == MOUSE_EVENT: |
||||
print(f"{bb.Event.MouseEvent=}") |
||||
print(f"{bb.Event.MouseEvent.dwMousePosition.X=}") |
||||
print(f"{bb.Event.MouseEvent.dwMousePosition.Y=}") |
||||
print(f"{bb.Event.MouseEvent.dwButtonState=}") |
||||
print(f"{bb.Event.MouseEvent.dwControlKeyState=}") |
||||
print(f"{bb.Event.MouseEvent.dwEventFlags=}") |
||||
|
||||
# case WINDOW_BUFFER_SIZE_EVENT: // scrn buf. resizing |
||||
# ResizeEventProc( irInBuf[i].Event.WindowBufferSizeEvent ); |
||||
# break; |
||||
elif bb.EventType == WINDOW_BUFFER_SIZE_EVENT: |
||||
print(f"{bb.Event.WindowBufferSizeEvent=}") |
||||
print(f"{bb.Event.WindowBufferSizeEvent.dwSize.X=}") |
||||
print(f"{bb.Event.WindowBufferSizeEvent.dwSize.Y=}") |
||||
|
||||
# case FOCUS_EVENT: // disregard focus events |
||||
# |
||||
# case MENU_EVENT: // disregard menu events |
||||
# break; |
||||
# |
||||
# default: |
||||
# ErrorExit("Unknown event type"); |
||||
# break; |
||||
# } |
||||
# } |
||||
# } |
||||
|
||||
# // Restore input mode on exit. |
||||
# |
||||
# SetConsoleMode(hStdIn, fdwSaveOldModeIn); |
||||
if not SetConsoleMode(hStdIn, fdwSaveOldModeIn): |
||||
raise Exception("SetConsoleMode") |
||||
|
||||
if not SetConsoleMode(hStdOut, fdwSaveOldModeOut): |
||||
raise Exception("SetConsoleMode") |
||||
|
||||
# return 0; |
||||
# |
||||
|
||||
reset() |
||||
print('OK') |
||||
@ -0,0 +1,436 @@
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
import sys,os |
||||
|
||||
from ctypes import Structure, Union, byref, wintypes, windll |
||||
|
||||
sys.path.append(os.path.join(sys.path[0],'..')) |
||||
|
||||
from TermTk.TTkCore.constant import TTkK |
||||
from TermTk.TTkCore.TTkTerm.inputmouse import TTkMouseEvent |
||||
|
||||
# Example ported from: |
||||
# https://learn.microsoft.com/en-us/windows/console/reading-input-buffer-events |
||||
|
||||
# https://learn.microsoft.com/en-us/windows/console/getstdhandle |
||||
STD_INPUT_HANDLE = wintypes.DWORD(-10) # The standard input device. Initially, this is the console input buffer, CONIN$. |
||||
STD_OUTPUT_HANDLE = wintypes.DWORD(-11) # The standard output device. Initially, this is the active console screen buffer, CONOUT$. |
||||
STD_ERROR_HANDLE = wintypes.DWORD(-12) # The standard error device. Initially, this is the active console screen buffer, CONOUT$. |
||||
|
||||
INVALID_HANDLE_VALUE = -1 # WinBase.h |
||||
|
||||
# https://learn.microsoft.com/en-us/windows/console/SetConsoleMode |
||||
ENABLE_ECHO_INPUT = 0x0004 # Characters read by the ReadFile or ReadConsole function are written to the active screen buffer as they are typed into the console. This mode can be used only if the ENABLE_LINE_INPUT mode is also enabled. |
||||
ENABLE_INSERT_MODE = 0x0020 # When enabled, text entered in a console window will be inserted at the current cursor location and all text following that location will not be overwritten. When disabled, all following text will be overwritten. |
||||
ENABLE_LINE_INPUT = 0x0002 # The ReadFile or ReadConsole function returns only when a carriage return character is read. If this mode is disabled, the functions return when one or more characters are available. |
||||
ENABLE_MOUSE_INPUT = 0x0010 # If the mouse pointer is within the borders of the console window and the window has the keyboard focus, mouse events generated by mouse movement and button presses are placed in the input buffer. These events are discarded by ReadFile or ReadConsole, even when this mode is enabled. The ReadConsoleInput function can be used to read MOUSE_EVENT input records from the input buffer. |
||||
ENABLE_PROCESSED_INPUT = 0x0001 # CTRL+C is processed by the system and is not placed in the input buffer. If the input buffer is being read by ReadFile or ReadConsole, other control keys are processed by the system and are not returned in the ReadFile or ReadConsole buffer. If the ENABLE_LINE_INPUT mode is also enabled, backspace, carriage return, and line feed characters are handled by the system. |
||||
ENABLE_QUICK_EDIT_MODE = 0x0040 # This flag enables the user to use the mouse to select and edit text. To enable this mode, use ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS. To disable this mode, use ENABLE_EXTENDED_FLAGS without this flag. |
||||
ENABLE_WINDOW_INPUT = 0x0008 # User interactions that change the size of the console screen buffer are reported in the console's input buffer. Information about these events can be read from the input buffer by applications using the ReadConsoleInput function, but not by those using ReadFile or ReadConsole. |
||||
ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200 # Setting this flag directs the Virtual Terminal processing engine to convert user input received by the console window into Console Virtual Terminal Sequences that can be retrieved by a supporting application through ReadFile or ReadConsole functions. |
||||
|
||||
ENABLE_PROCESSED_OUTPUT = 0x0001 |
||||
ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002 |
||||
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004 |
||||
DISABLE_NEWLINE_AUTO_RETURN = 0x0008 |
||||
ENABLE_LVB_GRID_WORLDWIDE = 0x0010 |
||||
|
||||
# https://learn.microsoft.com/en-us/windows/console/input-record-str |
||||
FOCUS_EVENT = 0x0010 # The Event member contains a FOCUS_EVENT_RECORD structure. These events are used internally and should be ignored. |
||||
KEY_EVENT = 0x0001 # The Event member contains a KEY_EVENT_RECORD structure with information about a keyboard event. |
||||
MENU_EVENT = 0x0008 # The Event member contains a MENU_EVENT_RECORD structure. These events are used internally and should be ignored. |
||||
MOUSE_EVENT = 0x0002 # The Event member contains a MOUSE_EVENT_RECORD structure with information about a mouse movement or button press event. |
||||
WINDOW_BUFFER_SIZE_EVENT = 0x0004 # The Event member contains a WINDOW_BUFFER_SIZE_RECORD structure with information about the new size of the console screen buffer. |
||||
|
||||
# https://learn.microsoft.com/en-us/windows/console/mouse-event-record-str |
||||
# dwButtonState |
||||
FROM_LEFT_1ST_BUTTON_PRESSED = 0x0001 # The leftmost mouse button. |
||||
FROM_LEFT_2ND_BUTTON_PRESSED = 0x0004 # The second button fom the left. |
||||
FROM_LEFT_3RD_BUTTON_PRESSED = 0x0008 # The third button from the left. |
||||
FROM_LEFT_4TH_BUTTON_PRESSED = 0x0010 # The fourth button from the left. |
||||
RIGHTMOST_BUTTON_PRESSED = 0x0002 # The rightmost mouse button. |
||||
# dwControlKeyState |
||||
CAPSLOCK_ON = 0x0080 # The CAPS LOCK light is on. |
||||
ENHANCED_KEY = 0x0100 # The key is enhanced. See remarks. |
||||
LEFT_ALT_PRESSED = 0x0002 # The left ALT key is pressed. |
||||
LEFT_CTRL_PRESSED = 0x0008 # The left CTRL key is pressed. |
||||
NUMLOCK_ON = 0x0020 # The NUM LOCK light is on. |
||||
RIGHT_ALT_PRESSED = 0x0001 # The right ALT key is pressed. |
||||
RIGHT_CTRL_PRESSED = 0x0004 # The right CTRL key is pressed. |
||||
SCROLLLOCK_ON = 0x0040 # The SCROLL LOCK light is on. |
||||
SHIFT_PRESSED = 0x0010 # The SHIFT key is pressed. |
||||
# dwEventFlags |
||||
DOUBLE_CLICK = 0x0002 # The second click (button press) of a double-click occurred. The first click is returned as a regular button-press event. |
||||
MOUSE_HWHEELED = 0x0008 # The horizontal mouse wheel was moved. |
||||
# If the high word of the dwButtonState member contains a positive value, the wheel was rotated to the right. Otherwise, the wheel was rotated to the left. |
||||
MOUSE_MOVED = 0x0001 # A change in mouse position occurred. |
||||
MOUSE_WHEELED = 0x0004 # The vertical mouse wheel was moved. |
||||
# If the high word of the dwButtonState member contains a positive value, the wheel was rotated forward, away from the user. Otherwise, the wheel was rotated backward, toward the user. |
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/coord-str |
||||
# |
||||
# typedef struct _COORD { |
||||
# SHORT X; |
||||
# SHORT Y; |
||||
# } COORD, *PCOORD; |
||||
class COORD(Structure): |
||||
_fields_ = [ |
||||
("X", wintypes.SHORT), |
||||
("Y", wintypes.SHORT)] |
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/key-event-record-str |
||||
# |
||||
# typedef struct _KEY_EVENT_RECORD { |
||||
# BOOL bKeyDown; |
||||
# WORD wRepeatCount; |
||||
# WORD wVirtualKeyCode; |
||||
# WORD wVirtualScanCode; |
||||
# union { |
||||
# WCHAR UnicodeChar; |
||||
# CHAR AsciiChar; |
||||
# } uChar; |
||||
# DWORD dwControlKeyState; |
||||
# } KEY_EVENT_RECORD; |
||||
class KEY_EVENT_RECORD(Structure): |
||||
class _uChar(Union): |
||||
_fields_ = [ |
||||
("UnicodeChar", wintypes.WCHAR) , |
||||
("AsciiChar" , wintypes.CHAR ) ] |
||||
|
||||
_fields_ = [ |
||||
("bKeyDown" , wintypes.BOOL ), |
||||
("wRepeatCount" , wintypes.WORD ), |
||||
("wVirtualKeyCode" , wintypes.WORD ), |
||||
("wVirtualScanCode" , wintypes.WORD ), |
||||
("uChar" , _uChar ), |
||||
("dwControlKeyState", wintypes.DWORD)] |
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str |
||||
# |
||||
# typedef struct _MOUSE_EVENT_RECORD { |
||||
# COORD dwMousePosition; |
||||
# DWORD dwButtonState; |
||||
# DWORD dwControlKeyState; |
||||
# DWORD dwEventFlags; |
||||
# } MOUSE_EVENT_RECORD; |
||||
class MOUSE_EVENT_RECORD(Structure): |
||||
_fields_ = [ |
||||
("dwMousePosition" , COORD), |
||||
("dwButtonState" , wintypes.DWORD), |
||||
("dwControlKeyState", wintypes.DWORD), |
||||
("dwEventFlags" , wintypes.DWORD)] |
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/window-buffer-size-record-str |
||||
# |
||||
# typedef struct _WINDOW_BUFFER_SIZE_RECORD { |
||||
# COORD dwSize; |
||||
# } WINDOW_BUFFER_SIZE_RECORD; |
||||
class WINDOW_BUFFER_SIZE_RECORD(Structure): |
||||
_fields_ = [("dwSize", COORD)] |
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/menu-event-record-str |
||||
# |
||||
# typedef struct _MENU_EVENT_RECORD { |
||||
# UINT dwCommandId; |
||||
# } MENU_EVENT_RECORD, *PMENU_EVENT_RECORD; |
||||
class MENU_EVENT_RECORD(Structure): |
||||
_fields_ = [("dwCommandId", wintypes.UINT)] |
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/focus-event-record-str |
||||
# |
||||
# typedef struct _FOCUS_EVENT_RECORD { |
||||
# BOOL bSetFocus; |
||||
# } FOCUS_EVENT_RECORD; |
||||
class FOCUS_EVENT_RECORD(Structure): |
||||
_fields_ = [("bSetFocus", wintypes.BOOL)] |
||||
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/input-record-str |
||||
# |
||||
# typedef struct _INPUT_RECORD { |
||||
# WORD EventType; |
||||
# union { |
||||
# KEY_EVENT_RECORD KeyEvent; |
||||
# MOUSE_EVENT_RECORD MouseEvent; |
||||
# WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent; |
||||
# MENU_EVENT_RECORD MenuEvent; |
||||
# FOCUS_EVENT_RECORD FocusEvent; |
||||
# } Event; |
||||
# } INPUT_RECORD; |
||||
class INPUT_RECORD(Structure): |
||||
class _Event(Union): |
||||
_fields_ = [ |
||||
("KeyEvent" , KEY_EVENT_RECORD ), |
||||
("MouseEvent" , MOUSE_EVENT_RECORD ), |
||||
("WindowBufferSizeEvent", WINDOW_BUFFER_SIZE_RECORD), |
||||
("MenuEvent" , MENU_EVENT_RECORD ), |
||||
("FocusEvent" , FOCUS_EVENT_RECORD )] |
||||
|
||||
_fields_ = [ |
||||
("EventType", wintypes.WORD), |
||||
("Event" , _Event )] |
||||
|
||||
|
||||
def reset(): |
||||
# Reset |
||||
sys.stdout.write("\033[?1000l") |
||||
# sys.stdout.write("\033[?1002l") |
||||
sys.stdout.write("\033[?1003l") |
||||
sys.stdout.write("\x1b[?1004l") # UnSet Bracheted Paste Mode |
||||
sys.stdout.write("\033[?1006l") |
||||
sys.stdout.write("\033[?1015l") |
||||
# sys.stdout.write("\033[?1049l") # Switch to normal screen |
||||
# sys.stdout.write("\033[?2004l") # Paste Bracketed mode |
||||
sys.stdout.flush() |
||||
|
||||
def init(): |
||||
sys.stdout.write("\x1b[?1000h") |
||||
sys.stdout.write("\x1b[?1003h") |
||||
sys.stdout.write("\x1b[?1004h") # Set Bracheted Paste Mode |
||||
sys.stdout.write("\x1b[?1006h") |
||||
sys.stdout.write("\x1b[?1015h") |
||||
sys.stdout.flush() |
||||
|
||||
# Get the standard input handle. |
||||
# From: |
||||
# https://learn.microsoft.com/en-us/windows/console/getstdhandle |
||||
# |
||||
# HANDLE WINAPI GetStdHandle( |
||||
# _In_ DWORD nStdHandle |
||||
# ); |
||||
|
||||
GetStdHandle = windll.kernel32.GetStdHandle |
||||
GetStdHandle.argtypes = [wintypes.DWORD] |
||||
GetStdHandle.restype = wintypes.HANDLE |
||||
|
||||
hStdIn = GetStdHandle(STD_INPUT_HANDLE) |
||||
if hStdIn == INVALID_HANDLE_VALUE: |
||||
raise Exception("GetStdHandle") |
||||
|
||||
hStdOut = GetStdHandle(STD_OUTPUT_HANDLE) |
||||
if hStdOut == INVALID_HANDLE_VALUE: |
||||
raise Exception("GetStdHandle") |
||||
|
||||
# Save the current input mode, to be restored on exit. |
||||
# From: |
||||
# https://learn.microsoft.com/en-us/windows/console/GetConsoleMode |
||||
# |
||||
# BOOL WINAPI GetConsoleMode( |
||||
# _In_ HANDLE hConsoleHandle, |
||||
# _Out_ LPDWORD lpMode |
||||
# ); |
||||
|
||||
GetConsoleMode = windll.kernel32.GetConsoleMode |
||||
GetConsoleMode.argtypes = [wintypes.HANDLE, wintypes.LPDWORD] |
||||
GetConsoleMode.restype = wintypes.BOOL |
||||
|
||||
fdwSaveOldModeIn = wintypes.DWORD() |
||||
if not GetConsoleMode(hStdIn, byref(fdwSaveOldModeIn)): |
||||
raise Exception("GetConsoleMode") |
||||
|
||||
fdwSaveOldModeOut = wintypes.DWORD() |
||||
if not GetConsoleMode(hStdOut, byref(fdwSaveOldModeOut)): |
||||
raise Exception("GetConsoleMode") |
||||
|
||||
print(f"{fdwSaveOldModeIn.value=:02x}") |
||||
print(f"{fdwSaveOldModeOut.value=:02x}") |
||||
|
||||
# Enable the window and mouse input events. |
||||
# From: |
||||
# https://learn.microsoft.com/en-us/windows/console/SetConsoleMode |
||||
# |
||||
# BOOL WINAPI SetConsoleMode( |
||||
# _In_ HANDLE hConsoleHandle, |
||||
# _In_ DWORD dwMode |
||||
# ); |
||||
|
||||
SetConsoleMode = windll.kernel32.SetConsoleMode |
||||
SetConsoleMode.argtypes = [wintypes.HANDLE, wintypes.DWORD] |
||||
SetConsoleMode.restype = wintypes.BOOL |
||||
|
||||
fdwModeIn = ENABLE_VIRTUAL_TERMINAL_INPUT |
||||
# fdwModeIn = ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT |
||||
# fdwModeIn = 0x0218 |
||||
if not SetConsoleMode(hStdIn, fdwModeIn): |
||||
raise Exception("SetConsoleMode") |
||||
|
||||
fdwModeOut = fdwSaveOldModeOut.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING |
||||
# fdwModeIn = 0x0218 |
||||
if not SetConsoleMode(hStdOut, fdwModeOut): |
||||
raise Exception("SetConsoleMode") |
||||
|
||||
print(f"{fdwModeIn=:02x}") |
||||
print(f"{fdwModeOut=:02x}") |
||||
|
||||
init() |
||||
|
||||
# From: |
||||
# https://learn.microsoft.com/en-us/windows/console/ReadConsoleInput |
||||
# |
||||
# BOOL WINAPI ReadConsoleInput( |
||||
# _In_ HANDLE hConsoleInput, |
||||
# _Out_ PINPUT_RECORD lpBuffer, |
||||
# _In_ DWORD nLength, |
||||
# _Out_ LPDWORD lpNumberOfEventsRead |
||||
# ); |
||||
|
||||
ReadConsoleInput = windll.kernel32.ReadConsoleInputW # Unicode |
||||
# ReadConsoleInput = windll.kernel32.ReadConsoleInputA # ANSII |
||||
# ReadConsoleInput.argtypes = [wintypes.HANDLE, |
||||
# wintypes.LPINT, |
||||
# wintypes.DWORD, |
||||
# wintypes.LPWORD] |
||||
ReadConsoleInput.restype = wintypes.BOOL |
||||
|
||||
# DWORD cNumRead; |
||||
# INPUT_RECORD irInBuf[128]; |
||||
cNumRead = wintypes.DWORD(0) |
||||
irInBuf = (INPUT_RECORD * 256)() |
||||
|
||||
# Loop to read and handle the next 100 input events. |
||||
for _ in range(50): |
||||
# Wait for the events. |
||||
if not ReadConsoleInput( |
||||
hStdIn, # input buffer handle |
||||
byref(irInBuf), # buffer to read into |
||||
256, # size of read buffer |
||||
byref(cNumRead)): # number of records read |
||||
raise Exception("ReadConsoleInput") |
||||
|
||||
# print(f"{hStdIn=} {irInBuf=} {cNumRead=}") |
||||
print(f"{cNumRead=}") |
||||
|
||||
# Dispatch the events to the appropriate handler. |
||||
lastMousePress = 0 |
||||
saveKeyb = b"" |
||||
saveKeys = b"" |
||||
listKeys = [] |
||||
for bb in irInBuf[:cNumRead.value]: |
||||
# if not bb.EventType: continue |
||||
# print(f"{bb=} {bb.EventType=} {cNumRead.value=}") |
||||
|
||||
if bb.EventType == MOUSE_EVENT: |
||||
x = bb.Event.MouseEvent.dwMousePosition.X |
||||
y = bb.Event.MouseEvent.dwMousePosition.Y |
||||
print(f"{bb.Event.MouseEvent.dwControlKeyState=}") |
||||
print(f"{bb.Event.MouseEvent.dwEventFlags=}") |
||||
bstate = bb.Event.MouseEvent.dwButtonState |
||||
cstate = bb.Event.MouseEvent.dwControlKeyState |
||||
|
||||
key = TTkMouseEvent.NoButton |
||||
evt = TTkMouseEvent.Move |
||||
mod = TTkK.NoModifier |
||||
tap = 0 |
||||
# Release the mouse |
||||
if not bstate and lastMousePress: |
||||
pass |
||||
|
||||
# Ignore the input if another button is pressed while holding the previous |
||||
if lastMousePress and lastMousePress & bstate: |
||||
continue |
||||
|
||||
# Release the mouse if another button is pressed |
||||
# while still holding the first one |
||||
if lastMousePress and lastMousePress != (bstate&lastMousePress): |
||||
pass |
||||
|
||||
if cstate & CAPSLOCK_ON: pass |
||||
if cstate & ENHANCED_KEY: pass |
||||
if cstate & LEFT_ALT_PRESSED: mod |= TTkK.AltModifier |
||||
if cstate & LEFT_CTRL_PRESSED: mod |= TTkK.ControlModifier |
||||
if cstate & NUMLOCK_ON: pass |
||||
if cstate & RIGHT_ALT_PRESSED: mod |= TTkK.AltModifier |
||||
if cstate & RIGHT_CTRL_PRESSED: mod |= TTkK.ControlModifier |
||||
if cstate & SCROLLLOCK_ON: pass |
||||
if cstate & SHIFT_PRESSED: mod |= TTkK.ShiftModifier |
||||
|
||||
# Exclude extra button pressed at the same time |
||||
if bstate & RIGHTMOST_BUTTON_PRESSED: |
||||
key = TTkMouseEvent.RightButton |
||||
lastMousePress = RIGHTMOST_BUTTON_PRESSED |
||||
elif bstate & FROM_LEFT_1ST_BUTTON_PRESSED: |
||||
key = TTkMouseEvent.LeftButton |
||||
lastMousePress = FROM_LEFT_1ST_BUTTON_PRESSED |
||||
elif bstate & FROM_LEFT_2ND_BUTTON_PRESSED: |
||||
key = TTkMouseEvent.MidButton |
||||
lastMousePress = FROM_LEFT_2ND_BUTTON_PRESSED |
||||
elif bstate & FROM_LEFT_3RD_BUTTON_PRESSED: |
||||
lastMousePress = 0 # FROM_LEFT_3RD_BUTTON_PRESSED |
||||
elif bstate & FROM_LEFT_4TH_BUTTON_PRESSED: |
||||
lastMousePress = 0 # FROM_LEFT_4TH_BUTTON_PRESSED |
||||
mevt = TTkMouseEvent(x, y, key, evt, mod, tap, "") |
||||
print(f"{str(mevt)=}") |
||||
|
||||
elif bb.EventType == WINDOW_BUFFER_SIZE_EVENT: |
||||
print(f"{bb.Event.WindowBufferSizeEvent=}") |
||||
print(f"{bb.Event.WindowBufferSizeEvent.dwSize.X=}") |
||||
print(f"{bb.Event.WindowBufferSizeEvent.dwSize.Y=}") |
||||
elif bb.EventType == KEY_EVENT: |
||||
# if not bb.Event.KeyEvent.bKeyDown: |
||||
# saveKeys += bb.Event.KeyEvent.uChar.UnicodeChar |
||||
# saveKeyb += bb.Event.KeyEvent.uChar.AsciiChar |
||||
# listKeys.append() |
||||
key = bb.Event.KeyEvent.uChar.UnicodeChar |
||||
if bb.Event.KeyEvent.bKeyDown or key == "\x1b": |
||||
if (bb.Event.KeyEvent.dwControlKeyState |
||||
and bb.Event.KeyEvent.wVirtualKeyCode ): |
||||
continue |
||||
listKeys.append(key) |
||||
#continue |
||||
print( |
||||
# f" evt:{bb.Event.KeyEvent}" + |
||||
f"\tkd:{bb.Event.KeyEvent.bKeyDown}" + |
||||
f"\trc:{bb.Event.KeyEvent.wRepeatCount}" + |
||||
f"\tVKC:{bb.Event.KeyEvent.wVirtualKeyCode}" + |
||||
f"\tVSC:{bb.Event.KeyEvent.wVirtualScanCode}" + |
||||
f"\tUC:{ord(bb.Event.KeyEvent.uChar.UnicodeChar):x}" + |
||||
f"\tAC:{bb.Event.KeyEvent.uChar.AsciiChar}" + |
||||
f"\tCKS:{bb.Event.KeyEvent.dwControlKeyState} -> {listKeys=}" |
||||
) |
||||
|
||||
print(f"{listKeys=}") |
||||
kk = "".join(listKeys) |
||||
print(f"{kk=}") |
||||
kk = kk.encode("utf-16", "surrogatepass") |
||||
print(f"{kk=}") |
||||
kk = kk.decode("utf-16") |
||||
print(f"{kk=}") |
||||
|
||||
|
||||
# Restore input mode on exit. |
||||
if not SetConsoleMode(hStdIn, fdwSaveOldModeIn): |
||||
raise Exception("SetConsoleMode") |
||||
|
||||
if not SetConsoleMode(hStdOut, fdwSaveOldModeOut): |
||||
raise Exception("SetConsoleMode") |
||||
|
||||
# return 0; |
||||
# |
||||
|
||||
reset() |
||||
print('OK') |
||||
@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the"Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED"AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
# This test is based on: |
||||
# pyte - In memory VTXXX-compatible terminal emulator. |
||||
# Terminal Emulator Example |
||||
# https://github.com/selectel/pyte/blob/master/examples/terminal_emulator.py |
||||
# |
||||
# pty — Pseudo-terminal utilities¶ |
||||
# https://docs.python.org/3/library/pty.html#example |
||||
# |
||||
# Using a pseudo-terminal to interact with interactive Python in a subprocess |
||||
# by Thomas Billinger |
||||
# https://gist.github.com/thomasballinger/7979808 |
||||
# |
||||
# Run interactive Bash with popen and a dedicated TTY Python |
||||
# https://stackoverflow.com/questions/41542960/run-interactive-bash-with-popen-and-a-dedicated-tty-python |
||||
|
||||
import os |
||||
import pty |
||||
import sys |
||||
import threading |
||||
import argparse |
||||
from select import select |
||||
|
||||
sys.path.append(os.path.join(sys.path[0],'..')) |
||||
import TermTk as ttk |
||||
|
||||
parser = argparse.ArgumentParser() |
||||
parser.add_argument('-d', help='Debug (Add LogViewer Panel)', action='store_true') |
||||
args = parser.parse_args() |
||||
|
||||
# ttk.TTkLog.use_default_file_logging() |
||||
root = ttk.TTk(layout=ttk.TTkGridLayout(), mouseTrack=True) |
||||
|
||||
split = ttk.TTkSplitter(parent=root, orientation=ttk.TTkK.VERTICAL) |
||||
|
||||
split.addItem(top := ttk.TTkLayout()) |
||||
|
||||
if args.d: |
||||
split.addWidget(ttk.TTkLogViewer(follow=False ), title='Log', size=20) |
||||
|
||||
quitBtn = ttk.TTkButton(text="QUIT", border=True) |
||||
quitBtn.clicked.connect(ttk.TTkHelper.quit) |
||||
|
||||
cb_c = ttk.TTkCheckbox(pos=(0,3),size=(20,1), text="CTRL-C (VINTR) ", checked=ttk.TTkK.Checked) |
||||
cb_s = ttk.TTkCheckbox(pos=(0,4),size=(20,1), text="CTRL-S (VSTOP) ", checked=ttk.TTkK.Checked) |
||||
cb_z = ttk.TTkCheckbox(pos=(0,5),size=(20,1), text="CTRL-Z (VSUSP) ", checked=ttk.TTkK.Checked) |
||||
cb_q = ttk.TTkCheckbox(pos=(0,6),size=(20,1), text="CTRL-Q (VSTART)", checked=ttk.TTkK.Checked) |
||||
|
||||
cb_c.stateChanged.connect(lambda x: ttk.TTkTerm.setSigmask(ttk.TTkTerm.Sigmask.CTRL_C,x==ttk.TTkK.Checked)) |
||||
cb_s.stateChanged.connect(lambda x: ttk.TTkTerm.setSigmask(ttk.TTkTerm.Sigmask.CTRL_S,x==ttk.TTkK.Checked)) |
||||
cb_z.stateChanged.connect(lambda x: ttk.TTkTerm.setSigmask(ttk.TTkTerm.Sigmask.CTRL_Z,x==ttk.TTkK.Checked)) |
||||
cb_q.stateChanged.connect(lambda x: ttk.TTkTerm.setSigmask(ttk.TTkTerm.Sigmask.CTRL_Q,x==ttk.TTkK.Checked)) |
||||
|
||||
win = ttk.TTkWindow(pos=(10,0), size=(100,30), title="Terminallo n.2", border=True, layout=ttk.TTkVBoxLayout(), flags = ttk.TTkK.WindowFlag.WindowMinMaxButtonsHint|ttk.TTkK.WindowFlag.WindowCloseButtonHint) |
||||
term = ttk.TTkTerminal(parent=win) |
||||
term.bell.connect(lambda : ttk.TTkLog.debug("BELL!!! 🔔🔔🔔")) |
||||
term.titleChanged.connect(win.setTitle) |
||||
term.runShell() |
||||
term.terminalClosed.connect(win.close) |
||||
win.closed.connect(term.close) |
||||
|
||||
top.addWidgets([quitBtn, cb_c, cb_s, cb_z, cb_q, win]) |
||||
|
||||
term.setFocus() |
||||
|
||||
root.mainloop() |
||||
@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the"Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED"AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
import os, sys, argparse |
||||
from select import select |
||||
|
||||
sys.path.append(os.path.join(sys.path[0],'..')) |
||||
import TermTk as ttk |
||||
|
||||
parser = argparse.ArgumentParser() |
||||
parser.add_argument('-d', help='Debug (Add LogViewer Panel)', action='store_true') |
||||
args = parser.parse_args() |
||||
|
||||
# ttk.TTkLog.use_default_file_logging() |
||||
root = ttk.TTk(layout=ttk.TTkGridLayout(), mouseTrack=True) |
||||
|
||||
split = ttk.TTkSplitter(parent=root, orientation=ttk.TTkK.VERTICAL) |
||||
|
||||
split.addItem(top := ttk.TTkLayout()) |
||||
|
||||
if args.d: |
||||
split.addWidget(ttk.TTkLogViewer(follow=False ), title='Log', size=20) |
||||
|
||||
quitBtn = ttk.TTkButton(text="QUIT", border=True) |
||||
quitBtn.clicked.connect(ttk.TTkHelper.quit) |
||||
|
||||
cb_c = ttk.TTkCheckbox(pos=(0,3),size=(20,1), text="CTRL-C (VINTR) ", checked=ttk.TTkK.Checked) |
||||
cb_s = ttk.TTkCheckbox(pos=(0,4),size=(20,1), text="CTRL-S (VSTOP) ", checked=ttk.TTkK.Checked) |
||||
cb_z = ttk.TTkCheckbox(pos=(0,5),size=(20,1), text="CTRL-Z (VSUSP) ", checked=ttk.TTkK.Checked) |
||||
cb_q = ttk.TTkCheckbox(pos=(0,6),size=(20,1), text="CTRL-Q (VSTART)", checked=ttk.TTkK.Checked) |
||||
|
||||
cb_c.stateChanged.connect(lambda x: ttk.TTkTerm.setSigmask(ttk.TTkTerm.Sigmask.CTRL_C,x==ttk.TTkK.Checked)) |
||||
cb_s.stateChanged.connect(lambda x: ttk.TTkTerm.setSigmask(ttk.TTkTerm.Sigmask.CTRL_S,x==ttk.TTkK.Checked)) |
||||
cb_z.stateChanged.connect(lambda x: ttk.TTkTerm.setSigmask(ttk.TTkTerm.Sigmask.CTRL_Z,x==ttk.TTkK.Checked)) |
||||
cb_q.stateChanged.connect(lambda x: ttk.TTkTerm.setSigmask(ttk.TTkTerm.Sigmask.CTRL_Q,x==ttk.TTkK.Checked)) |
||||
|
||||
win = ttk.TTkWindow(pos=(10,0), size=(100,30), title="Terminallo n.2", border=True, layout=ttk.TTkVBoxLayout(), flags = ttk.TTkK.WindowFlag.WindowMinMaxButtonsHint|ttk.TTkK.WindowFlag.WindowCloseButtonHint) |
||||
term = ttk.TTkTerminal(parent=win) |
||||
term.bell.connect(lambda : ttk.TTkLog.debug("BELL!!! 🔔🔔🔔")) |
||||
term.titleChanged.connect(win.setTitle) |
||||
term.runShell() |
||||
term.terminalClosed.connect(win.close) |
||||
win.closed.connect(term.close) |
||||
|
||||
winT = ttk.TTkWindow(pos=(20,10), size=(100,30), title="TextEdit", border=True, layout=ttk.TTkVBoxLayout(), flags = ttk.TTkK.WindowFlag.WindowMinMaxButtonsHint|ttk.TTkK.WindowFlag.WindowCloseButtonHint) |
||||
ttk.TTkTextEdit(parent=winT, readOnly=False, lineNumber=True) |
||||
|
||||
top.addWidgets([quitBtn, cb_c, cb_s, cb_z, cb_q, win, winT]) |
||||
|
||||
term.setFocus() |
||||
|
||||
root.mainloop() |
||||
@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
import sys, os, weakref |
||||
|
||||
import timeit |
||||
from threading import Lock |
||||
|
||||
class Foo(): |
||||
def a(self,v): |
||||
return v+v*v |
||||
|
||||
f1 = Foo() |
||||
f21 = Foo() |
||||
f22 = Foo() |
||||
|
||||
a1 = f1.a |
||||
a21 = weakref.WeakMethod(f21.a) |
||||
a22 = weakref.WeakMethod(f22.a) |
||||
a31 = weakref.ref(_a31:=f21.a) |
||||
a32 = weakref.ref(_a32:=f22.a) |
||||
|
||||
del f22,_a32 |
||||
|
||||
def test1(v=a1,ff=f1): return sum([ v(x) for x in range(100)]) |
||||
|
||||
def test2(v=a21,ff=f21): return sum([v()(x) if v() else 0 for x in range(100)]) |
||||
def test3(v=a22,ff=f21): return sum([v()(x) if v() else 0 for x in range(100)]) |
||||
def test4(v=a21,ff=f21): return sum([ _v(x) if (_v:=v()) else 0 for x in range(100)]) |
||||
def test5(v=a22,ff=f21): return sum([ _v(x) if (_v:=v()) else 0 for x in range(100)]) |
||||
|
||||
def test6(v=a31,ff=f21): return sum([v()(x) if v() else 0 for x in range(100)]) |
||||
def test7(v=a32,ff=f21): return sum([v()(x) if v() else 0 for x in range(100)]) |
||||
def test8(v=a31,ff=f21): return sum([ _v(x) if (_v:=v()) else 0 for x in range(100)]) |
||||
def test9(v=a32,ff=f21): return sum([ _v(x) if (_v:=v()) else 0 for x in range(100)]) |
||||
|
||||
loop = 10000 |
||||
|
||||
a = {} |
||||
|
||||
iii = 1 |
||||
while (testName := f'test{iii}') and (testName in globals()): |
||||
result = timeit.timeit(f'{testName}(*a)', globals=globals(), number=loop) |
||||
# print(f"test{iii}) fps {loop / result :.3f} - s {result / loop:.10f} - {result / loop} {globals()[testName](*a)}") |
||||
print(f"test{iii:02}) | {result / loop:.10f} sec. | {loop / result : 15.3f} Fps ╞╡-> {globals()[testName](*a)}") |
||||
iii+=1 |
||||
|
||||
@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
import sys, os, weakref |
||||
|
||||
import timeit |
||||
from queue import Queue |
||||
|
||||
qu = Queue() |
||||
r = 100 |
||||
|
||||
def test1(q=qu): |
||||
ret = 0 |
||||
for i in range(r): |
||||
ret += i |
||||
return ret |
||||
|
||||
def test2(q=qu): |
||||
ret = 0 |
||||
for i in range(r): |
||||
qu.put(i) |
||||
while x := q.get(): |
||||
ret += x |
||||
return ret |
||||
|
||||
def test3(q=qu): |
||||
ret = 0 |
||||
ar = [] |
||||
for i in range(r): |
||||
ar.append(i) |
||||
for x in ar: |
||||
ret += x |
||||
return ret |
||||
|
||||
def test4(q=qu): |
||||
return sum(i for i in range(r)) |
||||
|
||||
def test5(q=qu): |
||||
ar = [] |
||||
for i in range(r): |
||||
ar.append(i) |
||||
return sum(ar) |
||||
|
||||
def test6(q=qu): |
||||
ret = 0 |
||||
ar = [] |
||||
for i in range(r): |
||||
ar.append(i) |
||||
while ar: |
||||
ret += ar.pop() |
||||
return ret |
||||
|
||||
loop = 1000 |
||||
|
||||
a = {} |
||||
|
||||
iii = 1 |
||||
while (testName := f'test{iii}') and (testName in globals()): |
||||
result = timeit.timeit(f'{testName}(*a)', globals=globals(), number=loop) |
||||
# print(f"test{iii}) fps {loop / result :.3f} - s {result / loop:.10f} - {result / loop} {globals()[testName](*a)}") |
||||
print(f"test{iii:02}) | {result / loop:.10f} sec. | {loop / result : 15.3f} Fps ╞╡-> {globals()[testName](*a)}") |
||||
iii+=1 |
||||
|
||||
@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
# Example inspired by |
||||
# https://stackoverflow.com/questions/39838793/python-object-is-being-referenced-by-an-object-i-cannot-find |
||||
|
||||
import gc, weakref |
||||
|
||||
class Foo(object): |
||||
__slots__ = ('a','b') |
||||
def __init__(self, a=1234) -> None: |
||||
self.a = a |
||||
self.b = lambda : self.a |
||||
|
||||
def f(self): |
||||
return self.a |
||||
|
||||
# def __del__(self): |
||||
# print(f"Deleted {self}") |
||||
|
||||
def pobjs(): |
||||
for i,o in enumerate(gc.get_objects()[-100:]): |
||||
ss = str(o) |
||||
if "Foo" in ss: |
||||
print(f" * {i} - {ss}") |
||||
|
||||
v1 = {'b':2345} |
||||
|
||||
print(f"\nStart {gc.isenabled()=}") |
||||
# print(f"{gc.set_debug(gc.DEBUG_LEAK)=}") |
||||
|
||||
print("\n############# Phase 1 ##################") |
||||
foo = Foo(v1) |
||||
print(f"{gc.get_referents(foo)=}") |
||||
print(f"{gc.get_count()=}") |
||||
print(f"{foo.a=} - {foo.b=} - {foo.f()=}") |
||||
del foo |
||||
print(f"{gc.collect()=}") |
||||
|
||||
print("\n############# Phase 2 ##################") |
||||
foo = Foo(v1) |
||||
bar = foo.a |
||||
print(f"{gc.get_referents(foo)=}") |
||||
print(f"{gc.get_count()=}") |
||||
print(f"{foo.a=} - {foo.b=} - {foo.f()=} - {bar=}") |
||||
del foo |
||||
print(f"{gc.collect()=}") |
||||
print(f"{bar=}") |
||||
|
||||
print("\n############# Phase 3 ##################") |
||||
foo = Foo(v1) |
||||
bar = foo.b |
||||
print(f"{gc.get_referents(foo)=}") |
||||
print(f"{gc.get_count()=}") |
||||
print(f"{foo.a=} - {foo.b=} - {foo.f()=} - {bar()=}") |
||||
del foo |
||||
print(f"{gc.collect()=}") |
||||
print(f"{bar()=}") |
||||
|
||||
print("\n############# Phase 4 ##################") |
||||
foo = Foo(v1) |
||||
bar = foo.b |
||||
print(f"{gc.get_referents(foo)=}") |
||||
print(f"{gc.get_referents(v1)=}") |
||||
print(f"{gc.get_count()=}") |
||||
print(f"{foo.a=} - {foo.b=} - {foo.f()=} - {bar()=}") |
||||
del foo |
||||
pobjs() |
||||
print(f"{gc.collect()=}") |
||||
print(f"{bar()=}") |
||||
del bar |
||||
pobjs() |
||||
print(f"{gc.collect()=}") |
||||
pobjs() |
||||
|
||||
print("\n############# Phase 5 ##################") |
||||
foo = Foo(v1) |
||||
bar = weakref.ref(foo.b) |
||||
xx = foo.f |
||||
baz = weakref.ref(xx) |
||||
print(f"{gc.get_referents(foo)=}") |
||||
print(f"{gc.get_referents(v1)=}") |
||||
print(f"{gc.get_count()=}") |
||||
print(f"{foo.a=} - {foo.b=} - {foo.f()=} - {bar()()=}") |
||||
del foo |
||||
pobjs() |
||||
print(f"{gc.collect()=}") |
||||
print(f"{bar()() if bar() else None=}") |
||||
del bar |
||||
pobjs() |
||||
print(f"{gc.collect()=}") |
||||
pobjs() |
||||
|
||||
print(f"{gc.garbage=}") |
||||
print(f"End {gc.get_count()=}") |
||||
@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
# Example inspired by |
||||
# https://stackoverflow.com/questions/39838793/python-object-is-being-referenced-by-an-object-i-cannot-find |
||||
|
||||
import gc, weakref, time |
||||
|
||||
class Foo(): |
||||
__slots__ = ('__weakref__','a','b') |
||||
def __init__(self, a=1234) -> None: |
||||
self.a = a |
||||
self.b = lambda : self.a |
||||
|
||||
def f(self): |
||||
return self.a |
||||
|
||||
# def __del__(self): |
||||
# print(f"Deleted {self}") |
||||
|
||||
def pobjs(): |
||||
for i,o in enumerate(gc.get_objects()[-100:]): |
||||
ss = str(o) |
||||
if "Foo" in ss: |
||||
print(f" * {i} - {ss}") |
||||
|
||||
v1 = {'b':2345} |
||||
|
||||
print(f"\nStart {gc.isenabled()=}") |
||||
# print(f"{gc.set_debug(gc.DEBUG_LEAK)=}") |
||||
|
||||
def _gccb(phase,info): |
||||
print(f" ---> {gc.garbage=}") |
||||
print(f" ---> {phase=} {info=}") |
||||
|
||||
# gc.callbacks.append(_gccb) |
||||
|
||||
print("\n############# Phase 1 ##################") |
||||
foo = Foo(v1) |
||||
bar =foo.b |
||||
|
||||
wrfoo = weakref.ref(foo) |
||||
wrbar = weakref.ref(bar) |
||||
wrf = weakref.WeakMethod(foo.f) |
||||
|
||||
# print(f"{gc.get_referents(foo)=}") |
||||
# print(f"{gc.get_referrers(foo)=}") |
||||
# print(f"{gc.get_referents(v1)=}") |
||||
# print(f"{gc.get_referrers(v1)=}") |
||||
# print(f"{gc.get_count()=}") |
||||
print(f"{foo.a=} - {foo.b=} - {foo.f()=} - {bar()=}") |
||||
print(f"{wrfoo()=} {wrbar()=} {wrf()=}") |
||||
del foo |
||||
print(f"{gc.collect()=}") |
||||
print(f"{bar()}") |
||||
# print(f"{gc.get_referents(v1)=}") |
||||
# print(f"{gc.get_referrers(v1)=}") |
||||
print(f"{wrfoo()=} {wrbar()=} {wrf()=}") |
||||
bar = None |
||||
print(f"{wrfoo()=} {wrbar()=} {wrf()=}") |
||||
time.sleep(4) |
||||
print(f"{wrfoo()=} {wrbar()=} {wrf()=}") |
||||
print(f"{gc.collect()=}") |
||||
print(f"{wrfoo()=} {wrbar()=} {wrf()=}") |
||||
|
||||
print(f"{gc.garbage=}") |
||||
print(f"End {gc.get_count()=}") |
||||
@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
# Example inspired by |
||||
# https://stackoverflow.com/questions/39838793/python-object-is-being-referenced-by-an-object-i-cannot-find |
||||
|
||||
import gc, weakref, time |
||||
|
||||
class Bar(): |
||||
__slots__ = ('_foo') |
||||
def __init__(self, foo) -> None: |
||||
self._foo = foo |
||||
|
||||
class Foo(): |
||||
__slots__ = ('__weakref__','a','b','_bar') |
||||
def __init__(self, a=1234) -> None: |
||||
self._bar = Bar(self) |
||||
self.a = a |
||||
self.b = lambda : self.a |
||||
|
||||
def f(self): |
||||
return self.a |
||||
|
||||
# def __del__(self): |
||||
# print(f"Deleted {self}") |
||||
|
||||
def pobjs(): |
||||
for i,o in enumerate(gc.get_objects()[-100:]): |
||||
ss = str(o) |
||||
if "Foo" in ss: |
||||
print(f" * {i} - {ss}") |
||||
|
||||
def _ref(o): |
||||
print(f"\n### -> Referents - {o}") |
||||
for i,r in enumerate(gc.get_referents(o)): |
||||
print(f" - {i} ) {r}") |
||||
print(f"\n### -> Referrers - {o}") |
||||
for i,r in enumerate(gc.get_referrers(o)): |
||||
print(f" - {i} ) {r}") |
||||
print("") |
||||
|
||||
v1 = {'b':2345} |
||||
|
||||
print(f"\nStart {gc.isenabled()=}") |
||||
# print(f"{gc.set_debug(gc.DEBUG_LEAK)=}") |
||||
|
||||
def _gccb(phase,info): |
||||
print(f" ---> {gc.garbage=}") |
||||
print(f" ---> {phase=} {info=}") |
||||
|
||||
# gc.callbacks.append(_gccb) |
||||
|
||||
print("\n############# Phase 1 ##################") |
||||
foo = Foo(v1) |
||||
bar =foo.b |
||||
|
||||
wrfoo = weakref.ref(foo) |
||||
wrbar = weakref.ref(bar) |
||||
wrf = weakref.WeakMethod(foo.f) |
||||
|
||||
# print(f"{gc.get_referents(foo)=}") |
||||
# print(f"{gc.get_referrers(foo)=}") |
||||
# print(f"{gc.get_referents(v1)=}") |
||||
# print(f"{gc.get_referrers(v1)=}") |
||||
# print(f"{gc.get_count()=}") |
||||
_ref(foo) |
||||
|
||||
print(f"{foo.a=} - {foo.b=} - {foo.f()=} - {bar()=}") |
||||
print(f"{wrfoo()=} {wrbar()=} {wrf()=}") |
||||
del foo |
||||
print(f"{gc.collect()=}") |
||||
print(f"{bar()}") |
||||
# print(f"{gc.get_referents(v1)=}") |
||||
# print(f"{gc.get_referrers(v1)=}") |
||||
print(f"{wrfoo()=} {wrbar()=} {wrf()=}") |
||||
bar = None |
||||
print(f"{wrfoo()=} {wrbar()=} {wrf()=}") |
||||
time.sleep(4) |
||||
print(f"{wrfoo()=} {wrbar()=} {wrf()=}") |
||||
print(f"{gc.collect()=}") |
||||
print(f"{wrfoo()=} {wrbar()=} {wrf()=}") |
||||
|
||||
print(f"{gc.garbage=}") |
||||
print(f"End {gc.get_count()=}") |
||||
@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
import sys, os |
||||
import gc, weakref, time |
||||
|
||||
sys.path.append(os.path.join(sys.path[0],'../..')) |
||||
sys.path.append(os.path.join(sys.path[0],'.')) |
||||
import TermTk as ttk |
||||
|
||||
def pobjs(): |
||||
for i,o in enumerate(gc.get_objects()[-100:]): |
||||
ss = str(o) |
||||
if "Foo" in ss: |
||||
print(f" * {i} - {ss}") |
||||
|
||||
print(f"\nStart {gc.isenabled()=}") |
||||
|
||||
def _gccb(phase,info): |
||||
print(f" ---> {gc.garbage=}") |
||||
print(f" ---> {phase=} {info=}") |
||||
# gc.callbacks.append(_gccb) |
||||
|
||||
def _ref(o): |
||||
print(f"\n### -> Referents - {o}") |
||||
for i,r in enumerate(gc.get_referents(o)): |
||||
print(f" - {i} ) {r}") |
||||
print(f"\n### -> Referrers - {o}") |
||||
for i,r in enumerate(gc.get_referrers(o)): |
||||
print(f" - {i} ) {r}") |
||||
for ii,rr in enumerate(gc.get_referrers(r)): |
||||
print(f" | {ii} ) {rr}") |
||||
print("") |
||||
print("") |
||||
|
||||
print("\n############# Phase 1 ##################") |
||||
# wid = ttk.TTkWidget() |
||||
wid = ttk.TTkButton() |
||||
# wid = ttk.TTkLabel() |
||||
# wid = ttk.TTkGraph() |
||||
# wid = ttk.TTkSpacer() |
||||
# wid = ttk.TTkSplitter() |
||||
# wid = ttk.TTkCanvas() |
||||
# sizef = wid.size |
||||
sizef = [] |
||||
|
||||
ttk.TTkHelper._updateWidget = set() |
||||
ttk.TTkHelper._updateBuffer = set() |
||||
|
||||
wrwid = weakref.ref(wid) |
||||
# wrsizef = weakref.ref(sizef) |
||||
wrsizef = wrwid |
||||
# wrsizef2 = weakref.WeakMethod(wid.size) |
||||
wrsizef2 = wrwid |
||||
|
||||
_ref(wid) |
||||
|
||||
print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") |
||||
del wid |
||||
print(f"{gc.collect()=}") |
||||
# print(f"{sizef()}") |
||||
print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") |
||||
sizef = None |
||||
print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") |
||||
# time.sleep(4) |
||||
# print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") |
||||
print(f"{gc.collect()=}") |
||||
print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") |
||||
|
||||
print(f"{gc.garbage=}") |
||||
print(f"End {gc.get_count()=}") |
||||
@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
import sys, os |
||||
import gc, weakref, time |
||||
|
||||
sys.path.append(os.path.join(sys.path[0],'../..')) |
||||
sys.path.append(os.path.join(sys.path[0],'.')) |
||||
import TermTk as ttk |
||||
|
||||
def pobjs(): |
||||
for i,o in enumerate(gc.get_objects()[-100:]): |
||||
ss = str(o) |
||||
if "Foo" in ss: |
||||
print(f" * {i} - {ss}") |
||||
|
||||
print(f"\nStart {gc.isenabled()=}") |
||||
|
||||
def _gccb(phase,info): |
||||
print(f" ---> {gc.garbage=}") |
||||
print(f" ---> {phase=} {info=}") |
||||
# gc.callbacks.append(_gccb) |
||||
|
||||
def _ref(o): |
||||
print(f"\n### -> Referents - {o}") |
||||
for i,r in enumerate(gc.get_referents(o)): |
||||
print(f" - {i} ) {r}") |
||||
print(f"\n### -> Referrers - {o}") |
||||
for i,r in enumerate(gc.get_referrers(o)): |
||||
print(f" - {i} ) {r}") |
||||
for ii,rr in enumerate(gc.get_referrers(r)): |
||||
print(f" | {ii} ) {rr}") |
||||
print("") |
||||
print("") |
||||
|
||||
|
||||
class TestWid(ttk.TTkWidget): |
||||
__slots__ = ('_a','_b') |
||||
def __init__(self, *args, **kwargs): |
||||
self.setDefaultSize(kwargs, 10, 10) |
||||
super().__init__(*args, **kwargs) |
||||
self._b = ttk.pyTTkSignal(bool) |
||||
self.setFocusPolicy(ttk.TTkK.ClickFocus + ttk.TTkK.TabFocus) |
||||
|
||||
def mousePressEvent(self, evt): |
||||
# TTkLog.debug(f"{self._text} Test Mouse {evt}") |
||||
self.update() |
||||
return True |
||||
|
||||
def paintEvent(self, canvas): |
||||
canvas.fill(pos=(0,0), size=(2,2)) |
||||
|
||||
print("\n############# Phase 1 ##################") |
||||
# wid = ttk.TTkWidget() |
||||
wid = ttk.TTkButton() |
||||
# wid = ttk.TTkGraph() |
||||
# wid = ttk.TTkSpacer() |
||||
# wid = ttk.TTkSplitter() |
||||
# wid = TestWid() |
||||
# sizef = wid.size |
||||
sizef = [] |
||||
|
||||
wrwid = weakref.ref(wid) |
||||
# wrsizef = weakref.ref(sizef) |
||||
wrsizef = wrwid |
||||
# wrsizef2 = weakref.WeakMethod(wid.size) |
||||
wrsizef2 = wrwid |
||||
|
||||
_ref(wid) |
||||
|
||||
print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") |
||||
del wid |
||||
print(f"{gc.collect()=}") |
||||
# print(f"{sizef()}") |
||||
print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") |
||||
sizef = None |
||||
print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") |
||||
# time.sleep(4) |
||||
# print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") |
||||
print(f"{gc.collect()=}") |
||||
print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") |
||||
|
||||
print(f"{gc.garbage=}") |
||||
print(f"End {gc.get_count()=}") |
||||
@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
import sys, os |
||||
import gc, weakref, time |
||||
|
||||
sys.path.append(os.path.join(sys.path[0],'../..')) |
||||
sys.path.append(os.path.join(sys.path[0],'.')) |
||||
import TermTk as ttk |
||||
|
||||
def pobjs(): |
||||
for i,o in enumerate(gc.get_objects()[-100:]): |
||||
ss = str(o) |
||||
if "Foo" in ss: |
||||
print(f" * {i} - {ss}") |
||||
|
||||
print(f"\nStart {gc.isenabled()=}") |
||||
|
||||
def _gccb(phase,info): |
||||
print(f" ---> {gc.garbage=}") |
||||
print(f" ---> {phase=} {info=}") |
||||
# gc.callbacks.append(_gccb) |
||||
|
||||
def _ref(o): |
||||
print(f"\n### -> Referents - {o}") |
||||
for i,r in enumerate(gc.get_referents(o)): |
||||
print(f" - {i} ) {r}") |
||||
print(f"\n### -> Referrers - {o}") |
||||
for i,r in enumerate(gc.get_referrers(o)): |
||||
print(f" - {i} ) {r}") |
||||
for ii,rr in enumerate(gc.get_referrers(r)): |
||||
print(f" | {ii} ) {rr}") |
||||
print("") |
||||
print("") |
||||
|
||||
print("\n############# Phase 1 ##################") |
||||
|
||||
root = ttk.TTkWidget() |
||||
# wid = ttk.TTkWidget() |
||||
wid = ttk.TTkButton() |
||||
# wid = ttk.TTkLabel() |
||||
# wid = ttk.TTkGraph() |
||||
# wid = ttk.TTkSpacer() |
||||
# wid = ttk.TTkSplitter() |
||||
# sizef = wid.size |
||||
sizef = [] |
||||
|
||||
root.closed.connect(wid.close) |
||||
|
||||
ttk.TTkHelper._updateWidget = set() |
||||
ttk.TTkHelper._updateBuffer = set() |
||||
|
||||
wrwid = weakref.ref(wid) |
||||
# wrsizef = weakref.ref(sizef) |
||||
wrsizef = wrwid |
||||
# wrsizef2 = weakref.WeakMethod(wid.size) |
||||
wrsizef2 = wrwid |
||||
|
||||
_ref(wid) |
||||
|
||||
print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") |
||||
del wid |
||||
print(f"{gc.collect()=}") |
||||
# print(f"{sizef()}") |
||||
print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") |
||||
sizef = None |
||||
print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") |
||||
# time.sleep(4) |
||||
# print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") |
||||
print(f"{gc.collect()=}") |
||||
print(f"{wrwid()=} {wrsizef()=} {wrsizef2()=}") |
||||
|
||||
print(f"{gc.garbage=}") |
||||
print(f"End {gc.get_count()=}") |
||||
@ -0,0 +1,44 @@
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
import TermTk as ttk |
||||
import ttkDesigner.app.superobj as so |
||||
from .superobj import SuperObject |
||||
|
||||
|
||||
class SuperWidgetAbstractScrollArea(so.SuperWidgetContainer): |
||||
@staticmethod |
||||
def _swFromWidget(wid, swClass, *args, **kwargs): |
||||
return swClass(wid=wid, *args, **kwargs) |
||||
|
||||
def getSuperProperties(self): |
||||
additions, exceptions, exclude = super().getSuperProperties() |
||||
exclude += ['Layout','Padding'] |
||||
return additions, exceptions, exclude |
||||
|
||||
def dumpDict(self): |
||||
wid = self._wid |
||||
ret = { |
||||
'class' : wid.__class__.__name__, |
||||
'params' : SuperObject.dumpParams(wid,exclude=['Layout','Padding']), |
||||
} |
||||
return ret |
||||
@ -0,0 +1,29 @@
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
import TermTk as ttk |
||||
import ttkDesigner.app.superobj as so |
||||
from .superobj import SuperObject |
||||
|
||||
|
||||
class SuperWidgetList(so.SuperWidgetAbstractScrollArea): |
||||
pass |
||||
Loading…
Reference in new issue