liveConsole 1.3.2__tar.gz → 1.4.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {liveconsole-1.3.2/src/liveConsole.egg-info → liveconsole-1.4.1}/PKG-INFO +15 -1
- {liveconsole-1.3.2 → liveconsole-1.4.1}/README.md +14 -0
- {liveconsole-1.3.2 → liveconsole-1.4.1}/pyproject.toml +1 -1
- liveconsole-1.4.1/src/commandHistory.py +34 -0
- liveconsole-1.4.1/src/helpTab.py +64 -0
- {liveconsole-1.3.2 → liveconsole-1.4.1/src/liveConsole.egg-info}/PKG-INFO +15 -1
- {liveconsole-1.3.2 → liveconsole-1.4.1}/src/liveConsole.egg-info/SOURCES.txt +5 -0
- liveconsole-1.4.1/src/liveConsole.egg-info/top_level.txt +7 -0
- liveconsole-1.4.1/src/liveConsole.py +126 -0
- liveconsole-1.4.1/src/mainConsole.py +354 -0
- liveconsole-1.4.1/src/styledTextbox.py +51 -0
- liveconsole-1.4.1/src/suggestionManager.py +165 -0
- liveconsole-1.3.2/src/liveConsole.egg-info/top_level.txt +0 -2
- liveconsole-1.3.2/src/liveConsole.py +0 -656
- {liveconsole-1.3.2 → liveconsole-1.4.1}/LICENSE +0 -0
- {liveconsole-1.3.2 → liveconsole-1.4.1}/setup.cfg +0 -0
- {liveconsole-1.3.2 → liveconsole-1.4.1}/src/__init__.py +0 -0
- {liveconsole-1.3.2 → liveconsole-1.4.1}/src/liveConsole.egg-info/dependency_links.txt +0 -0
- {liveconsole-1.3.2 → liveconsole-1.4.1}/src/liveConsole.egg-info/requires.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: liveConsole
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.4.1
|
4
4
|
Summary: An IDLE-like debugger to allow for real-time command injection for debugging and testing python code
|
5
5
|
Author-email: Tzur Soffer <tzur.soffer@gmail.com>
|
6
6
|
License: MIT
|
@@ -29,6 +29,9 @@ A fully-featured, **live Python console GUI** built with **CustomTkinter** and *
|
|
29
29
|
|
30
30
|
* Clickable history of previous commands
|
31
31
|
|
32
|
+
* **Integrated Help Panel** for quick access to Python object documentation
|
33
|
+
|
34
|
+
|
32
35
|
## Installation
|
33
36
|
|
34
37
|
`pip install liveConsole`
|
@@ -77,6 +80,17 @@ A fully-featured, **live Python console GUI** built with **CustomTkinter** and *
|
|
77
80
|
* Click to copy them back to the prompt for editing or re-execution.
|
78
81
|
|
79
82
|
|
83
|
+
### Help Panel
|
84
|
+
|
85
|
+
* A resizable right-hand panel that displays Python documentation (help()) for any object.
|
86
|
+
|
87
|
+
* Opens when clicking ctrl+click on a function/method and can be closed with the "X" button.
|
88
|
+
|
89
|
+
* Scrollable and syntax-styled.
|
90
|
+
|
91
|
+
* Perfect for quick reference without leaving the console.
|
92
|
+
|
93
|
+
|
80
94
|
### Easy Integration
|
81
95
|
|
82
96
|
* Automatically grabs **caller frame globals and locals** if not provided.
|
@@ -16,6 +16,9 @@ A fully-featured, **live Python console GUI** built with **CustomTkinter** and *
|
|
16
16
|
|
17
17
|
* Clickable history of previous commands
|
18
18
|
|
19
|
+
* **Integrated Help Panel** for quick access to Python object documentation
|
20
|
+
|
21
|
+
|
19
22
|
## Installation
|
20
23
|
|
21
24
|
`pip install liveConsole`
|
@@ -64,6 +67,17 @@ A fully-featured, **live Python console GUI** built with **CustomTkinter** and *
|
|
64
67
|
* Click to copy them back to the prompt for editing or re-execution.
|
65
68
|
|
66
69
|
|
70
|
+
### Help Panel
|
71
|
+
|
72
|
+
* A resizable right-hand panel that displays Python documentation (help()) for any object.
|
73
|
+
|
74
|
+
* Opens when clicking ctrl+click on a function/method and can be closed with the "X" button.
|
75
|
+
|
76
|
+
* Scrollable and syntax-styled.
|
77
|
+
|
78
|
+
* Perfect for quick reference without leaving the console.
|
79
|
+
|
80
|
+
|
67
81
|
### Easy Integration
|
68
82
|
|
69
83
|
* Automatically grabs **caller frame globals and locals** if not provided.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "liveConsole"
|
3
|
-
version = "1.
|
3
|
+
version = "1.4.1"
|
4
4
|
description = "An IDLE-like debugger to allow for real-time command injection for debugging and testing python code"
|
5
5
|
authors = [{ name="Tzur Soffer", email="tzur.soffer@gmail.com" }]
|
6
6
|
license = {text = "MIT"}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class CommandHistory:
|
2
|
+
"""Manages command history and navigation."""
|
3
|
+
|
4
|
+
def __init__(self):
|
5
|
+
self.history = []
|
6
|
+
self.index = -1
|
7
|
+
self.tempCommand = ""
|
8
|
+
|
9
|
+
def add(self, command):
|
10
|
+
"""Add a command to history."""
|
11
|
+
if command.strip():
|
12
|
+
self.history.append(command)
|
13
|
+
self.index = len(self.history)
|
14
|
+
|
15
|
+
def navigateUp(self):
|
16
|
+
"""Get previous command from history."""
|
17
|
+
if self.index > 0:
|
18
|
+
self.index -= 1
|
19
|
+
return(self.history[self.index])
|
20
|
+
return(None)
|
21
|
+
|
22
|
+
def navigateDown(self):
|
23
|
+
"""Get next command from history."""
|
24
|
+
if self.index < len(self.history) - 1:
|
25
|
+
self.index += 1
|
26
|
+
return(self.history[self.index])
|
27
|
+
elif self.index == len(self.history) - 1:
|
28
|
+
self.index = len(self.history)
|
29
|
+
return(self.tempCommand)
|
30
|
+
return(None)
|
31
|
+
|
32
|
+
def setTemp(self, command):
|
33
|
+
"""Store temporary command while navigating history."""
|
34
|
+
self.tempCommand = command
|
@@ -0,0 +1,64 @@
|
|
1
|
+
import sys
|
2
|
+
import io
|
3
|
+
from pygments.styles import get_style_by_name
|
4
|
+
import customtkinter as ctk
|
5
|
+
from styledTextbox import StyledTextWindow
|
6
|
+
|
7
|
+
class HelpTab(ctk.CTkFrame):
|
8
|
+
"""A right-hand help tab with closable and updateable text content."""
|
9
|
+
|
10
|
+
def __init__(self, parent, width=500, title="Help", **kwargs):
|
11
|
+
super().__init__(parent, width=width, **kwargs)
|
12
|
+
self.parent = parent
|
13
|
+
self.visible = False
|
14
|
+
|
15
|
+
# Ensure initial width is respected
|
16
|
+
self.pack_propagate(False)
|
17
|
+
|
18
|
+
# Header frame with title and close button
|
19
|
+
headerFrame = ctk.CTkFrame(self, height=30)
|
20
|
+
headerFrame.pack(fill="x")
|
21
|
+
self.style = get_style_by_name("monokai")
|
22
|
+
|
23
|
+
self.titleLabel = ctk.CTkLabel(headerFrame, text=title, font=("Consolas", 12, "bold"))
|
24
|
+
self.titleLabel.pack(side="left", padx=5)
|
25
|
+
|
26
|
+
self.closeButton = ctk.CTkButton(headerFrame, text="X", height=20, command=self.close)
|
27
|
+
self.closeButton.pack(side="right", padx=5)
|
28
|
+
|
29
|
+
# Scrollable text area
|
30
|
+
self.textBox = StyledTextWindow(self, wrap="word", font=("Consolas", 11), bg="#2e2e2e")
|
31
|
+
self.textBox.pack(fill="both", expand=True, padx=5, pady=5)
|
32
|
+
self.textBox.configure(state="disabled") # read-only
|
33
|
+
|
34
|
+
def close(self):
|
35
|
+
"""Hide the help tab."""
|
36
|
+
if self.visible:
|
37
|
+
self.pack_forget()
|
38
|
+
self.visible = False
|
39
|
+
|
40
|
+
def open(self):
|
41
|
+
"""Show the help tab."""
|
42
|
+
if not self.visible:
|
43
|
+
self.pack(side="left", fill="y")
|
44
|
+
# self.configure(width=self.minWidth)
|
45
|
+
self.visible = True
|
46
|
+
|
47
|
+
def _getHelp(self, obj):
|
48
|
+
"""Return the output of help(obj) as a string."""
|
49
|
+
old_stdout = sys.stdout # save current stdout
|
50
|
+
sys.stdout = buffer = io.StringIO() # redirect stdout to a string buffer
|
51
|
+
try:
|
52
|
+
help(obj)
|
53
|
+
return(buffer.getvalue())
|
54
|
+
finally:
|
55
|
+
sys.stdout = old_stdout # restore original stdout
|
56
|
+
|
57
|
+
def updateHelp(self, obj):
|
58
|
+
"""Update the help tab content."""
|
59
|
+
|
60
|
+
self.textBox.configure(state="normal")
|
61
|
+
self.textBox.delete("1.0", "end")
|
62
|
+
self.textBox.insert("1.0", self._getHelp(obj))
|
63
|
+
self.textBox.updateStyling()
|
64
|
+
self.textBox.configure(state="disabled")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: liveConsole
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.4.1
|
4
4
|
Summary: An IDLE-like debugger to allow for real-time command injection for debugging and testing python code
|
5
5
|
Author-email: Tzur Soffer <tzur.soffer@gmail.com>
|
6
6
|
License: MIT
|
@@ -29,6 +29,9 @@ A fully-featured, **live Python console GUI** built with **CustomTkinter** and *
|
|
29
29
|
|
30
30
|
* Clickable history of previous commands
|
31
31
|
|
32
|
+
* **Integrated Help Panel** for quick access to Python object documentation
|
33
|
+
|
34
|
+
|
32
35
|
## Installation
|
33
36
|
|
34
37
|
`pip install liveConsole`
|
@@ -77,6 +80,17 @@ A fully-featured, **live Python console GUI** built with **CustomTkinter** and *
|
|
77
80
|
* Click to copy them back to the prompt for editing or re-execution.
|
78
81
|
|
79
82
|
|
83
|
+
### Help Panel
|
84
|
+
|
85
|
+
* A resizable right-hand panel that displays Python documentation (help()) for any object.
|
86
|
+
|
87
|
+
* Opens when clicking ctrl+click on a function/method and can be closed with the "X" button.
|
88
|
+
|
89
|
+
* Scrollable and syntax-styled.
|
90
|
+
|
91
|
+
* Perfect for quick reference without leaving the console.
|
92
|
+
|
93
|
+
|
80
94
|
### Easy Integration
|
81
95
|
|
82
96
|
* Automatically grabs **caller frame globals and locals** if not provided.
|
@@ -2,7 +2,12 @@ LICENSE
|
|
2
2
|
README.md
|
3
3
|
pyproject.toml
|
4
4
|
src/__init__.py
|
5
|
+
src/commandHistory.py
|
6
|
+
src/helpTab.py
|
5
7
|
src/liveConsole.py
|
8
|
+
src/mainConsole.py
|
9
|
+
src/styledTextbox.py
|
10
|
+
src/suggestionManager.py
|
6
11
|
src/liveConsole.egg-info/PKG-INFO
|
7
12
|
src/liveConsole.egg-info/SOURCES.txt
|
8
13
|
src/liveConsole.egg-info/dependency_links.txt
|
@@ -0,0 +1,126 @@
|
|
1
|
+
import customtkinter as ctk
|
2
|
+
import inspect
|
3
|
+
import sys
|
4
|
+
import io
|
5
|
+
|
6
|
+
from helpTab import HelpTab
|
7
|
+
from mainConsole import InteractiveConsoleText
|
8
|
+
|
9
|
+
|
10
|
+
class StdoutRedirect(io.StringIO):
|
11
|
+
"""Redirects stdout/stderr to a callback function."""
|
12
|
+
|
13
|
+
def __init__(self, writeCallback):
|
14
|
+
super().__init__()
|
15
|
+
self.writeCallback = writeCallback
|
16
|
+
|
17
|
+
def write(self, s):
|
18
|
+
if s.strip():
|
19
|
+
self.writeCallback(s, "output")
|
20
|
+
|
21
|
+
def flush(self):
|
22
|
+
pass
|
23
|
+
|
24
|
+
class StdinRedirect(io.StringIO):
|
25
|
+
"""Redirects stdin to capture input() from the console."""
|
26
|
+
def __init__(self, readCallback):
|
27
|
+
super().__init__()
|
28
|
+
self.readCallback = readCallback
|
29
|
+
|
30
|
+
def readline(self, *args, **kwargs):
|
31
|
+
return(self.readCallback())
|
32
|
+
|
33
|
+
|
34
|
+
class InteractiveConsole(ctk.CTk):
|
35
|
+
"""Main console window application."""
|
36
|
+
|
37
|
+
def __init__(self, userGlobals=None, userLocals=None):
|
38
|
+
super().__init__()
|
39
|
+
|
40
|
+
# Window setup
|
41
|
+
self.title("Live Interactive Console")
|
42
|
+
self.geometry("900x600")
|
43
|
+
|
44
|
+
ctk.set_appearance_mode("dark")
|
45
|
+
ctk.set_default_color_theme("blue")
|
46
|
+
|
47
|
+
# Get namespace from caller if not provided
|
48
|
+
if userGlobals is None or userLocals is None:
|
49
|
+
callerFrame = inspect.currentframe().f_back
|
50
|
+
if userGlobals is None:
|
51
|
+
userGlobals = callerFrame.f_globals
|
52
|
+
if userLocals is None:
|
53
|
+
userLocals = callerFrame.f_locals
|
54
|
+
|
55
|
+
self.userGlobals = userGlobals
|
56
|
+
self.userLocals = userLocals
|
57
|
+
|
58
|
+
# Create UI
|
59
|
+
self._createUi()
|
60
|
+
|
61
|
+
# Redirect stdout/stderr
|
62
|
+
self._setupOutputRedirect()
|
63
|
+
self._setupInputRedirect()
|
64
|
+
|
65
|
+
def _createUi(self):
|
66
|
+
"""Create UI with console and help tab."""
|
67
|
+
frame = ctk.CTkFrame(self)
|
68
|
+
frame.pack(padx=10, pady=10, fill="both", expand=True)
|
69
|
+
|
70
|
+
# Horizontal frame
|
71
|
+
self.horizFrame = ctk.CTkFrame(frame)
|
72
|
+
self.horizFrame.pack(fill="both", expand=True)
|
73
|
+
|
74
|
+
# Right: Help Tab
|
75
|
+
self.helpTab = HelpTab(self.horizFrame, width=500)
|
76
|
+
|
77
|
+
# Left: Console
|
78
|
+
self.consoleFrame = ctk.CTkFrame(self.horizFrame, width=600)
|
79
|
+
self.consoleFrame.pack(side="left", fill="both", expand=True)
|
80
|
+
self.consoleFrame.pack_propagate(False) # prevent shrinking to fit contents
|
81
|
+
|
82
|
+
self.console = InteractiveConsoleText(
|
83
|
+
self.consoleFrame,
|
84
|
+
self.helpTab,
|
85
|
+
userGlobals=self.userGlobals,
|
86
|
+
userLocals=self.userLocals,
|
87
|
+
wrap="word",
|
88
|
+
bg="#1e1e1e",
|
89
|
+
fg="white",
|
90
|
+
insertbackground="white",
|
91
|
+
font=("Consolas", 12)
|
92
|
+
)
|
93
|
+
self.console.pack(fill="both", expand=True, padx=5, pady=5)
|
94
|
+
self.console.master = self
|
95
|
+
|
96
|
+
|
97
|
+
def _setupOutputRedirect(self):
|
98
|
+
"""Setup stdout/stderr redirection to console."""
|
99
|
+
sys.stdout = StdoutRedirect(self.console.writeOutput)
|
100
|
+
sys.stderr = StdoutRedirect(
|
101
|
+
lambda text, tag: self.console.writeOutput(text, "error")
|
102
|
+
)
|
103
|
+
|
104
|
+
def _setupInputRedirect(self):
|
105
|
+
"""Setup stdin redirection to console."""
|
106
|
+
sys.stdin = StdinRedirect(self.console.readInput)
|
107
|
+
|
108
|
+
def probe(self, *args, **kwargs):
|
109
|
+
"""Start the console main loop."""
|
110
|
+
self.mainloop(*args, **kwargs)
|
111
|
+
|
112
|
+
|
113
|
+
# Example usage
|
114
|
+
if __name__ == "__main__":
|
115
|
+
# Example variables and functions for testing
|
116
|
+
foo = 42
|
117
|
+
|
118
|
+
def greet(name):
|
119
|
+
print(f"Hello {name}!")
|
120
|
+
return(f"Greeted {name}")
|
121
|
+
|
122
|
+
# Create the list for testing autocomplete
|
123
|
+
exampleList = [1, 2, 3, 4, 5]
|
124
|
+
|
125
|
+
# Start the console
|
126
|
+
InteractiveConsole().probe()
|