Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add IPython-style assignment
  • Loading branch information
YoannQDQ authored and nyalldawson committed Apr 24, 2023
1 parent 73e9596 commit 6257a65
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 5 deletions.
39 changes: 35 additions & 4 deletions python/console/console_sci.py
Expand Up @@ -24,6 +24,8 @@
import re
import sys
import traceback
from pathlib import Path
from tempfile import NamedTemporaryFile

from qgis.PyQt.Qsci import QsciScintilla
from qgis.PyQt.QtCore import Qt, QCoreApplication
Expand Down Expand Up @@ -93,17 +95,46 @@ def execCommandImpl(self, cmd, show_input=True):
self.sub_process.write(cmd)
return 0

if show_input:
self.writeCMD(cmd)

if self.currentState() == 0:

# This line makes single line commands with leading spaces work
cmd = cmd.strip()
if cmd.startswith("!"):
self.writeCMD(cmd)

# User entered: varname = !cmd
# Run the command and assign the output to varname
# Mimics IPython's behavior
assignment_pattern = r"(\w+)\s*=\s*!(.+)"
match = re.match(assignment_pattern, cmd)
if match:
varname = match[1]
cmd = match[2]
# Run the command in non-interactive mode
self.sub_process = ProcessWrapper(cmd, interactive=False)
# Concatenate stdout and stderr
res = (self.sub_process.stdout + self.sub_process.stderr).strip()

# Use a temporary file to communicate the result to the inner interpreter
tmp = Path(NamedTemporaryFile(delete=False).name)
tmp.write_text(res, encoding="utf-8")
self.runsource(f'{varname} = Path("{tmp}").read_text(encoding="utf-8").split("\\n")')
tmp.unlink()
self.sub_process = None
return 0

# User entered: !cmd
# Run the command and stream the output to the console
# While the process is running, the console is in state 2 meaning
# that all input is sent to the child process
# Mimics IPython's behavior
elif cmd.startswith("!"):
cmd = cmd[1:]
self.sub_process = ProcessWrapper(cmd)
self.sub_process.finished.connect(self.processFinished)
return 0

if show_input:
self.writeCMD(cmd)
import webbrowser
version = 'master' if 'master' in Qgis.QGIS_VERSION.lower() else \
re.findall(r'^\d.[0-9]*', Qgis.QGIS_VERSION)[0]
Expand Down
10 changes: 9 additions & 1 deletion python/console/process_wrapper.py
Expand Up @@ -15,7 +15,7 @@ class ProcessWrapper(QObject):

finished = pyqtSignal(int)

def __init__(self, command, parent=None):
def __init__(self, command, interactive=True, parent=None):
super().__init__(parent)

self.stdout = ""
Expand All @@ -37,6 +37,14 @@ def __init__(self, command, parent=None):
# Create and start subprocess
self.p = subprocess.Popen(command, **options)

# Start in non-interactive mode, wait for the process to finish
if not interactive:
out, err = self.p.communicate()
self.stdout = self.decode(out)
self.stderr = self.decode(err)
self.returncode = self.p.returncode
return

# Read process stdout and push to out queue
self.q_out = Queue()
self.t_out = Thread(daemon=True, target=self.enqueue_output, args=[self.p.stdout, self.q_out])
Expand Down

0 comments on commit 6257a65

Please sign in to comment.