liveConsole 1.7.2__tar.gz → 1.7.4__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.
Potentially problematic release.
This version of liveConsole might be problematic. Click here for more details.
- {liveconsole-1.7.2/src/liveConsole.egg-info → liveconsole-1.7.4}/PKG-INFO +1 -1
- {liveconsole-1.7.2 → liveconsole-1.7.4}/pyproject.toml +1 -1
- liveconsole-1.7.4/src/liveConsole/__init__.py +1 -0
- {liveconsole-1.7.2 → liveconsole-1.7.4/src/liveConsole.egg-info}/PKG-INFO +1 -1
- {liveconsole-1.7.2 → liveconsole-1.7.4}/src/liveConsole.egg-info/SOURCES.txt +1 -0
- liveconsole-1.7.4/src/liveConsole.egg-info/top_level.txt +2 -0
- liveconsole-1.7.4/src/pysole/__init__.py +4 -0
- {liveconsole-1.7.2 → liveconsole-1.7.4}/src/pysole/mainConsole.py +24 -20
- {liveconsole-1.7.2 → liveconsole-1.7.4}/src/pysole/pysole.py +63 -35
- {liveconsole-1.7.2 → liveconsole-1.7.4}/src/pysole/settings.json +1 -1
- {liveconsole-1.7.2 → liveconsole-1.7.4}/src/pysole/themes.json +4 -4
- liveconsole-1.7.2/src/liveConsole.egg-info/top_level.txt +0 -1
- liveconsole-1.7.2/src/pysole/__init__.py +0 -1
- {liveconsole-1.7.2 → liveconsole-1.7.4}/LICENSE +0 -0
- {liveconsole-1.7.2 → liveconsole-1.7.4}/MANIFEST.in +0 -0
- {liveconsole-1.7.2 → liveconsole-1.7.4}/README.md +0 -0
- {liveconsole-1.7.2 → liveconsole-1.7.4}/setup.cfg +0 -0
- {liveconsole-1.7.2 → liveconsole-1.7.4}/src/liveConsole.egg-info/dependency_links.txt +0 -0
- {liveconsole-1.7.2 → liveconsole-1.7.4}/src/liveConsole.egg-info/entry_points.txt +0 -0
- {liveconsole-1.7.2 → liveconsole-1.7.4}/src/liveConsole.egg-info/requires.txt +0 -0
- {liveconsole-1.7.2 → liveconsole-1.7.4}/src/pysole/__main__.py +0 -0
- {liveconsole-1.7.2 → liveconsole-1.7.4}/src/pysole/commandHistory.py +0 -0
- {liveconsole-1.7.2 → liveconsole-1.7.4}/src/pysole/helpTab.py +0 -0
- {liveconsole-1.7.2 → liveconsole-1.7.4}/src/pysole/liveConsole.py +0 -0
- {liveconsole-1.7.2 → liveconsole-1.7.4}/src/pysole/styledTextbox.py +0 -0
- {liveconsole-1.7.2 → liveconsole-1.7.4}/src/pysole/suggestionManager.py +0 -0
- {liveconsole-1.7.2 → liveconsole-1.7.4}/src/pysole/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "liveConsole"
|
|
3
|
-
version = "1.7.
|
|
3
|
+
version = "1.7.4"
|
|
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 @@
|
|
|
1
|
+
from pysole import *
|
|
@@ -50,6 +50,10 @@ class InteractiveConsoleText(StyledTextWindow):
|
|
|
50
50
|
self.bind("<Up>", self.onUp)
|
|
51
51
|
self.bind("<Down>", self.onDown)
|
|
52
52
|
|
|
53
|
+
def getPromptPosition(self):
|
|
54
|
+
"""Get the position right after the prompt on current command line."""
|
|
55
|
+
return(f"{self.currentCommandLine}.{self.PROMPT_LENGTH}")
|
|
56
|
+
|
|
53
57
|
def getCurrentLineNumber(self):
|
|
54
58
|
"""Get the line number where current command starts."""
|
|
55
59
|
return(int(self.index("end-1c").split(".")[0]))
|
|
@@ -60,30 +64,35 @@ class InteractiveConsoleText(StyledTextWindow):
|
|
|
60
64
|
def getCommandStartPosition(self):
|
|
61
65
|
"""Get the starting position of the current command."""
|
|
62
66
|
return(f"{self.currentCommandLine}.0")
|
|
67
|
+
|
|
68
|
+
def writeToPrompt(self, text):
|
|
69
|
+
"""Write text to the prompt of the console"""
|
|
70
|
+
if self.isExecuting:
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
if text:
|
|
74
|
+
self.insert("end", text)
|
|
75
|
+
self.mark_set("insert", "end")
|
|
76
|
+
self.see("end")
|
|
77
|
+
self.updateStyling(start=self.getPromptPosition()) #< Ensure styling/lexer applied after programmatic change:
|
|
63
78
|
|
|
64
79
|
def replaceCurrentCommand(self, newCommand):
|
|
65
80
|
"""Replace the current command with new text."""
|
|
66
|
-
if self.isExecuting:
|
|
67
|
-
return
|
|
68
|
-
|
|
69
81
|
start = self.getPromptPosition()
|
|
70
82
|
end = "end-1c"
|
|
71
|
-
|
|
72
83
|
self.delete(start, end)
|
|
73
|
-
|
|
74
|
-
self.insert(start, newCommand)
|
|
75
|
-
self.mark_set("insert", "end")
|
|
76
|
-
self.see("end")
|
|
77
|
-
# Ensure styling/lexer applied after programmatic change:
|
|
78
|
-
self.updateStyling(start=self.getPromptPosition())
|
|
84
|
+
self.writeToPrompt(newCommand)
|
|
79
85
|
|
|
80
|
-
def runCommand(self, command, printCommand=False):
|
|
86
|
+
def runCommand(self, command, printCommand=False, clearPrompt=True):
|
|
81
87
|
"""Insert code into the console prompt and execute it as if Enter was pressed."""
|
|
82
88
|
if self.isExecuting:
|
|
83
89
|
return(False)
|
|
84
90
|
if printCommand:
|
|
85
|
-
|
|
86
|
-
|
|
91
|
+
if clearPrompt:
|
|
92
|
+
self.replaceCurrentCommand(command) #< Replace current command with the new code
|
|
93
|
+
else:
|
|
94
|
+
self.writeToPrompt(command)
|
|
95
|
+
self.onEnter(None, insertWhitespace=False) #< Simulate pressing Enter to run the command
|
|
87
96
|
else:
|
|
88
97
|
self.executeCommandThreaded(command, addPrompt=False)
|
|
89
98
|
|
|
@@ -98,7 +107,7 @@ class InteractiveConsoleText(StyledTextWindow):
|
|
|
98
107
|
return((cursorLine >= self.currentCommandLine and
|
|
99
108
|
(cursorLine > self.currentCommandLine or cursorCol >= self.PROMPT_LENGTH)))
|
|
100
109
|
|
|
101
|
-
def onEnter(self, event):
|
|
110
|
+
def onEnter(self, event, insertWhitespace=True):
|
|
102
111
|
"""Handle Enter key - execute command."""
|
|
103
112
|
self.suggestionManager.hideSuggestions()
|
|
104
113
|
|
|
@@ -119,9 +128,8 @@ class InteractiveConsoleText(StyledTextWindow):
|
|
|
119
128
|
return("break")
|
|
120
129
|
|
|
121
130
|
# Check if statement is incomplete
|
|
122
|
-
if self.isIncompleteStatement(command):
|
|
131
|
+
if self.isIncompleteStatement(command) and insertWhitespace:
|
|
123
132
|
return(self.onShiftEnter(event))
|
|
124
|
-
|
|
125
133
|
# Execute the command
|
|
126
134
|
self.history.add(command)
|
|
127
135
|
self.mark_set("insert", "end")
|
|
@@ -351,10 +359,6 @@ class InteractiveConsoleText(StyledTextWindow):
|
|
|
351
359
|
"""Insert a newline at the end."""
|
|
352
360
|
self.writeOutput("")
|
|
353
361
|
|
|
354
|
-
def getPromptPosition(self):
|
|
355
|
-
"""Get the position right after the prompt on current command line."""
|
|
356
|
-
return(f"{self.currentCommandLine}.{self.PROMPT_LENGTH}")
|
|
357
|
-
|
|
358
362
|
def getCurrentCommand(self):
|
|
359
363
|
"""Extract the current command text (without prompt)."""
|
|
360
364
|
start = self.getPromptPosition()
|
|
@@ -86,7 +86,6 @@ class InteractiveConsole(ctk.CTk):
|
|
|
86
86
|
|
|
87
87
|
self.runRemainingCode = runRemainingCode
|
|
88
88
|
self.printStartupCode = printStartupCode
|
|
89
|
-
self.leadingWhitespaceLen = 0
|
|
90
89
|
self.removeWaterMark = removeWaterMark
|
|
91
90
|
self.startupCode = ()
|
|
92
91
|
if runRemainingCode:
|
|
@@ -99,8 +98,9 @@ class InteractiveConsole(ctk.CTk):
|
|
|
99
98
|
|
|
100
99
|
startLineIndex = callerFrame.f_lineno
|
|
101
100
|
startLine = lines[startLineIndex - 1]
|
|
102
|
-
|
|
101
|
+
leadingWhitespaceLen = len(startLine) - len(startLine.lstrip())
|
|
103
102
|
self.startupCode = lines[startLineIndex:]
|
|
103
|
+
self.startupCode = [line.rstrip()[leadingWhitespaceLen:] for line in self.startupCode]
|
|
104
104
|
|
|
105
105
|
def _createMenu(self):
|
|
106
106
|
"""Create a menu bar using CTkOptionMenu."""
|
|
@@ -260,42 +260,70 @@ class InteractiveConsole(ctk.CTk):
|
|
|
260
260
|
sys.stdout = sys.__stdout__
|
|
261
261
|
sys.stderr = sys.__stderr__
|
|
262
262
|
self.destroy()
|
|
263
|
+
|
|
264
|
+
def _printWaterMark(self):
|
|
265
|
+
m = (
|
|
266
|
+
"Welcome to Pysole, if you find me useful, please star me on GitHub:\n"
|
|
267
|
+
"https://github.com/TzurSoffer/Pysole"
|
|
268
|
+
)
|
|
269
|
+
stdPrint(m)
|
|
270
|
+
self.console.newline()
|
|
271
|
+
self.console.writeOutput(m, "instruction")
|
|
272
|
+
time.sleep(0.1)
|
|
273
|
+
if self.runRemainingCode:
|
|
274
|
+
if self.printStartupCode:
|
|
275
|
+
self.console.addPrompt()
|
|
276
|
+
else:
|
|
277
|
+
self.console.newline()
|
|
278
|
+
else:
|
|
279
|
+
self.console.addPrompt()
|
|
280
|
+
|
|
281
|
+
def _splitCodeIntoChunks(self):
|
|
282
|
+
codeChunks = []
|
|
283
|
+
currentChunk = []
|
|
284
|
+
|
|
285
|
+
for line in self.startupCode:
|
|
286
|
+
strippedLine = line.lstrip()
|
|
287
|
+
indentLevel = len(line) - len(strippedLine)
|
|
288
|
+
|
|
289
|
+
if not strippedLine: #< Blank line, keep it in current chunk
|
|
290
|
+
currentChunk.append(line)
|
|
291
|
+
continue
|
|
292
|
+
|
|
293
|
+
if indentLevel != 0:
|
|
294
|
+
currentChunk.append(line)
|
|
295
|
+
else:
|
|
296
|
+
codeChunks.append(currentChunk)
|
|
297
|
+
currentChunk = [line]
|
|
298
|
+
|
|
299
|
+
if currentChunk:
|
|
300
|
+
codeChunks.append(currentChunk)
|
|
301
|
+
|
|
302
|
+
return(["\n".join(chunk).strip() for chunk in codeChunks if any(line.strip() for line in chunk)])
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def _runStartup(self):
|
|
306
|
+
if self.removeWaterMark == False:
|
|
307
|
+
self._printWaterMark()
|
|
308
|
+
|
|
309
|
+
if self.runRemainingCode == False:
|
|
310
|
+
return
|
|
311
|
+
|
|
312
|
+
if self.printStartupCode == False:
|
|
313
|
+
self.console.newline()
|
|
314
|
+
code = "\n".join(self.startupCode)
|
|
315
|
+
self.console.executeCommandThreaded(code, addPrompt=True)
|
|
316
|
+
return
|
|
317
|
+
|
|
318
|
+
chunks = self._splitCodeIntoChunks()
|
|
319
|
+
for chunk in chunks:
|
|
320
|
+
while self.console.isExecuting:
|
|
321
|
+
time.sleep(0.01)
|
|
322
|
+
self.console.runCommand(chunk, printCommand=True, clearPrompt=True)
|
|
263
323
|
|
|
264
324
|
def probe(self, *args, **kwargs):
|
|
265
325
|
"""Start the console main loop."""
|
|
266
|
-
|
|
267
|
-
if not self.removeWaterMark:
|
|
268
|
-
m = (
|
|
269
|
-
"Welcome to Pysole, if you find me useful, please star me on GitHub:\n"
|
|
270
|
-
"https://github.com/TzurSoffer/Pysole"
|
|
271
|
-
)
|
|
272
|
-
stdPrint(m)
|
|
273
|
-
self.console.newline()
|
|
274
|
-
self.console.writeOutput(m, "instruction")
|
|
275
|
-
time.sleep(0.1)
|
|
276
|
-
if self.runRemainingCode:
|
|
277
|
-
if self.printStartupCode:
|
|
278
|
-
self.console.addPrompt()
|
|
279
|
-
else:
|
|
280
|
-
self.console.newline()
|
|
281
|
-
else:
|
|
282
|
-
self.console.addPrompt()
|
|
283
|
-
elif self.runRemainingCode == True and self.printStartupCode == False:
|
|
284
|
-
self.console.newline()
|
|
285
|
-
|
|
286
|
-
for line in self.startupCode:
|
|
287
|
-
line = line.rstrip()[self.leadingWhitespaceLen:]
|
|
288
|
-
while self.console.isExecuting:
|
|
289
|
-
time.sleep(0.01)
|
|
290
|
-
if self.printStartupCode:
|
|
291
|
-
self.console.runCommand(line, printCommand=True)
|
|
292
|
-
else:
|
|
293
|
-
self.console.runCommand(line, printCommand=False)
|
|
294
|
-
|
|
295
|
-
if self.runRemainingCode == True and self.printStartupCode == False:
|
|
296
|
-
self.console.resetCurrentLineNumber()
|
|
297
|
-
self.console.addPrompt()
|
|
298
|
-
threading.Thread(target=runStartup).start()
|
|
326
|
+
self.after(0, threading.Thread(target=self._runStartup).start)
|
|
299
327
|
self.mainloop(*args, **kwargs)
|
|
300
328
|
|
|
301
329
|
def probe(userGlobals=None, userLocals=None, callerFrame=None,
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"OUTPUT": "#ffffff",
|
|
12
12
|
"ERROR": "#ff0000",
|
|
13
13
|
"RESULT": "#66ccff",
|
|
14
|
-
"INSTRUCTION": "#
|
|
14
|
+
"INSTRUCTION": "#ffccdd",
|
|
15
15
|
"SUGGESTION_BOX_BG": "#2d2d2d",
|
|
16
16
|
"SUGGESTION_BOX_SELECTION_BG": "#0066cc",
|
|
17
17
|
"FONT": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"OUTPUT": "#000000",
|
|
32
32
|
"ERROR": "#ff0000",
|
|
33
33
|
"RESULT": "#0066cc",
|
|
34
|
-
"INSTRUCTION": "#
|
|
34
|
+
"INSTRUCTION": "#ffccdd",
|
|
35
35
|
"SUGGESTION_BOX_BG": "#f0f0f0",
|
|
36
36
|
"SUGGESTION_BOX_SELECTION_BG": "#cce6ff",
|
|
37
37
|
"FONT": {
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"OUTPUT": "#586e75",
|
|
52
52
|
"ERROR": "#dc322f",
|
|
53
53
|
"RESULT": "#2aa198",
|
|
54
|
-
"INSTRUCTION": "#
|
|
54
|
+
"INSTRUCTION": "#ffccdd",
|
|
55
55
|
"SUGGESTION_BOX_BG": "#eee8d5",
|
|
56
56
|
"SUGGESTION_BOX_SELECTION_BG": "#b58900",
|
|
57
57
|
"FONT": {
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"OUTPUT": "#f8f8f2",
|
|
72
72
|
"ERROR": "#ff5555",
|
|
73
73
|
"RESULT": "#8be9fd",
|
|
74
|
-
"INSTRUCTION": "#
|
|
74
|
+
"INSTRUCTION": "#ffccdd",
|
|
75
75
|
"SUGGESTION_BOX_BG": "#44475a",
|
|
76
76
|
"SUGGESTION_BOX_SELECTION_BG": "#6272a4",
|
|
77
77
|
"FONT": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
pysole
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from .pysole import probe, _standalone, InteractiveConsole
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|