mwxlib 1.4.0__py3-none-any.whl → 1.4.5__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 +73 -68
- mwx/utilus.py +76 -72
- {mwxlib-1.4.0.dist-info → mwxlib-1.4.5.dist-info}/METADATA +1 -1
- {mwxlib-1.4.0.dist-info → mwxlib-1.4.5.dist-info}/RECORD +9 -9
- {mwxlib-1.4.0.dist-info → mwxlib-1.4.5.dist-info}/WHEEL +1 -1
- {mwxlib-1.4.0.dist-info → mwxlib-1.4.5.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.5"
|
|
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,10 +28,23 @@ 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
|
|
|
35
|
+
## Monkey-patch for wx.py.introspect.getRoot with terminator '('.
|
|
36
|
+
getRoot = introspect.getRoot
|
|
37
|
+
def _getRoot(command, terminator=None):
|
|
38
|
+
"""Return the rightmost root portion of an arbitrary Python command."""
|
|
39
|
+
if terminator == '(':
|
|
40
|
+
words = split_words(command, reverse=1)
|
|
41
|
+
for word in words:
|
|
42
|
+
if word == terminator:
|
|
43
|
+
return next(words, '')
|
|
44
|
+
return getRoot(command, terminator) # original
|
|
45
|
+
introspect.getRoot = _getRoot
|
|
46
|
+
|
|
47
|
+
|
|
35
48
|
## URL pattern (flag = re.M | re.A)
|
|
36
49
|
## url_re = r"https?://[\w/:%#$&?()~.=+-]+"
|
|
37
50
|
url_re = r"https?://[\w/:%#$&?!@~.,;=+-]+" # excluding ()
|
|
@@ -210,8 +223,8 @@ class AutoCompInterfaceMixin:
|
|
|
210
223
|
dispatcher.send(signal='Shell.calltip', sender=self, calltip=tip)
|
|
211
224
|
p = self.cpos
|
|
212
225
|
if argspec and insertcalltip:
|
|
213
|
-
self.AddText(argspec + ')')
|
|
214
|
-
self.
|
|
226
|
+
self.AddText(argspec + ')')
|
|
227
|
+
self.cpos = p # selection backward to the point
|
|
215
228
|
if tip:
|
|
216
229
|
## In case there isn't enough room, only go back to bol fallback.
|
|
217
230
|
tippos = max(self.bol, p - len(name) - 1)
|
|
@@ -269,7 +282,7 @@ class AutoCompInterfaceMixin:
|
|
|
269
282
|
self.anchor = q
|
|
270
283
|
with self.off_undocollection():
|
|
271
284
|
self.ReplaceSelection(word[n:])
|
|
272
|
-
self.cpos = p # backward
|
|
285
|
+
self.cpos = p # selection backward to the point
|
|
273
286
|
self.__comp_ind = j
|
|
274
287
|
except IndexError:
|
|
275
288
|
self.message("No completion words")
|
|
@@ -641,8 +654,8 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
|
|
|
641
654
|
self.IndicatorSetStyle(11, stc.STC_INDIC_STRAIGHTBOX)
|
|
642
655
|
self.IndicatorSetForeground(11, "yellow")
|
|
643
656
|
self.IndicatorSetUnder(11, True)
|
|
644
|
-
self.IndicatorSetAlpha(11, 0xe8)
|
|
645
|
-
self.IndicatorSetOutlineAlpha(11, 0)
|
|
657
|
+
## self.IndicatorSetAlpha(11, 0xe8)
|
|
658
|
+
## self.IndicatorSetOutlineAlpha(11, 0)
|
|
646
659
|
|
|
647
660
|
self.IndicatorSetStyle(2, stc.STC_INDIC_DOTS)
|
|
648
661
|
self.IndicatorSetForeground(2, "light gray")
|
|
@@ -863,7 +876,7 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
|
|
|
863
876
|
return sty
|
|
864
877
|
|
|
865
878
|
def get_char(self, pos):
|
|
866
|
-
"""Returns the character at the position."""
|
|
879
|
+
"""Returns the character at the given position."""
|
|
867
880
|
return chr(self.GetCharAt(pos))
|
|
868
881
|
|
|
869
882
|
def get_text(self, start, end):
|
|
@@ -944,10 +957,12 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
|
|
|
944
957
|
return topic
|
|
945
958
|
with self.save_excursion():
|
|
946
959
|
p = q = self.cpos
|
|
947
|
-
if self.get_char(p-1).
|
|
960
|
+
## if self.get_char(p-1).isidentifier():
|
|
961
|
+
if self.GetTextRange(self.PositionBefore(p), p).isidentifier():
|
|
948
962
|
self.WordLeft()
|
|
949
963
|
p = self.cpos
|
|
950
|
-
if self.get_char(q).
|
|
964
|
+
## if self.get_char(q).isidentifier():
|
|
965
|
+
if self.GetTextRange(q, self.PositionAfter(q)).isidentifier():
|
|
951
966
|
self.WordRightEnd()
|
|
952
967
|
q = self.cpos
|
|
953
968
|
return self.GetTextRange(p, q)
|
|
@@ -1376,32 +1391,34 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
|
|
|
1376
1391
|
def grep(self, pattern, flags=re.M):
|
|
1377
1392
|
yield from re.finditer(pattern.encode(), self.TextRaw, flags)
|
|
1378
1393
|
|
|
1379
|
-
def search_text(self, text):
|
|
1380
|
-
"""Yields
|
|
1381
|
-
word
|
|
1382
|
-
|
|
1394
|
+
def search_text(self, text, mode=True):
|
|
1395
|
+
"""Yields positions where `text` is found.
|
|
1396
|
+
If mode is True, search by word; otherwise, search by string.
|
|
1397
|
+
"""
|
|
1398
|
+
text = text.encode()
|
|
1383
1399
|
pos = -1
|
|
1400
|
+
p = re.compile(r"[a-zA-Z0-9_]")
|
|
1384
1401
|
while 1:
|
|
1385
|
-
pos =
|
|
1402
|
+
pos = self.TextRaw.find(text, pos+1)
|
|
1386
1403
|
if pos < 0:
|
|
1387
1404
|
break
|
|
1405
|
+
if mode and p.search(self.get_char(pos-1) + self.get_char(pos+len(text))):
|
|
1406
|
+
continue
|
|
1388
1407
|
yield pos
|
|
1389
1408
|
|
|
1390
|
-
def filter_text(self
|
|
1409
|
+
def filter_text(self):
|
|
1391
1410
|
"""Show indicators for the selected text."""
|
|
1392
1411
|
self.__itextlines = []
|
|
1393
1412
|
for i in (10, 11,):
|
|
1394
1413
|
self.SetIndicatorCurrent(i)
|
|
1395
1414
|
self.IndicatorClearRange(0, self.TextLength)
|
|
1396
|
-
|
|
1397
|
-
text = self.topic_at_caret
|
|
1415
|
+
text = self.topic_at_caret
|
|
1398
1416
|
if not text:
|
|
1399
1417
|
self.message("No words")
|
|
1400
1418
|
return
|
|
1401
|
-
|
|
1402
1419
|
lw = len(text.encode()) # for multi-byte string
|
|
1403
1420
|
lines = []
|
|
1404
|
-
for p in self.search_text(text):
|
|
1421
|
+
for p in self.search_text(text, mode=(not self.SelectedText)):
|
|
1405
1422
|
lines.append(self.LineFromPosition(p))
|
|
1406
1423
|
for i in (10, 11,):
|
|
1407
1424
|
self.SetIndicatorCurrent(i)
|
|
@@ -1833,12 +1850,8 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
1833
1850
|
self.message("")
|
|
1834
1851
|
|
|
1835
1852
|
def clear_autocomp(evt):
|
|
1836
|
-
## """Clear autocomp, selection, and message."""
|
|
1837
1853
|
if self.AutoCompActive():
|
|
1838
1854
|
self.AutoCompCancel()
|
|
1839
|
-
if self.CanEdit():
|
|
1840
|
-
with self.off_undocollection():
|
|
1841
|
-
self.ReplaceSelection("")
|
|
1842
1855
|
self.message("")
|
|
1843
1856
|
|
|
1844
1857
|
def fork(evt):
|
|
@@ -1882,7 +1895,7 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
1882
1895
|
'* pressed' : (0, clear_autocomp, fork),
|
|
1883
1896
|
'tab pressed' : (0, clear, skip),
|
|
1884
1897
|
'enter pressed' : (0, clear, skip),
|
|
1885
|
-
'escape pressed' : (0,
|
|
1898
|
+
'escape pressed' : (0, clear, skip),
|
|
1886
1899
|
'up pressed' : (2, skip, self.on_completion_backward),
|
|
1887
1900
|
'down pressed' : (2, skip, self.on_completion_forward),
|
|
1888
1901
|
'*left pressed' : (2, skip),
|
|
@@ -1909,7 +1922,7 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
1909
1922
|
'* pressed' : (0, clear_autocomp, fork),
|
|
1910
1923
|
'tab pressed' : (0, clear, skip),
|
|
1911
1924
|
'enter pressed' : (0, clear, skip),
|
|
1912
|
-
'escape pressed' : (0,
|
|
1925
|
+
'escape pressed' : (0, clear, skip),
|
|
1913
1926
|
'up pressed' : (3, skip, self.on_completion_backward),
|
|
1914
1927
|
'down pressed' : (3, skip, self.on_completion_forward),
|
|
1915
1928
|
'*left pressed' : (3, skip),
|
|
@@ -2099,8 +2112,15 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
2099
2112
|
if self.CallTipActive():
|
|
2100
2113
|
self.CallTipCancel()
|
|
2101
2114
|
|
|
2102
|
-
|
|
2103
|
-
|
|
2115
|
+
def _gen_text():
|
|
2116
|
+
text = self.SelectedText
|
|
2117
|
+
if text:
|
|
2118
|
+
yield text
|
|
2119
|
+
else:
|
|
2120
|
+
yield self.line_at_caret
|
|
2121
|
+
yield self.expr_at_caret
|
|
2122
|
+
|
|
2123
|
+
for text in _gen_text():
|
|
2104
2124
|
try:
|
|
2105
2125
|
obj = eval(text, self.globals, self.locals)
|
|
2106
2126
|
except Exception as e:
|
|
@@ -2108,7 +2128,8 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
2108
2128
|
else:
|
|
2109
2129
|
self.CallTipShow(self.cpos, pformat(obj))
|
|
2110
2130
|
self.message(text)
|
|
2111
|
-
|
|
2131
|
+
return
|
|
2132
|
+
if not text:
|
|
2112
2133
|
self.message("No words")
|
|
2113
2134
|
|
|
2114
2135
|
def exec_region(self):
|
|
@@ -2610,22 +2631,6 @@ class Interpreter(interpreter.Interpreter):
|
|
|
2610
2631
|
self.parent.handler('interp_error', v)
|
|
2611
2632
|
except AttributeError:
|
|
2612
2633
|
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
2634
|
|
|
2630
2635
|
|
|
2631
2636
|
class Nautilus(EditorInterface, Shell):
|
|
@@ -2796,12 +2801,8 @@ class Nautilus(EditorInterface, Shell):
|
|
|
2796
2801
|
self.message("")
|
|
2797
2802
|
|
|
2798
2803
|
def clear_autocomp(evt):
|
|
2799
|
-
## """Clear autocomp, selection, and message."""
|
|
2800
2804
|
if self.AutoCompActive():
|
|
2801
2805
|
self.AutoCompCancel()
|
|
2802
|
-
if self.CanEdit():
|
|
2803
|
-
with self.off_undocollection():
|
|
2804
|
-
self.ReplaceSelection("")
|
|
2805
2806
|
self.message("")
|
|
2806
2807
|
|
|
2807
2808
|
def fork(evt):
|
|
@@ -2900,7 +2901,7 @@ class Nautilus(EditorInterface, Shell):
|
|
|
2900
2901
|
'* pressed' : (0, clear_autocomp, fork),
|
|
2901
2902
|
'tab pressed' : (0, clear, skip),
|
|
2902
2903
|
'enter pressed' : (0, clear, skip),
|
|
2903
|
-
'escape pressed' : (0,
|
|
2904
|
+
'escape pressed' : (0, clear, skip),
|
|
2904
2905
|
'up pressed' : (2, skip, self.on_completion_backward),
|
|
2905
2906
|
'down pressed' : (2, skip, self.on_completion_forward),
|
|
2906
2907
|
'*left pressed' : (2, skip),
|
|
@@ -2928,7 +2929,7 @@ class Nautilus(EditorInterface, Shell):
|
|
|
2928
2929
|
'* pressed' : (0, clear_autocomp, fork),
|
|
2929
2930
|
'tab pressed' : (0, clear, skip),
|
|
2930
2931
|
'enter pressed' : (0, clear, skip),
|
|
2931
|
-
'escape pressed' : (0,
|
|
2932
|
+
'escape pressed' : (0, clear, skip),
|
|
2932
2933
|
'up pressed' : (3, skip, self.on_completion_backward),
|
|
2933
2934
|
'down pressed' : (3, skip, self.on_completion_forward),
|
|
2934
2935
|
'*left pressed' : (3, skip),
|
|
@@ -2956,7 +2957,7 @@ class Nautilus(EditorInterface, Shell):
|
|
|
2956
2957
|
'* pressed' : (0, clear_autocomp, fork),
|
|
2957
2958
|
'tab pressed' : (0, clear, skip),
|
|
2958
2959
|
'enter pressed' : (0, clear, skip),
|
|
2959
|
-
'escape pressed' : (0,
|
|
2960
|
+
'escape pressed' : (0, clear, skip),
|
|
2960
2961
|
'up pressed' : (4, skip, self.on_completion_backward),
|
|
2961
2962
|
'down pressed' : (4, skip, self.on_completion_forward),
|
|
2962
2963
|
'*left pressed' : (4, skip),
|
|
@@ -2984,7 +2985,7 @@ class Nautilus(EditorInterface, Shell):
|
|
|
2984
2985
|
'* pressed' : (0, clear_autocomp, fork),
|
|
2985
2986
|
'tab pressed' : (0, clear, skip),
|
|
2986
2987
|
'enter pressed' : (0, clear, skip),
|
|
2987
|
-
'escape pressed' : (0,
|
|
2988
|
+
'escape pressed' : (0, clear, skip),
|
|
2988
2989
|
'up pressed' : (5, skip, self.on_completion_backward),
|
|
2989
2990
|
'down pressed' : (5, skip, self.on_completion_forward),
|
|
2990
2991
|
'*left pressed' : (5, skip),
|
|
@@ -3135,7 +3136,7 @@ class Nautilus(EditorInterface, Shell):
|
|
|
3135
3136
|
rst = self.get_style(p)
|
|
3136
3137
|
if p == self.bolc:
|
|
3137
3138
|
self.ReplaceSelection('self') # replace [.] --> [self.]
|
|
3138
|
-
elif st in ('
|
|
3139
|
+
elif st in ('space', 'sep', 'lparen'):
|
|
3139
3140
|
self.ReplaceSelection('self')
|
|
3140
3141
|
elif st not in ('moji', 'word', 'rparen') or rst == 'word':
|
|
3141
3142
|
self.handler('quit', evt) # don't enter autocomp
|
|
@@ -3238,16 +3239,21 @@ class Nautilus(EditorInterface, Shell):
|
|
|
3238
3239
|
## func(a,b,c) @debug --> func,a,b,c @debug
|
|
3239
3240
|
if rhs in ("debug", "profile", "timeit"):
|
|
3240
3241
|
if lhs[-1] in ')':
|
|
3241
|
-
|
|
3242
|
+
R = next(split_parts(lhs, reverse=1))
|
|
3243
|
+
L = lhs[:-len(R)]
|
|
3242
3244
|
if not L:
|
|
3243
3245
|
lhs = "{!r}".format(R[1:-1])
|
|
3244
|
-
|
|
3246
|
+
else:
|
|
3245
3247
|
lhs = "{}, {}".format(L, R[1:-1])
|
|
3246
3248
|
|
|
3247
3249
|
## @(y1,,,yn) --> @partial(y1,,,yn)
|
|
3248
3250
|
elif rhs.startswith('('):
|
|
3249
3251
|
rhs = re.sub(r"^\((.*)\)", r"partial(\1)", rhs, flags=re.S)
|
|
3250
3252
|
|
|
3253
|
+
## obj @.method --> (obj).method
|
|
3254
|
+
elif rhs.startswith('.'):
|
|
3255
|
+
return self.magic_interpret([f"({lhs}){rhs}"] + rest)
|
|
3256
|
+
|
|
3251
3257
|
return self.magic_interpret([f"{rhs}({lhs})"] + rest)
|
|
3252
3258
|
|
|
3253
3259
|
if c == '`':
|
|
@@ -3516,7 +3522,7 @@ class Nautilus(EditorInterface, Shell):
|
|
|
3516
3522
|
def write(self, text, pos=None):
|
|
3517
3523
|
"""Display text in the shell.
|
|
3518
3524
|
|
|
3519
|
-
(override) Append text if it is writable at the position.
|
|
3525
|
+
(override) Append text if it is writable at the given position.
|
|
3520
3526
|
"""
|
|
3521
3527
|
if pos is not None:
|
|
3522
3528
|
if pos < 0:
|
|
@@ -3603,22 +3609,20 @@ class Nautilus(EditorInterface, Shell):
|
|
|
3603
3609
|
## Autocomp actions of the shell
|
|
3604
3610
|
## --------------------------------
|
|
3605
3611
|
|
|
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
3612
|
def eval_line(self):
|
|
3616
3613
|
"""Evaluate the selected word or line."""
|
|
3617
3614
|
if self.CallTipActive():
|
|
3618
3615
|
self.CallTipCancel()
|
|
3619
3616
|
|
|
3620
|
-
|
|
3621
|
-
|
|
3617
|
+
def _gen_text():
|
|
3618
|
+
text = self.SelectedText
|
|
3619
|
+
if text:
|
|
3620
|
+
yield text
|
|
3621
|
+
else:
|
|
3622
|
+
yield self.line_at_caret
|
|
3623
|
+
yield self.expr_at_caret
|
|
3624
|
+
|
|
3625
|
+
for text in _gen_text():
|
|
3622
3626
|
tokens = split_words(text)
|
|
3623
3627
|
try:
|
|
3624
3628
|
cmd = self.magic_interpret(tokens)
|
|
@@ -3629,7 +3633,8 @@ class Nautilus(EditorInterface, Shell):
|
|
|
3629
3633
|
else:
|
|
3630
3634
|
self.CallTipShow(self.cpos, pformat(obj))
|
|
3631
3635
|
self.message(cmd)
|
|
3632
|
-
|
|
3636
|
+
return
|
|
3637
|
+
if not text:
|
|
3633
3638
|
self.message("No words")
|
|
3634
3639
|
|
|
3635
3640
|
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
|
-
|
|
1001
|
+
doc = inspect.getdoc(f)
|
|
1002
|
+
if doc is None:
|
|
1003
|
+
return None
|
|
1004
|
+
m = re.match(r"(\w+)\s*\((.*?)\)", doc.strip(), re.S)
|
|
1005
|
+
if not m:
|
|
1006
|
+
return None
|
|
1007
|
+
else:
|
|
1017
1008
|
name, argspec = m.groups()
|
|
1018
|
-
|
|
1019
|
-
|
|
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=DO2VrF_SOS6Gdr22PZclHChWr2oRQfW__7-1xxr97Cc,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=4GDfGCHvHptpLqJIUVAfCMyI6V2KFcgji8S0PWMviL0,142385
|
|
12
12
|
mwx/testsuite.py,sha256=Zk75onPSEn2tf0swS3l-vIn6yTXGB7allIyvJsPHj20,1229
|
|
13
|
-
mwx/utilus.py,sha256=
|
|
13
|
+
mwx/utilus.py,sha256=iAqtDbkVuFsSuS71leUd-mHH0ETRQ3GLnII7O2wcw3I,38065
|
|
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.5.dist-info/METADATA,sha256=004S_ou1NJHL8BynaX391SwQ5vamthk4oifMNz8yUrE,7433
|
|
26
|
+
mwxlib-1.4.5.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
|
27
|
+
mwxlib-1.4.5.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
|
|
28
|
+
mwxlib-1.4.5.dist-info/RECORD,,
|
|
File without changes
|