mwxlib 1.4.0__py3-none-any.whl → 1.4.6__py3-none-any.whl
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 mwxlib might be problematic. Click here for more details.
- mwx/framework.py +3 -2
- mwx/graphman.py +30 -30
- mwx/matplot2g.py +8 -3
- mwx/nutshell.py +60 -68
- mwx/utilus.py +77 -73
- {mwxlib-1.4.0.dist-info → mwxlib-1.4.6.dist-info}/METADATA +1 -1
- {mwxlib-1.4.0.dist-info → mwxlib-1.4.6.dist-info}/RECORD +9 -9
- {mwxlib-1.4.0.dist-info → mwxlib-1.4.6.dist-info}/WHEEL +1 -1
- {mwxlib-1.4.0.dist-info → mwxlib-1.4.6.dist-info}/top_level.txt +0 -0
mwx/framework.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#! python3
|
|
2
2
|
"""mwxlib framework.
|
|
3
3
|
"""
|
|
4
|
-
__version__ = "1.4.
|
|
4
|
+
__version__ = "1.4.6"
|
|
5
5
|
__author__ = "Kazuya O'moto <komoto@jeol.co.jp>"
|
|
6
6
|
|
|
7
7
|
from contextlib import contextmanager
|
|
@@ -1460,7 +1460,8 @@ class ShellFrame(MiniFrame):
|
|
|
1460
1460
|
if not evt.Active:
|
|
1461
1461
|
## Reset autoload when active focus going outside.
|
|
1462
1462
|
self.__autoload = True
|
|
1463
|
-
elif evt.GetActivationReason() == evt.Reason_Mouse and self.__autoload:
|
|
1463
|
+
## elif evt.GetActivationReason() == evt.Reason_Mouse and self.__autoload:
|
|
1464
|
+
elif self.__autoload:
|
|
1464
1465
|
## Check all buffers that need to be loaded.
|
|
1465
1466
|
verbose = 1
|
|
1466
1467
|
for book in self.get_all_editors():
|
mwx/graphman.py
CHANGED
|
@@ -192,12 +192,12 @@ class Thread:
|
|
|
192
192
|
except BdbQuit:
|
|
193
193
|
pass
|
|
194
194
|
except KeyboardInterrupt as e:
|
|
195
|
-
print("- Thread
|
|
195
|
+
print("- Thread execution stopped:", e)
|
|
196
196
|
except AssertionError as e:
|
|
197
|
-
print("- Thread
|
|
197
|
+
print("- Thread execution failed:", e)
|
|
198
198
|
except Exception as e:
|
|
199
199
|
traceback.print_exc()
|
|
200
|
-
print("- Thread
|
|
200
|
+
print("- Thread exception:", e)
|
|
201
201
|
self.handler('thread_error', self)
|
|
202
202
|
finally:
|
|
203
203
|
self.active = 0
|
|
@@ -437,7 +437,7 @@ class LayerInterface(CtrlInterface):
|
|
|
437
437
|
def OnDestroy(self, evt):
|
|
438
438
|
if evt.EventObject is self:
|
|
439
439
|
if self.thread and self.thread.active:
|
|
440
|
-
self.thread.active = 0
|
|
440
|
+
## self.thread.active = 0
|
|
441
441
|
self.thread.Stop()
|
|
442
442
|
del self.Arts
|
|
443
443
|
evt.Skip()
|
|
@@ -882,28 +882,28 @@ class Frame(mwx.Frame):
|
|
|
882
882
|
elif ret == wx.ID_CANCEL:
|
|
883
883
|
evt.Veto()
|
|
884
884
|
return
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
885
|
+
n = sum(bool(plug.thread and plug.thread.active)
|
|
886
|
+
for plug in (self.get_plug(name) for name in self.plugins))
|
|
887
|
+
if n:
|
|
888
|
+
s = 's' if n > 1 else ''
|
|
889
|
+
if wx.MessageBox( # Confirm closing the thread.
|
|
890
|
+
f"Currently running {n} thread{s}.\n\n"
|
|
891
|
+
"Continue closing?",
|
|
892
|
+
style=wx.YES_NO|wx.ICON_INFORMATION) != wx.YES:
|
|
893
|
+
self.message("The close has been canceled.")
|
|
894
|
+
evt.Veto()
|
|
895
|
+
return
|
|
896
|
+
self.Quit()
|
|
897
|
+
n = sum(frame.pathname is None for frame in self.graph.all_frames)
|
|
898
|
+
if n:
|
|
899
|
+
s = 's' if n > 1 else ''
|
|
900
|
+
if wx.MessageBox( # Confirm closing the frame.
|
|
901
|
+
f"You are closing {n} unsaved frame{s}.\n\n"
|
|
902
|
+
"Continue closing?",
|
|
903
|
+
style=wx.YES_NO|wx.ICON_INFORMATION) != wx.YES:
|
|
904
|
+
self.message("The close has been canceled.")
|
|
905
|
+
evt.Veto()
|
|
906
|
+
return
|
|
907
907
|
evt.Skip()
|
|
908
908
|
|
|
909
909
|
def Destroy(self):
|
|
@@ -1383,7 +1383,7 @@ class Frame(mwx.Frame):
|
|
|
1383
1383
|
plug = self.get_plug(name)
|
|
1384
1384
|
thread = plug.thread # Note: thread can be None or shared.
|
|
1385
1385
|
if thread and thread.active:
|
|
1386
|
-
thread.active = 0
|
|
1386
|
+
## thread.active = 0
|
|
1387
1387
|
thread.Stop()
|
|
1388
1388
|
|
|
1389
1389
|
## --------------------------------
|
|
@@ -1432,7 +1432,7 @@ class Frame(mwx.Frame):
|
|
|
1432
1432
|
"""
|
|
1433
1433
|
view = self.selected_view
|
|
1434
1434
|
if not frames:
|
|
1435
|
-
frames = view.
|
|
1435
|
+
frames = view.all_frames
|
|
1436
1436
|
if not frames:
|
|
1437
1437
|
return None
|
|
1438
1438
|
|
|
@@ -1698,7 +1698,7 @@ class Frame(mwx.Frame):
|
|
|
1698
1698
|
def save_buffers_as_tiffs(self, path=None, frames=None):
|
|
1699
1699
|
"""Save buffers to a file as a multi-page tiff."""
|
|
1700
1700
|
if not frames:
|
|
1701
|
-
frames = self.selected_view.
|
|
1701
|
+
frames = self.selected_view.all_frames
|
|
1702
1702
|
if not frames:
|
|
1703
1703
|
return None
|
|
1704
1704
|
|
|
@@ -1817,7 +1817,7 @@ class Frame(mwx.Frame):
|
|
|
1817
1817
|
|
|
1818
1818
|
def _save(view):
|
|
1819
1819
|
name = view.Name
|
|
1820
|
-
paths = [x.pathname for x in view.
|
|
1820
|
+
paths = [x.pathname for x in view.all_frames if x.pathname]
|
|
1821
1821
|
o.write(f"self.{name}.unit = {view.unit:g}\n")
|
|
1822
1822
|
o.write(f"self.load_frame({paths!r}, self.{name})\n")
|
|
1823
1823
|
try:
|
mwx/matplot2g.py
CHANGED
|
@@ -783,9 +783,14 @@ class GraphPlot(MatplotPanel):
|
|
|
783
783
|
else:
|
|
784
784
|
return self.__Arts[j] # j:int -> frame
|
|
785
785
|
|
|
786
|
-
def get_all_frames(self):
|
|
786
|
+
def get_all_frames(self, j=None):
|
|
787
787
|
"""List of arts <matplotlib.image.AxesImage>."""
|
|
788
|
-
|
|
788
|
+
if j is None:
|
|
789
|
+
yield from self.__Arts
|
|
790
|
+
elif isinstance(j, str):
|
|
791
|
+
yield from (art for art in self.__Arts if j in art.name)
|
|
792
|
+
elif isinstance(j, np.ndarray):
|
|
793
|
+
yield from (art for art in self.__Arts if j is art.buffer)
|
|
789
794
|
|
|
790
795
|
## --------------------------------
|
|
791
796
|
## Property of frame / drawer
|
|
@@ -798,7 +803,7 @@ class GraphPlot(MatplotPanel):
|
|
|
798
803
|
score_percentile = 0.005
|
|
799
804
|
|
|
800
805
|
@property
|
|
801
|
-
def all_frames(self):
|
|
806
|
+
def all_frames(self):
|
|
802
807
|
"""List of arts <matplotlib.image.AxesImage>."""
|
|
803
808
|
return self.__Arts
|
|
804
809
|
|
mwx/nutshell.py
CHANGED
|
@@ -28,7 +28,7 @@ from wx.py.editwindow import EditWindow
|
|
|
28
28
|
|
|
29
29
|
from .utilus import funcall as _F
|
|
30
30
|
from .utilus import ignore, typename
|
|
31
|
-
from .utilus import split_words,
|
|
31
|
+
from .utilus import split_words, split_parts, split_tokens, find_modules
|
|
32
32
|
from .framework import CtrlInterface, AuiNotebook, Menu
|
|
33
33
|
|
|
34
34
|
|
|
@@ -210,8 +210,8 @@ class AutoCompInterfaceMixin:
|
|
|
210
210
|
dispatcher.send(signal='Shell.calltip', sender=self, calltip=tip)
|
|
211
211
|
p = self.cpos
|
|
212
212
|
if argspec and insertcalltip:
|
|
213
|
-
self.AddText(argspec + ')')
|
|
214
|
-
self.
|
|
213
|
+
self.AddText(argspec + ')')
|
|
214
|
+
self.cpos = p # selection backward to the point
|
|
215
215
|
if tip:
|
|
216
216
|
## In case there isn't enough room, only go back to bol fallback.
|
|
217
217
|
tippos = max(self.bol, p - len(name) - 1)
|
|
@@ -269,7 +269,7 @@ class AutoCompInterfaceMixin:
|
|
|
269
269
|
self.anchor = q
|
|
270
270
|
with self.off_undocollection():
|
|
271
271
|
self.ReplaceSelection(word[n:])
|
|
272
|
-
self.cpos = p # backward
|
|
272
|
+
self.cpos = p # selection backward to the point
|
|
273
273
|
self.__comp_ind = j
|
|
274
274
|
except IndexError:
|
|
275
275
|
self.message("No completion words")
|
|
@@ -641,8 +641,8 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
|
|
|
641
641
|
self.IndicatorSetStyle(11, stc.STC_INDIC_STRAIGHTBOX)
|
|
642
642
|
self.IndicatorSetForeground(11, "yellow")
|
|
643
643
|
self.IndicatorSetUnder(11, True)
|
|
644
|
-
self.IndicatorSetAlpha(11, 0xe8)
|
|
645
|
-
self.IndicatorSetOutlineAlpha(11, 0)
|
|
644
|
+
## self.IndicatorSetAlpha(11, 0xe8)
|
|
645
|
+
## self.IndicatorSetOutlineAlpha(11, 0)
|
|
646
646
|
|
|
647
647
|
self.IndicatorSetStyle(2, stc.STC_INDIC_DOTS)
|
|
648
648
|
self.IndicatorSetForeground(2, "light gray")
|
|
@@ -863,7 +863,7 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
|
|
|
863
863
|
return sty
|
|
864
864
|
|
|
865
865
|
def get_char(self, pos):
|
|
866
|
-
"""Returns the character at the position."""
|
|
866
|
+
"""Returns the character at the given position."""
|
|
867
867
|
return chr(self.GetCharAt(pos))
|
|
868
868
|
|
|
869
869
|
def get_text(self, start, end):
|
|
@@ -944,10 +944,12 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
|
|
|
944
944
|
return topic
|
|
945
945
|
with self.save_excursion():
|
|
946
946
|
p = q = self.cpos
|
|
947
|
-
if self.get_char(p-1).
|
|
947
|
+
## if self.get_char(p-1).isidentifier():
|
|
948
|
+
if self.GetTextRange(self.PositionBefore(p), p).isidentifier():
|
|
948
949
|
self.WordLeft()
|
|
949
950
|
p = self.cpos
|
|
950
|
-
if self.get_char(q).
|
|
951
|
+
## if self.get_char(q).isidentifier():
|
|
952
|
+
if self.GetTextRange(q, self.PositionAfter(q)).isidentifier():
|
|
951
953
|
self.WordRightEnd()
|
|
952
954
|
q = self.cpos
|
|
953
955
|
return self.GetTextRange(p, q)
|
|
@@ -1376,32 +1378,34 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
|
|
|
1376
1378
|
def grep(self, pattern, flags=re.M):
|
|
1377
1379
|
yield from re.finditer(pattern.encode(), self.TextRaw, flags)
|
|
1378
1380
|
|
|
1379
|
-
def search_text(self, text):
|
|
1380
|
-
"""Yields
|
|
1381
|
-
word
|
|
1382
|
-
|
|
1381
|
+
def search_text(self, text, mode=True):
|
|
1382
|
+
"""Yields positions where `text` is found.
|
|
1383
|
+
If mode is True, search by word; otherwise, search by string.
|
|
1384
|
+
"""
|
|
1385
|
+
text = text.encode()
|
|
1383
1386
|
pos = -1
|
|
1387
|
+
p = re.compile(r"[a-zA-Z0-9_]")
|
|
1384
1388
|
while 1:
|
|
1385
|
-
pos =
|
|
1389
|
+
pos = self.TextRaw.find(text, pos+1)
|
|
1386
1390
|
if pos < 0:
|
|
1387
1391
|
break
|
|
1392
|
+
if mode and p.search(self.get_char(pos-1) + self.get_char(pos+len(text))):
|
|
1393
|
+
continue
|
|
1388
1394
|
yield pos
|
|
1389
1395
|
|
|
1390
|
-
def filter_text(self
|
|
1396
|
+
def filter_text(self):
|
|
1391
1397
|
"""Show indicators for the selected text."""
|
|
1392
1398
|
self.__itextlines = []
|
|
1393
1399
|
for i in (10, 11,):
|
|
1394
1400
|
self.SetIndicatorCurrent(i)
|
|
1395
1401
|
self.IndicatorClearRange(0, self.TextLength)
|
|
1396
|
-
|
|
1397
|
-
text = self.topic_at_caret
|
|
1402
|
+
text = self.topic_at_caret
|
|
1398
1403
|
if not text:
|
|
1399
1404
|
self.message("No words")
|
|
1400
1405
|
return
|
|
1401
|
-
|
|
1402
1406
|
lw = len(text.encode()) # for multi-byte string
|
|
1403
1407
|
lines = []
|
|
1404
|
-
for p in self.search_text(text):
|
|
1408
|
+
for p in self.search_text(text, mode=(not self.SelectedText)):
|
|
1405
1409
|
lines.append(self.LineFromPosition(p))
|
|
1406
1410
|
for i in (10, 11,):
|
|
1407
1411
|
self.SetIndicatorCurrent(i)
|
|
@@ -1833,12 +1837,8 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
1833
1837
|
self.message("")
|
|
1834
1838
|
|
|
1835
1839
|
def clear_autocomp(evt):
|
|
1836
|
-
## """Clear autocomp, selection, and message."""
|
|
1837
1840
|
if self.AutoCompActive():
|
|
1838
1841
|
self.AutoCompCancel()
|
|
1839
|
-
if self.CanEdit():
|
|
1840
|
-
with self.off_undocollection():
|
|
1841
|
-
self.ReplaceSelection("")
|
|
1842
1842
|
self.message("")
|
|
1843
1843
|
|
|
1844
1844
|
def fork(evt):
|
|
@@ -1882,7 +1882,7 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
1882
1882
|
'* pressed' : (0, clear_autocomp, fork),
|
|
1883
1883
|
'tab pressed' : (0, clear, skip),
|
|
1884
1884
|
'enter pressed' : (0, clear, skip),
|
|
1885
|
-
'escape pressed' : (0,
|
|
1885
|
+
'escape pressed' : (0, clear, skip),
|
|
1886
1886
|
'up pressed' : (2, skip, self.on_completion_backward),
|
|
1887
1887
|
'down pressed' : (2, skip, self.on_completion_forward),
|
|
1888
1888
|
'*left pressed' : (2, skip),
|
|
@@ -1909,7 +1909,7 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
1909
1909
|
'* pressed' : (0, clear_autocomp, fork),
|
|
1910
1910
|
'tab pressed' : (0, clear, skip),
|
|
1911
1911
|
'enter pressed' : (0, clear, skip),
|
|
1912
|
-
'escape pressed' : (0,
|
|
1912
|
+
'escape pressed' : (0, clear, skip),
|
|
1913
1913
|
'up pressed' : (3, skip, self.on_completion_backward),
|
|
1914
1914
|
'down pressed' : (3, skip, self.on_completion_forward),
|
|
1915
1915
|
'*left pressed' : (3, skip),
|
|
@@ -2099,8 +2099,15 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
2099
2099
|
if self.CallTipActive():
|
|
2100
2100
|
self.CallTipCancel()
|
|
2101
2101
|
|
|
2102
|
-
|
|
2103
|
-
|
|
2102
|
+
def _gen_text():
|
|
2103
|
+
text = self.SelectedText
|
|
2104
|
+
if text:
|
|
2105
|
+
yield text
|
|
2106
|
+
else:
|
|
2107
|
+
yield self.line_at_caret
|
|
2108
|
+
yield self.expr_at_caret
|
|
2109
|
+
|
|
2110
|
+
for text in _gen_text():
|
|
2104
2111
|
try:
|
|
2105
2112
|
obj = eval(text, self.globals, self.locals)
|
|
2106
2113
|
except Exception as e:
|
|
@@ -2108,7 +2115,8 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
2108
2115
|
else:
|
|
2109
2116
|
self.CallTipShow(self.cpos, pformat(obj))
|
|
2110
2117
|
self.message(text)
|
|
2111
|
-
|
|
2118
|
+
return
|
|
2119
|
+
if not text:
|
|
2112
2120
|
self.message("No words")
|
|
2113
2121
|
|
|
2114
2122
|
def exec_region(self):
|
|
@@ -2610,22 +2618,6 @@ class Interpreter(interpreter.Interpreter):
|
|
|
2610
2618
|
self.parent.handler('interp_error', v)
|
|
2611
2619
|
except AttributeError:
|
|
2612
2620
|
pass
|
|
2613
|
-
|
|
2614
|
-
@ignore(DeprecationWarning)
|
|
2615
|
-
def getCallTip(self, command='', *args, **kwargs):
|
|
2616
|
-
"""Return call tip text for a command.
|
|
2617
|
-
|
|
2618
|
-
(override) Ignore DeprecationWarning: for function,
|
|
2619
|
-
`formatargspec` is deprecated since Python 3.5.
|
|
2620
|
-
(override) Ignore ValueError: no signature found for builtin
|
|
2621
|
-
if the unwrapped function is a builtin function.
|
|
2622
|
-
"""
|
|
2623
|
-
## In 4.2.1, DeprecationWarning was fixed.
|
|
2624
|
-
## In 4.2.2, ValueError was fixed.
|
|
2625
|
-
try:
|
|
2626
|
-
return interpreter.Interpreter.getCallTip(self, command, *args, **kwargs)
|
|
2627
|
-
except ValueError:
|
|
2628
|
-
return interpreter.Interpreter.getCallTip(self) # dummy
|
|
2629
2621
|
|
|
2630
2622
|
|
|
2631
2623
|
class Nautilus(EditorInterface, Shell):
|
|
@@ -2796,12 +2788,8 @@ class Nautilus(EditorInterface, Shell):
|
|
|
2796
2788
|
self.message("")
|
|
2797
2789
|
|
|
2798
2790
|
def clear_autocomp(evt):
|
|
2799
|
-
## """Clear autocomp, selection, and message."""
|
|
2800
2791
|
if self.AutoCompActive():
|
|
2801
2792
|
self.AutoCompCancel()
|
|
2802
|
-
if self.CanEdit():
|
|
2803
|
-
with self.off_undocollection():
|
|
2804
|
-
self.ReplaceSelection("")
|
|
2805
2793
|
self.message("")
|
|
2806
2794
|
|
|
2807
2795
|
def fork(evt):
|
|
@@ -2900,7 +2888,7 @@ class Nautilus(EditorInterface, Shell):
|
|
|
2900
2888
|
'* pressed' : (0, clear_autocomp, fork),
|
|
2901
2889
|
'tab pressed' : (0, clear, skip),
|
|
2902
2890
|
'enter pressed' : (0, clear, skip),
|
|
2903
|
-
'escape pressed' : (0,
|
|
2891
|
+
'escape pressed' : (0, clear, skip),
|
|
2904
2892
|
'up pressed' : (2, skip, self.on_completion_backward),
|
|
2905
2893
|
'down pressed' : (2, skip, self.on_completion_forward),
|
|
2906
2894
|
'*left pressed' : (2, skip),
|
|
@@ -2928,7 +2916,7 @@ class Nautilus(EditorInterface, Shell):
|
|
|
2928
2916
|
'* pressed' : (0, clear_autocomp, fork),
|
|
2929
2917
|
'tab pressed' : (0, clear, skip),
|
|
2930
2918
|
'enter pressed' : (0, clear, skip),
|
|
2931
|
-
'escape pressed' : (0,
|
|
2919
|
+
'escape pressed' : (0, clear, skip),
|
|
2932
2920
|
'up pressed' : (3, skip, self.on_completion_backward),
|
|
2933
2921
|
'down pressed' : (3, skip, self.on_completion_forward),
|
|
2934
2922
|
'*left pressed' : (3, skip),
|
|
@@ -2956,7 +2944,7 @@ class Nautilus(EditorInterface, Shell):
|
|
|
2956
2944
|
'* pressed' : (0, clear_autocomp, fork),
|
|
2957
2945
|
'tab pressed' : (0, clear, skip),
|
|
2958
2946
|
'enter pressed' : (0, clear, skip),
|
|
2959
|
-
'escape pressed' : (0,
|
|
2947
|
+
'escape pressed' : (0, clear, skip),
|
|
2960
2948
|
'up pressed' : (4, skip, self.on_completion_backward),
|
|
2961
2949
|
'down pressed' : (4, skip, self.on_completion_forward),
|
|
2962
2950
|
'*left pressed' : (4, skip),
|
|
@@ -2984,7 +2972,7 @@ class Nautilus(EditorInterface, Shell):
|
|
|
2984
2972
|
'* pressed' : (0, clear_autocomp, fork),
|
|
2985
2973
|
'tab pressed' : (0, clear, skip),
|
|
2986
2974
|
'enter pressed' : (0, clear, skip),
|
|
2987
|
-
'escape pressed' : (0,
|
|
2975
|
+
'escape pressed' : (0, clear, skip),
|
|
2988
2976
|
'up pressed' : (5, skip, self.on_completion_backward),
|
|
2989
2977
|
'down pressed' : (5, skip, self.on_completion_forward),
|
|
2990
2978
|
'*left pressed' : (5, skip),
|
|
@@ -3135,7 +3123,7 @@ class Nautilus(EditorInterface, Shell):
|
|
|
3135
3123
|
rst = self.get_style(p)
|
|
3136
3124
|
if p == self.bolc:
|
|
3137
3125
|
self.ReplaceSelection('self') # replace [.] --> [self.]
|
|
3138
|
-
elif st in ('
|
|
3126
|
+
elif st in ('space', 'sep', 'lparen'):
|
|
3139
3127
|
self.ReplaceSelection('self')
|
|
3140
3128
|
elif st not in ('moji', 'word', 'rparen') or rst == 'word':
|
|
3141
3129
|
self.handler('quit', evt) # don't enter autocomp
|
|
@@ -3238,16 +3226,21 @@ class Nautilus(EditorInterface, Shell):
|
|
|
3238
3226
|
## func(a,b,c) @debug --> func,a,b,c @debug
|
|
3239
3227
|
if rhs in ("debug", "profile", "timeit"):
|
|
3240
3228
|
if lhs[-1] in ')':
|
|
3241
|
-
|
|
3229
|
+
R = next(split_parts(lhs, reverse=1))
|
|
3230
|
+
L = lhs[:-len(R)]
|
|
3242
3231
|
if not L:
|
|
3243
3232
|
lhs = "{!r}".format(R[1:-1])
|
|
3244
|
-
|
|
3233
|
+
else:
|
|
3245
3234
|
lhs = "{}, {}".format(L, R[1:-1])
|
|
3246
3235
|
|
|
3247
3236
|
## @(y1,,,yn) --> @partial(y1,,,yn)
|
|
3248
3237
|
elif rhs.startswith('('):
|
|
3249
3238
|
rhs = re.sub(r"^\((.*)\)", r"partial(\1)", rhs, flags=re.S)
|
|
3250
3239
|
|
|
3240
|
+
## obj @.method --> (obj).method
|
|
3241
|
+
elif rhs.startswith('.'):
|
|
3242
|
+
return self.magic_interpret([f"({lhs}){rhs}"] + rest)
|
|
3243
|
+
|
|
3251
3244
|
return self.magic_interpret([f"{rhs}({lhs})"] + rest)
|
|
3252
3245
|
|
|
3253
3246
|
if c == '`':
|
|
@@ -3516,7 +3509,7 @@ class Nautilus(EditorInterface, Shell):
|
|
|
3516
3509
|
def write(self, text, pos=None):
|
|
3517
3510
|
"""Display text in the shell.
|
|
3518
3511
|
|
|
3519
|
-
(override) Append text if it is writable at the position.
|
|
3512
|
+
(override) Append text if it is writable at the given position.
|
|
3520
3513
|
"""
|
|
3521
3514
|
if pos is not None:
|
|
3522
3515
|
if pos < 0:
|
|
@@ -3603,22 +3596,20 @@ class Nautilus(EditorInterface, Shell):
|
|
|
3603
3596
|
## Autocomp actions of the shell
|
|
3604
3597
|
## --------------------------------
|
|
3605
3598
|
|
|
3606
|
-
def autoCallTipShow(self, command, insertcalltip=True, forceCallTip=False):
|
|
3607
|
-
"""Display argument spec and docstring in a popup window.
|
|
3608
|
-
|
|
3609
|
-
(override) Swap anchors to not scroll to the end of the line.
|
|
3610
|
-
"""
|
|
3611
|
-
Shell.autoCallTipShow(self, command, insertcalltip, forceCallTip)
|
|
3612
|
-
self.cpos, self.anchor = self.anchor, self.cpos
|
|
3613
|
-
self.EnsureCaretVisible()
|
|
3614
|
-
|
|
3615
3599
|
def eval_line(self):
|
|
3616
3600
|
"""Evaluate the selected word or line."""
|
|
3617
3601
|
if self.CallTipActive():
|
|
3618
3602
|
self.CallTipCancel()
|
|
3619
3603
|
|
|
3620
|
-
|
|
3621
|
-
|
|
3604
|
+
def _gen_text():
|
|
3605
|
+
text = self.SelectedText
|
|
3606
|
+
if text:
|
|
3607
|
+
yield text
|
|
3608
|
+
else:
|
|
3609
|
+
yield self.line_at_caret
|
|
3610
|
+
yield self.expr_at_caret
|
|
3611
|
+
|
|
3612
|
+
for text in _gen_text():
|
|
3622
3613
|
tokens = split_words(text)
|
|
3623
3614
|
try:
|
|
3624
3615
|
cmd = self.magic_interpret(tokens)
|
|
@@ -3629,7 +3620,8 @@ class Nautilus(EditorInterface, Shell):
|
|
|
3629
3620
|
else:
|
|
3630
3621
|
self.CallTipShow(self.cpos, pformat(obj))
|
|
3631
3622
|
self.message(cmd)
|
|
3632
|
-
|
|
3623
|
+
return
|
|
3624
|
+
if not text:
|
|
3633
3625
|
self.message("No words")
|
|
3634
3626
|
|
|
3635
3627
|
def exec_region(self):
|
mwx/utilus.py
CHANGED
|
@@ -283,24 +283,28 @@ if pp:
|
|
|
283
283
|
pp.sort_dicts = True
|
|
284
284
|
|
|
285
285
|
|
|
286
|
-
def
|
|
287
|
-
"""
|
|
288
|
-
If reverse is True,
|
|
286
|
+
def split_words(text, reverse=False):
|
|
287
|
+
"""Generates words (python phrase) extracted from text.
|
|
288
|
+
If reverse is True, process from tail to head.
|
|
289
289
|
"""
|
|
290
290
|
tokens = list(split_tokens(text))
|
|
291
291
|
if reverse:
|
|
292
292
|
tokens = tokens[::-1]
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
293
|
+
while tokens:
|
|
294
|
+
words = []
|
|
295
|
+
while 1:
|
|
296
|
+
word = _extract_words_from_tokens(tokens, reverse)
|
|
297
|
+
if not word:
|
|
298
|
+
break
|
|
299
|
+
words += word
|
|
300
|
+
if words:
|
|
301
|
+
yield ''.join(reversed(words) if reverse else words)
|
|
302
|
+
if tokens:
|
|
303
|
+
yield tokens.pop(0) # sep-token
|
|
300
304
|
|
|
301
305
|
|
|
302
|
-
def
|
|
303
|
-
"""Generates words extracted from text.
|
|
306
|
+
def split_parts(text, reverse=False):
|
|
307
|
+
"""Generates portions (words and parens) extracted from text.
|
|
304
308
|
If reverse is True, process from tail to head.
|
|
305
309
|
"""
|
|
306
310
|
tokens = list(split_tokens(text))
|
|
@@ -345,10 +349,6 @@ def split_tokens(text, comment=True):
|
|
|
345
349
|
def _extract_words_from_tokens(tokens, reverse=False):
|
|
346
350
|
"""Extracts pythonic expressions from tokens.
|
|
347
351
|
|
|
348
|
-
Extraction continues until the parenthesis is closed
|
|
349
|
-
and the following token starts with a char in sep, where
|
|
350
|
-
the sep includes `@, ops, delims, and whitespaces, etc.
|
|
351
|
-
|
|
352
352
|
Returns:
|
|
353
353
|
A token list extracted including the parenthesis.
|
|
354
354
|
If reverse is True, the order of the tokens will be reversed.
|
|
@@ -372,45 +372,16 @@ def _extract_words_from_tokens(tokens, reverse=False):
|
|
|
372
372
|
elif not stack and c[0] in sep: # ok; starts with a char in sep
|
|
373
373
|
break
|
|
374
374
|
words.append(c)
|
|
375
|
-
|
|
375
|
+
if not stack: # ok
|
|
376
|
+
j += 1 # to remove current token
|
|
377
|
+
break
|
|
378
|
+
else:
|
|
379
|
+
## if stack: error("unclosed-paren")
|
|
376
380
|
j = None
|
|
377
381
|
del tokens[:j] # remove extracted tokens (except the last one)
|
|
378
382
|
return words
|
|
379
383
|
|
|
380
384
|
|
|
381
|
-
def _extract_paren_from_tokens(tokens, reverse=False):
|
|
382
|
-
"""Extracts parenthesis from tokens.
|
|
383
|
-
|
|
384
|
-
The first token must be a parenthesis.
|
|
385
|
-
Returns:
|
|
386
|
-
A token list extracted including the parenthesis,
|
|
387
|
-
or an empty list if the parenthesis is not closed.
|
|
388
|
-
If reverse is True, the order of the tokens will be reversed.
|
|
389
|
-
"""
|
|
390
|
-
p, q = "({[", ")}]"
|
|
391
|
-
if reverse:
|
|
392
|
-
p, q = q, p
|
|
393
|
-
stack = []
|
|
394
|
-
words = []
|
|
395
|
-
for j, c in enumerate(tokens):
|
|
396
|
-
if not c:
|
|
397
|
-
continue
|
|
398
|
-
if c in p:
|
|
399
|
-
stack.append(c)
|
|
400
|
-
elif c in q:
|
|
401
|
-
if not stack: # error("open-paren")
|
|
402
|
-
break
|
|
403
|
-
if c != q[p.index(stack.pop())]: # error("mismatch-paren")
|
|
404
|
-
break
|
|
405
|
-
elif j == 0:
|
|
406
|
-
break # first char is not paren
|
|
407
|
-
words.append(c)
|
|
408
|
-
if not stack: # ok
|
|
409
|
-
del tokens[:j+1] # remove extracted tokens
|
|
410
|
-
return words
|
|
411
|
-
return [] # error("unclosed-paren")
|
|
412
|
-
|
|
413
|
-
|
|
414
385
|
def walk_packages_no_import(path=None, prefix=''):
|
|
415
386
|
"""Yields module info recursively for all submodules on path.
|
|
416
387
|
If path is None, yields all top-level modules on sys.path.
|
|
@@ -979,26 +950,44 @@ class TreeList:
|
|
|
979
950
|
|
|
980
951
|
|
|
981
952
|
def get_fullargspec(f):
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
953
|
+
"""Get the names and default values of a callable object's parameters.
|
|
954
|
+
If the object is a built-in function, it tries to get argument
|
|
955
|
+
information from the docstring. If it fails, it returns None.
|
|
956
|
+
|
|
957
|
+
Returns:
|
|
958
|
+
args : a list of the parameter names.
|
|
959
|
+
varargs : the name of the * parameter or None.
|
|
960
|
+
varkwargs : the name of the ** parameter or None.
|
|
961
|
+
defaults : a dict mapping names from args to defaults.
|
|
962
|
+
kwonlyargs : a list of keyword-only parameter names.
|
|
963
|
+
kwonlydefaults : a dict mapping names from kwonlyargs to defaults.
|
|
964
|
+
|
|
965
|
+
Note:
|
|
966
|
+
`self` parameter is not reported for bound methods.
|
|
967
|
+
|
|
968
|
+
cf. inspect.getfullargspec
|
|
969
|
+
"""
|
|
970
|
+
argv = [] # <before /> 0:POSITIONAL_ONLY
|
|
971
|
+
# <before *> 1:POSITIONAL_OR_KEYWORD
|
|
972
|
+
varargs = None # <*args> 2:VAR_POSITIONAL
|
|
973
|
+
varkwargs = None # <**kwargs> 4:VAR_KEYWORD
|
|
974
|
+
defaults = {} #
|
|
975
|
+
kwonlyargs = [] # <after *> 3:KEYWORD_ONLY
|
|
976
|
+
kwonlydefaults = {} #
|
|
988
977
|
try:
|
|
989
978
|
sig = inspect.signature(f)
|
|
990
979
|
for k, v in sig.parameters.items():
|
|
991
|
-
if v.kind
|
|
980
|
+
if v.kind in (v.POSITIONAL_ONLY, v.POSITIONAL_OR_KEYWORD):
|
|
992
981
|
argv.append(k)
|
|
993
982
|
if v.default != v.empty:
|
|
994
983
|
defaults[k] = v.default
|
|
995
|
-
elif v.kind ==
|
|
984
|
+
elif v.kind == v.VAR_POSITIONAL:
|
|
996
985
|
varargs = k
|
|
997
|
-
elif v.kind ==
|
|
986
|
+
elif v.kind == v.KEYWORD_ONLY:
|
|
998
987
|
kwonlyargs.append(k)
|
|
999
988
|
if v.default != v.empty:
|
|
1000
989
|
kwonlydefaults[k] = v.default
|
|
1001
|
-
elif v.kind ==
|
|
990
|
+
elif v.kind == v.VAR_KEYWORD:
|
|
1002
991
|
varkwargs = k
|
|
1003
992
|
except ValueError:
|
|
1004
993
|
## Builtin functions don't have an argspec that we can get.
|
|
@@ -1009,19 +998,33 @@ def get_fullargspec(f):
|
|
|
1009
998
|
##
|
|
1010
999
|
## ...(details)...
|
|
1011
1000
|
## ```
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1001
|
+
doc = inspect.getdoc(f)
|
|
1002
|
+
for word in split_parts(doc or ''): # Search pattern for `func(argspec)`.
|
|
1003
|
+
if word.startswith('('):
|
|
1004
|
+
argspec = word[1:-1]
|
|
1005
|
+
break
|
|
1006
|
+
else:
|
|
1007
|
+
return None # no argument spec information
|
|
1008
|
+
if argspec:
|
|
1009
|
+
argparts = ['']
|
|
1010
|
+
for part in split_parts(argspec): # Separate argument parts with commas.
|
|
1011
|
+
if not part.strip():
|
|
1012
|
+
continue
|
|
1013
|
+
if part != ',':
|
|
1014
|
+
argparts[-1] += part
|
|
1015
|
+
else:
|
|
1016
|
+
argparts.append('')
|
|
1017
|
+
for v in argparts:
|
|
1018
|
+
m = re.match(r"(\w+):?", v) # argv + kwonlyargs
|
|
1020
1019
|
if m:
|
|
1021
1020
|
argv.append(m.group(1))
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1021
|
+
m = re.match(r"(\w+)(?::\w+)?=(.+)", v) # defaults + kwonlydefaults
|
|
1022
|
+
if m:
|
|
1023
|
+
defaults.update([m.groups()])
|
|
1024
|
+
elif v.startswith('**'): # <**kwargs>
|
|
1025
|
+
varkwargs = v[2:]
|
|
1026
|
+
elif v.startswith('*'): # <*args>
|
|
1027
|
+
varargs = v[1:]
|
|
1025
1028
|
return (argv, varargs, varkwargs,
|
|
1026
1029
|
defaults, kwonlyargs, kwonlydefaults)
|
|
1027
1030
|
|
|
@@ -1038,10 +1041,10 @@ def funcall(f, *args, doc=None, alias=None, **kwargs):
|
|
|
1038
1041
|
>>> Act1 = lambda *v,**kw: f(*(v+args), **(kwargs|kw))
|
|
1039
1042
|
>>> Act2 = lambda *v,**kw: f(*args, **(kwargs|kw))
|
|
1040
1043
|
|
|
1041
|
-
|
|
1044
|
+
`Act1` is returned (accepts event arguments) if event arguments
|
|
1042
1045
|
cannot be omitted or if there are any remaining arguments
|
|
1043
1046
|
that must be explicitly specified.
|
|
1044
|
-
Otherwise,
|
|
1047
|
+
Otherwise, `Act2` is returned (ignores event arguments).
|
|
1045
1048
|
"""
|
|
1046
1049
|
assert callable(f)
|
|
1047
1050
|
assert isinstance(doc, (str, type(None)))
|
|
@@ -1062,6 +1065,7 @@ def funcall(f, *args, doc=None, alias=None, **kwargs):
|
|
|
1062
1065
|
(argv, varargs, varkwargs, defaults,
|
|
1063
1066
|
kwonlyargs, kwonlydefaults) = get_fullargspec(f)
|
|
1064
1067
|
except Exception:
|
|
1068
|
+
warn(f"Failed to get the signature of {f}.")
|
|
1065
1069
|
return f
|
|
1066
1070
|
if not varargs:
|
|
1067
1071
|
N = len(argv)
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
mwx/__init__.py,sha256=pS7ZG8QKRypiFFiaWAq_opBB6I_1viZ0zUMk2TbjzE0,667
|
|
2
2
|
mwx/bookshelf.py,sha256=MXjrm_ryRGHvOFKu8wb10qz_oka70xW2yFbYjBMYfns,8140
|
|
3
3
|
mwx/controls.py,sha256=RssTROprNfgnRMiWVOoSSd8Fy0qwZ8DCrYM2f5Wgr4E,48610
|
|
4
|
-
mwx/framework.py,sha256=
|
|
5
|
-
mwx/graphman.py,sha256=
|
|
4
|
+
mwx/framework.py,sha256=hP2mhnYPOrSVFvA3CgoOR9-axWx_WLd83aXioUHodEk,76830
|
|
5
|
+
mwx/graphman.py,sha256=_8_DaG3qhhZByoh5wboyYQlAsm7GlPoR8wT-RNMx4Cw,70627
|
|
6
6
|
mwx/images.py,sha256=oxCn0P-emiWujSS2gUgU5TUnr5cPjix2jBcjOBDr24I,48701
|
|
7
7
|
mwx/matplot2.py,sha256=Htwegq6N5G7oKSRCuajik5Dixd93i8PKVbkL7Azy99M,33150
|
|
8
|
-
mwx/matplot2g.py,sha256=
|
|
8
|
+
mwx/matplot2g.py,sha256=4BBHlvfhg1796hu1nTCsTA82YRkZhwUnfcHCBf5ZGO8,65083
|
|
9
9
|
mwx/matplot2lg.py,sha256=cb0EZXivccDQu4oFj5ddSUF9pEE4f5UuFJJK2ELItww,27404
|
|
10
10
|
mwx/mgplt.py,sha256=8mXbHpCmm7lz3XbAxOg7IVC7DaSGBEby1UfTlMl9kjk,5604
|
|
11
|
-
mwx/nutshell.py,sha256=
|
|
11
|
+
mwx/nutshell.py,sha256=TNaZbMQcvSKDSHDnw3P8rpMM2yNG0HbVOej52L0EZgY,141903
|
|
12
12
|
mwx/testsuite.py,sha256=Zk75onPSEn2tf0swS3l-vIn6yTXGB7allIyvJsPHj20,1229
|
|
13
|
-
mwx/utilus.py,sha256=
|
|
13
|
+
mwx/utilus.py,sha256=ObXYWsDVn5DmjvwVQgP2HGAhrdxlDrwL7g9pMCDbU7U,38127
|
|
14
14
|
mwx/wxmon.py,sha256=yzWqrbY6LzpfRwQeytYUeqFhFuLVm_XEvrVAL_k0HBQ,12756
|
|
15
15
|
mwx/wxpdb.py,sha256=ih2iLcOgYnUX849YXO4niIYue6amuoG7nWdpr-X1jFw,18839
|
|
16
16
|
mwx/wxwil.py,sha256=hhyB1lPrF9ixeObxCOKQv0Theu-B-kpJg_yVU3EGSNg,5406
|
|
@@ -22,7 +22,7 @@ mwx/plugins/frame_listview.py,sha256=gowjQ-ARNonMkDSXkQgPKq4U9YBJ-vQ0jK2krBVOdCs
|
|
|
22
22
|
mwx/plugins/line_profile.py,sha256=zzm6_7lnAnNepLbh07ordp3nRWDFQJtu719ZVjrVf8s,819
|
|
23
23
|
mwx/py/__init__.py,sha256=xykgfOytOwNuvXsfkLoumFZSTN-iBsHOjczYXngjmUE,12
|
|
24
24
|
mwx/py/filling.py,sha256=fumUG1F5M9TL-Dfqni4G85uk7TmvnUunTbdcPDV0vfo,16857
|
|
25
|
-
mwxlib-1.4.
|
|
26
|
-
mwxlib-1.4.
|
|
27
|
-
mwxlib-1.4.
|
|
28
|
-
mwxlib-1.4.
|
|
25
|
+
mwxlib-1.4.6.dist-info/METADATA,sha256=hqiNPf-eNSU1H6H5huSCCToKcRvpXYWipmwzJc1r_xw,7433
|
|
26
|
+
mwxlib-1.4.6.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
|
27
|
+
mwxlib-1.4.6.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
|
|
28
|
+
mwxlib-1.4.6.dist-info/RECORD,,
|
|
File without changes
|