Skip to content

Commit 90efcdc

Browse files
committed
Initial commit.
0 parents  commit 90efcdc

File tree

6 files changed

+184
-0
lines changed

6 files changed

+184
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.vscode
2+
__pycache__
3+
python-debug.zip
4+
lib/**

__init__.py

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
"""An example of embedding a RichJupyterWidget in a PyQT Application.
2+
3+
This uses a normal kernel launched as a subprocess. It shows how to shutdown
4+
the kernel cleanly when the application quits.
5+
6+
To run:
7+
8+
python3 embed_qtconsole.py
9+
"""
10+
import os
11+
import site
12+
13+
from typing import List
14+
15+
from PyQt5 import QtCore, QtGui, QtWidgets
16+
17+
import mobase
18+
import moprivate
19+
20+
site.addsitedir(os.path.join(os.path.dirname(__file__), "lib"))
21+
22+
from pyqtconsole.console import PythonConsole # noqa: E402
23+
24+
25+
class InfinitePythonConsole(PythonConsole):
26+
def __init__(self, *args, **kwargs):
27+
28+
oldps = self._show_ps
29+
self._show_ps = lambda *args: None
30+
31+
super().__init__(*args, **kwargs)
32+
33+
styles = self.pbar.highlighter.styles
34+
self.pbar.highlighter.rules = [
35+
# Match the prompt incase of a console
36+
(QtCore.QRegExp(r"In[^\:]*"), 0, styles["inprompt"]),
37+
(QtCore.QRegExp(r"Out[^\:]*"), 0, styles["outprompt"]),
38+
# Numeric literals
39+
(QtCore.QRegExp(r"\b[+-]?[0-9]+\b"), 0, styles["numbers"]),
40+
]
41+
42+
self._ps1 = "In [%s]: "
43+
self._ps2 = "...: "
44+
self._ps_out = "Out[%s]: "
45+
self._ps = self._ps1 % self._current_line
46+
47+
self._show_ps = oldps
48+
49+
self.interpreter.locals["clear"] = self._clear
50+
51+
def _clear(self):
52+
edit = self.edit
53+
vsb = self.edit.verticalScrollBar()
54+
fm = QtGui.QFontMetrics(self.edit.font())
55+
56+
nvislines = min(
57+
edit.document().lineCount(),
58+
(edit.height() - edit.document().documentMargin() * 2) // fm.lineSpacing(),
59+
)
60+
61+
vsb.setMaximum(vsb.maximum() + nvislines - 1)
62+
vsb.setValue(vsb.maximum())
63+
64+
def exit(self):
65+
self._close()
66+
67+
68+
class IPythonDebugPlugin(mobase.IPluginTool):
69+
70+
_organizer: mobase.IOrganizer
71+
72+
def __init__(self):
73+
super().__init__() # You need to call this manually.
74+
75+
def init(self, organizer: mobase.IOrganizer):
76+
self._organizer = organizer
77+
78+
# Create the console:
79+
self._console = InfinitePythonConsole(
80+
locals={
81+
"organizer": self._organizer,
82+
"mobase": mobase,
83+
"moprivate": moprivate,
84+
"_plugin": self,
85+
}
86+
)
87+
self._console.resize(840, 680)
88+
self._setFont()
89+
self._console._show_ps()
90+
self._console.eval_in_thread()
91+
92+
self._organizer.onUserInterfaceInitialized(
93+
lambda mw: QtWidgets.QShortcut(
94+
QtGui.QKeySequence(QtCore.Qt.Key_F12), mw
95+
).activated.connect(self.display),
96+
)
97+
98+
return True
99+
100+
def name(self) -> str:
101+
return "Python Debugger"
102+
103+
def author(self) -> str:
104+
return "Holt59"
105+
106+
def description(self) -> str:
107+
return self._tr("Run IPython from MO2")
108+
109+
def version(self) -> mobase.VersionInfo:
110+
return mobase.VersionInfo(1, 0, 0, mobase.ReleaseType.FINAL)
111+
112+
def isActive(self) -> bool:
113+
return self._organizer.pluginSetting(self.name(), "enabled")
114+
115+
def settings(self) -> List[mobase.PluginSetting]:
116+
return [
117+
mobase.PluginSetting("enabled", "enable this plugin", True),
118+
mobase.PluginSetting(
119+
"font family", "font family for the terminal", "Courier New"
120+
),
121+
mobase.PluginSetting("font size", "font size for the terminal", 10),
122+
]
123+
124+
def displayName(self) -> str:
125+
return self._tr("Python Debugger")
126+
127+
def icon(self) -> QtGui.QIcon:
128+
return QtGui.QIcon(
129+
os.path.join(os.path.dirname(__file__), "res", "python.webp")
130+
)
131+
132+
def tooltip(self) -> str:
133+
return self._tr("Open the Python debugger")
134+
135+
def display(self):
136+
self._console.show()
137+
138+
def _setFont(self):
139+
font = self._console.edit.document().defaultFont()
140+
font.setFamily(self._organizer.pluginSetting(self.name(), "font family"))
141+
font.setPointSize(self._organizer.pluginSetting(self.name(), "font size"))
142+
self._console.setFont(font)
143+
144+
def _tr(self, txt: str) -> str:
145+
return QtWidgets.QApplication.translate(IPythonDebugPlugin.__name__, txt)
146+
147+
148+
def createPlugin() -> mobase.IPlugin:
149+
return IPythonDebugPlugin()

lib/.gitkeep

Whitespace-only changes.

make-release.ps1

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
if ((python --version) -match "Python 3.8.") {
2+
python -m pip install --target=.\lib --force --upgrade pyqtconsole
3+
zip -qr python-debug.zip .\__init__.py .\lib\ .\res\
4+
}
5+
else {
6+
Write-Output "Cannot build release without Python 3.8."
7+
}

res/python.webp

10.9 KB
Loading

setup.cfg

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[flake8]
2+
# Use black line length:
3+
max-line-length = 88
4+
extend-ignore =
5+
# See https://github.com/PyCQA/pycodestyle/issues/373
6+
E203, E266
7+
8+
[mypy]
9+
warn_return_any = True
10+
warn_unused_configs = True
11+
12+
[tox:tox]
13+
skipsdist = true
14+
envlist = py38-lint
15+
16+
[testenv:py38-lint]
17+
skip_install = true
18+
deps =
19+
black
20+
flake8
21+
flake8-black
22+
commands =
23+
black --check --diff .
24+
flake8 .

0 commit comments

Comments
 (0)