liveConsole 1.2.0__tar.gz → 1.3.0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: liveConsole
3
- Version: 1.2.0
3
+ Version: 1.3.0
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "liveConsole"
3
- version = "1.2.0"
3
+ version = "1.3.0"
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"}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: liveConsole
3
- Version: 1.2.0
3
+ Version: 1.3.0
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
@@ -30,7 +30,9 @@ class StdoutRedirect(io.StringIO):
30
30
  class CodeSuggestionManager:
31
31
  """Manages code suggestions and autocomplete functionality."""
32
32
 
33
- def __init__(self, textWidget):
33
+ def __init__(self, textWidget, userLocals, userGlobals):
34
+ self.userLocals = userLocals
35
+ self.userGlobals = userGlobals
34
36
  self.textWidget = textWidget
35
37
  self.suggestionWindow = None
36
38
  self.suggestionListbox = None
@@ -42,60 +44,72 @@ class CodeSuggestionManager:
42
44
  self.builtins = [name for name in dir(builtins) if not name.startswith('_')]
43
45
 
44
46
  def getCurrentWord(self):
45
- """Extract the word being typed at cursor position."""
47
+ """Extract the word being typed at cursor position and suggest dir() if applicable."""
48
+ suggestions = []
46
49
  cursorPos = self.textWidget.index(tk.INSERT)
47
50
  lineStart = self.textWidget.index(f"{cursorPos} linestart")
48
51
  currentLine = self.textWidget.get(lineStart, cursorPos)
49
-
52
+
50
53
  # Find the current word
51
54
  words = currentLine.split()
52
55
  if not words:
53
- return ""
54
-
56
+ return "", suggestions
57
+
55
58
  currentWord = words[-1]
56
- # Handle cases like "print(" where we want to suggest after special chars
59
+
60
+
61
+ # If the word contains a dot, try to evaluate the base and get its dir()
62
+ if '.' in currentWord:
63
+ try:
64
+ base_expr = '.'.join(currentWord.split('.')[:-1])
65
+ obj = eval(base_expr, self.userLocals, self.userGlobals)
66
+ suggestions = dir(obj)
67
+ except Exception as e:
68
+ print(e)
57
69
  for char in "([{,.":
58
70
  if char in currentWord:
59
71
  currentWord = currentWord.split(char)[-1]
60
-
61
- return currentWord
72
+
73
+ return currentWord, suggestions
62
74
 
63
- def getSuggestions(self, partialWord):
75
+ def getSuggestions(self, partialWord, suggestions=[]):
64
76
  """Get code suggestions for partial word."""
65
77
  if len(partialWord) < 2:
66
- return []
67
-
68
- suggestions = []
69
-
70
- # Add matching keywords
71
- for kw in self.keywords:
72
- if kw.startswith(partialWord.lower()):
73
- suggestions.append(kw)
74
-
75
- # Add matching builtins
76
- for builtin in self.builtins:
77
- if builtin.startswith(partialWord):
78
- suggestions.append(builtin)
79
-
80
- # Add matching variables from namespace
81
- master = self.textWidget.master
82
- if hasattr(master, 'userLocals'):
83
- for var in master.userLocals:
84
- if var.startswith(partialWord) and not var.startswith('_'):
85
- suggestions.append(var)
78
+ return suggestions
86
79
 
87
- if hasattr(master, 'userGlobals'):
88
- for var in master.userGlobals:
89
- if var.startswith(partialWord) and not var.startswith('_'):
90
- suggestions.append(var)
80
+ # print(partialWord)
81
+ if suggestions != []:
82
+ suggestions = [suggestion for suggestion in suggestions if suggestion.lower().startswith(partialWord.lower())]
83
+ else:
84
+ # Add matching keywords
85
+ for kw in self.keywords:
86
+ if kw.startswith(partialWord.lower()):
87
+ suggestions.append(kw)
88
+
89
+ # Add matching builtins
90
+ for builtin in self.builtins:
91
+ if builtin.startswith(partialWord):
92
+ suggestions.append(builtin)
93
+
94
+ # Add matching variables from namespace
95
+ master = self.textWidget.master
96
+ if hasattr(master, 'userLocals'):
97
+ for var in master.userLocals:
98
+ if var.startswith(partialWord) and not var.startswith('_'):
99
+ suggestions.append(var)
100
+
101
+ if hasattr(master, 'userGlobals'):
102
+ for var in master.userGlobals:
103
+ if var.startswith(partialWord) and not var.startswith('_'):
104
+ suggestions.append(var)
91
105
 
92
106
  # Remove duplicates and sort
93
- return sorted(list(set(suggestions)))[:10]
107
+ return sorted(list(set(suggestions)))
94
108
 
95
109
  def showSuggestions(self):
96
110
  """Display the suggestions popup."""
97
- currentWord = self.getCurrentWord()
98
- suggestions = self.getSuggestions(currentWord)
111
+ currentWord, extraSuggestions = self.getCurrentWord()
112
+ suggestions = self.getSuggestions(currentWord, extraSuggestions)
99
113
 
100
114
  if not suggestions:
101
115
  self.hideSuggestions()
@@ -155,12 +169,11 @@ class CodeSuggestionManager:
155
169
  if not suggestion:
156
170
  return
157
171
 
158
- currentWord = self.getCurrentWord()
159
- if suggestion.startswith(currentWord):
160
- # Only insert the missing part
161
- missingPart = suggestion[len(currentWord):]
162
- cursorPos = self.textWidget.index(tk.INSERT)
163
- self.textWidget.insert(cursorPos, missingPart)
172
+ currentWord, _ = self.getCurrentWord()
173
+ # Only insert the missing part
174
+ missingPart = suggestion[len(currentWord):]
175
+ cursorPos = self.textWidget.index(tk.INSERT)
176
+ self.textWidget.insert(cursorPos, missingPart)
164
177
 
165
178
  self.hideSuggestions()
166
179
 
@@ -220,11 +233,11 @@ class InteractiveConsoleText(tk.Text):
220
233
  PROMPT = ">>> "
221
234
  PROMPT_LENGTH = 4
222
235
 
223
- def __init__(self, master, **kwargs):
236
+ def __init__(self, master, userLocals=None, userGlobals=None, **kwargs):
224
237
  super().__init__(master, **kwargs)
225
238
 
226
239
  # Initialize components
227
- self.suggestionManager = CodeSuggestionManager(self)
240
+ self.suggestionManager = CodeSuggestionManager(self, userLocals=userLocals, userGlobals=userGlobals)
228
241
 
229
242
  self.navigatingHistory = False
230
243
  self.history = CommandHistory()
@@ -591,7 +604,7 @@ class InteractiveConsole(ctk.CTk):
591
604
  self._createUi()
592
605
 
593
606
  # Redirect stdout/stderr
594
- self._setupOutputRedirect()
607
+ # self._setupOutputRedirect()
595
608
 
596
609
  def _createUi(self):
597
610
  """Create the user interface."""
@@ -602,6 +615,8 @@ class InteractiveConsole(ctk.CTk):
602
615
  # Console text widget
603
616
  self.console = InteractiveConsoleText(
604
617
  frame,
618
+ userGlobals=self.userGlobals,
619
+ userLocals=self.userLocals,
605
620
  wrap="word",
606
621
  bg="#1e1e1e",
607
622
  fg="white",
File without changes
File without changes
File without changes
File without changes