mwxlib 0.96.0__py3-none-any.whl → 0.96.4__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/bookshelf.py +1 -0
- mwx/controls.py +37 -34
- mwx/framework.py +7 -17
- mwx/graphman.py +43 -27
- mwx/matplot2g.py +25 -35
- mwx/matplot2lg.py +1 -1
- mwx/nutshell.py +7 -8
- mwx/plugins/frame_listview.py +33 -29
- mwx/utilus.py +29 -28
- mwx/wxmon.py +3 -5
- mwx/wxwil.py +1 -1
- {mwxlib-0.96.0.dist-info → mwxlib-0.96.4.dist-info}/METADATA +1 -1
- mwxlib-0.96.4.dist-info/RECORD +28 -0
- {mwxlib-0.96.0.dist-info → mwxlib-0.96.4.dist-info}/WHEEL +1 -1
- mwxlib-0.96.0.dist-info/RECORD +0 -28
- {mwxlib-0.96.0.dist-info → mwxlib-0.96.4.dist-info}/LICENSE +0 -0
- {mwxlib-0.96.0.dist-info → mwxlib-0.96.4.dist-info}/top_level.txt +0 -0
mwx/bookshelf.py
CHANGED
mwx/controls.py
CHANGED
|
@@ -8,11 +8,12 @@ import wx.lib.scrolledpanel as scrolled
|
|
|
8
8
|
|
|
9
9
|
from . import images
|
|
10
10
|
from .utilus import SSM
|
|
11
|
+
from .utilus import warn
|
|
11
12
|
from .utilus import funcall as _F
|
|
12
13
|
from .framework import pack, Menu
|
|
13
14
|
|
|
14
15
|
import numpy as np
|
|
15
|
-
from numpy import nan, inf
|
|
16
|
+
from numpy import nan, inf # noqa: necessary to eval
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
def _Tip(*tips):
|
|
@@ -83,12 +84,12 @@ class Param(object):
|
|
|
83
84
|
def __len__(self):
|
|
84
85
|
return len(self.range)
|
|
85
86
|
|
|
86
|
-
@wx.deprecatedMsg("Use `Param.callback.bind` instead.") #<DeprecationWarning>
|
|
87
87
|
def bind(self, action=None, target='control'):
|
|
88
|
+
warn("Use `Param.callback.bind` instead.", DeprecationWarning)
|
|
88
89
|
return self.callback.bind(target, action)
|
|
89
90
|
|
|
90
|
-
@wx.deprecatedMsg("Use `Param.callback.unbind` instead.") #<DeprecationWarning>
|
|
91
91
|
def unbind(self, action=None, target='control'):
|
|
92
|
+
warn("Use `Param.callback.unbind` instead.", DeprecationWarning)
|
|
92
93
|
return self.callback.unbind(target, action)
|
|
93
94
|
|
|
94
95
|
def reset(self, v=None, backcall=True):
|
|
@@ -97,10 +98,8 @@ class Param(object):
|
|
|
97
98
|
v = self.std_value
|
|
98
99
|
if v is None:
|
|
99
100
|
return
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
elif isinstance(v, str):
|
|
103
|
-
v = self.__eval(v.replace(',', '')) # eliminates commas
|
|
101
|
+
if isinstance(v, str):
|
|
102
|
+
v = self.__eval(v.replace(',', '')) # eliminates commas; includes nan, inf
|
|
104
103
|
self._set_value(v)
|
|
105
104
|
if backcall:
|
|
106
105
|
self.callback('control', self)
|
|
@@ -111,7 +110,8 @@ class Param(object):
|
|
|
111
110
|
"""
|
|
112
111
|
if v is None:
|
|
113
112
|
v = nan
|
|
114
|
-
|
|
113
|
+
|
|
114
|
+
if np.isnan(v) or np.isinf(v):
|
|
115
115
|
self.__value = v
|
|
116
116
|
for knob in self.knobs:
|
|
117
117
|
knob.update_ctrl(None, notify=False)
|
|
@@ -185,7 +185,7 @@ class Param(object):
|
|
|
185
185
|
@offset.setter
|
|
186
186
|
def offset(self, v):
|
|
187
187
|
if self.std_value is not None:
|
|
188
|
-
if
|
|
188
|
+
if not np.isnan(v):
|
|
189
189
|
v += self.std_value
|
|
190
190
|
self._set_value(v)
|
|
191
191
|
|
|
@@ -253,6 +253,7 @@ class LParam(Param):
|
|
|
253
253
|
|
|
254
254
|
@range.setter
|
|
255
255
|
def range(self, v):
|
|
256
|
+
assert v is None or len(v) <= 3, "The range must be of length <= 3 or None"
|
|
256
257
|
if v is None:
|
|
257
258
|
v = (0, 0)
|
|
258
259
|
self.__min = v[0]
|
|
@@ -266,7 +267,8 @@ class LParam(Param):
|
|
|
266
267
|
"""A knob index -> value
|
|
267
268
|
Returns -1 if the value is nan or inf.
|
|
268
269
|
"""
|
|
269
|
-
|
|
270
|
+
v = self.value
|
|
271
|
+
if np.isnan(v) or np.isinf(v):
|
|
270
272
|
return -1
|
|
271
273
|
return int(round((self.value - self.min) / self.step))
|
|
272
274
|
|
|
@@ -294,7 +296,6 @@ class Knob(wx.Panel):
|
|
|
294
296
|
None -> static text (default)
|
|
295
297
|
chkbox -> label with check box
|
|
296
298
|
button -> label with flat button
|
|
297
|
-
editable: textctrl is editable or readonly
|
|
298
299
|
cw : width of ctrl
|
|
299
300
|
lw : width of label
|
|
300
301
|
tw : width of textbox
|
|
@@ -319,7 +320,7 @@ class Knob(wx.Panel):
|
|
|
319
320
|
wx.Panel.__init__(self, parent, **kwargs)
|
|
320
321
|
|
|
321
322
|
assert isinstance(param, Param),\
|
|
322
|
-
"Argument `param` must be an instance of Param
|
|
323
|
+
"Argument `param` must be an instance of Param"
|
|
323
324
|
|
|
324
325
|
self.__bit = 1
|
|
325
326
|
self.__par = param
|
|
@@ -354,23 +355,22 @@ class Knob(wx.Panel):
|
|
|
354
355
|
else:
|
|
355
356
|
raise Exception("unknown style: {!r}".format(style))
|
|
356
357
|
|
|
357
|
-
self.label.Enable(lw)
|
|
358
358
|
self.label.Bind(wx.EVT_MIDDLE_DOWN, lambda v: self.__par.reset())
|
|
359
|
-
|
|
360
359
|
self.label.SetToolTip(self.__par._tooltip)
|
|
360
|
+
self.label.Enable(lw) # skip focus
|
|
361
361
|
|
|
362
|
-
if editable:
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
362
|
+
if not editable:
|
|
363
|
+
warn("Knob option `editable` is deprecated.", DeprecationWarning)
|
|
364
|
+
|
|
365
|
+
self.text = wx.TextCtrl(self, size=(tw,h), style=wx.TE_PROCESS_ENTER)
|
|
366
|
+
self.text.Bind(wx.EVT_TEXT_ENTER, self.OnTextEnter)
|
|
367
|
+
self.text.Bind(wx.EVT_KILL_FOCUS, self.OnTextExit)
|
|
368
|
+
self.text.Bind(wx.EVT_KEY_DOWN, self.OnTextKeyDown)
|
|
369
|
+
self.text.Bind(wx.EVT_KEY_UP, self.OnTextKeyUp)
|
|
370
|
+
self.text.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
|
|
371
|
+
self.text.Bind(wx.EVT_MIDDLE_DOWN, lambda v: self.__par.reset())
|
|
372
372
|
|
|
373
|
-
self.text.Enable(tw)
|
|
373
|
+
self.text.Enable(tw) # skip focus
|
|
374
374
|
|
|
375
375
|
if type == 'slider':
|
|
376
376
|
self.ctrl = wx.Slider(self, size=(cw,h), style=wx.SL_HORIZONTAL)
|
|
@@ -404,8 +404,8 @@ class Knob(wx.Panel):
|
|
|
404
404
|
else:
|
|
405
405
|
raise Exception("unknown type: {!r}".format(type))
|
|
406
406
|
|
|
407
|
-
self.ctrl.Enable(cw != 0)
|
|
408
407
|
self.ctrl.Bind(wx.EVT_MIDDLE_DOWN, lambda v: self.__par.reset())
|
|
408
|
+
self.ctrl.Enable(cw) # skip focus
|
|
409
409
|
|
|
410
410
|
c = (cw and type != 'vspin')
|
|
411
411
|
self.SetSizer(
|
|
@@ -425,6 +425,7 @@ class Knob(wx.Panel):
|
|
|
425
425
|
evt.Skip()
|
|
426
426
|
|
|
427
427
|
def update_range(self):
|
|
428
|
+
"""Called when range is being changed (internal use only)."""
|
|
428
429
|
v = self.__par
|
|
429
430
|
if isinstance(self.ctrl, wx.Choice): #<wx.Choice>
|
|
430
431
|
items = [v.__str__(x) for x in v.range]
|
|
@@ -435,6 +436,7 @@ class Knob(wx.Panel):
|
|
|
435
436
|
self.ctrl.SetRange(0, len(v)-1) #<wx.Slider> <wx.SpinButton>
|
|
436
437
|
|
|
437
438
|
def update_label(self):
|
|
439
|
+
"""Called when label is being changed (internal use only)."""
|
|
438
440
|
v = self.__par
|
|
439
441
|
if isinstance(self.label, wx.CheckBox):
|
|
440
442
|
self.label.SetValue(v.check)
|
|
@@ -445,6 +447,7 @@ class Knob(wx.Panel):
|
|
|
445
447
|
self.label.Refresh()
|
|
446
448
|
|
|
447
449
|
def update_ctrl(self, valid=True, notify=False):
|
|
450
|
+
"""Called when value is being changed (internal use only)."""
|
|
448
451
|
v = self.__par
|
|
449
452
|
try:
|
|
450
453
|
j = v.index
|
|
@@ -765,32 +768,32 @@ class Clipboard:
|
|
|
765
768
|
The clipboard data cannot be transferred unless wx.Frame exists.
|
|
766
769
|
"""
|
|
767
770
|
@staticmethod
|
|
768
|
-
def read(verbose=
|
|
771
|
+
def read(verbose=False):
|
|
769
772
|
do = wx.TextDataObject()
|
|
770
773
|
if wx.TheClipboard.Open():
|
|
771
774
|
wx.TheClipboard.GetData(do)
|
|
772
775
|
wx.TheClipboard.Close()
|
|
773
776
|
text = do.GetText()
|
|
774
777
|
if verbose:
|
|
775
|
-
print("From clipboard
|
|
778
|
+
print(f"From clipboard:\n{text}")
|
|
776
779
|
return text
|
|
777
780
|
else:
|
|
778
781
|
print("- Unable to open clipboard.")
|
|
779
782
|
|
|
780
783
|
@staticmethod
|
|
781
|
-
def write(text, verbose=
|
|
784
|
+
def write(text, verbose=False):
|
|
782
785
|
do = wx.TextDataObject(str(text))
|
|
783
786
|
if wx.TheClipboard.Open():
|
|
784
787
|
wx.TheClipboard.SetData(do)
|
|
785
788
|
wx.TheClipboard.Flush()
|
|
786
789
|
wx.TheClipboard.Close()
|
|
787
790
|
if verbose:
|
|
788
|
-
print("To clipboard
|
|
791
|
+
print(f"To clipboard:\n{text}")
|
|
789
792
|
else:
|
|
790
793
|
print("- Unable to open clipboard.")
|
|
791
794
|
|
|
792
795
|
@staticmethod
|
|
793
|
-
def imread(verbose=
|
|
796
|
+
def imread(verbose=False):
|
|
794
797
|
do = wx.BitmapDataObject()
|
|
795
798
|
if wx.TheClipboard.Open():
|
|
796
799
|
wx.TheClipboard.GetData(do)
|
|
@@ -804,14 +807,14 @@ class Clipboard:
|
|
|
804
807
|
img = bmp.ConvertToImage()
|
|
805
808
|
buf = np.array(img.GetDataBuffer()) # do copy, don't ref
|
|
806
809
|
if verbose:
|
|
807
|
-
print("From clipboard {:.1f} Mb data".format(buf.nbytes/1e6))
|
|
810
|
+
print("From clipboard: {:.1f} Mb data read.".format(buf.nbytes/1e6))
|
|
808
811
|
w, h = img.GetSize()
|
|
809
812
|
return buf.reshape(h, w, 3)
|
|
810
813
|
except Exception:
|
|
811
814
|
print("- The contents of the clipboard are not images.")
|
|
812
815
|
|
|
813
816
|
@staticmethod
|
|
814
|
-
def imwrite(buf, verbose=
|
|
817
|
+
def imwrite(buf, verbose=False):
|
|
815
818
|
try:
|
|
816
819
|
## Convert buf --> bmp
|
|
817
820
|
h, w = buf.shape[:2]
|
|
@@ -829,7 +832,7 @@ class Clipboard:
|
|
|
829
832
|
wx.TheClipboard.Flush()
|
|
830
833
|
wx.TheClipboard.Close()
|
|
831
834
|
if verbose:
|
|
832
|
-
print("To clipboard: {:.1f} Mb data".format(buf.nbytes/1e6))
|
|
835
|
+
print("To clipboard: {:.1f} Mb data written.".format(buf.nbytes/1e6))
|
|
833
836
|
else:
|
|
834
837
|
print("- Unable to open clipboard.")
|
|
835
838
|
|
mwx/framework.py
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
#! python3
|
|
2
2
|
"""mwxlib framework.
|
|
3
3
|
"""
|
|
4
|
-
__version__ = "0.96.
|
|
4
|
+
__version__ = "0.96.4"
|
|
5
5
|
__author__ = "Kazuya O'moto <komoto@jeol.co.jp>"
|
|
6
6
|
|
|
7
7
|
from functools import wraps, partial
|
|
8
8
|
from importlib import reload
|
|
9
|
-
from contextlib import contextmanager
|
|
10
9
|
import traceback
|
|
11
|
-
import warnings
|
|
12
10
|
import builtins
|
|
13
11
|
import datetime
|
|
14
12
|
import textwrap
|
|
@@ -21,8 +19,8 @@ from wx import stc
|
|
|
21
19
|
from wx.py import dispatcher
|
|
22
20
|
|
|
23
21
|
from .utilus import funcall as _F
|
|
22
|
+
from .utilus import get_rootpath, ignore, warn # noqa
|
|
24
23
|
from .utilus import FSM, TreeList, apropos, typename, where, mro, pp
|
|
25
|
-
from .utilus import get_rootpath
|
|
26
24
|
|
|
27
25
|
|
|
28
26
|
def deb(target=None, loop=True, locals=None, **kwargs):
|
|
@@ -232,7 +230,7 @@ class KeyCtrlInterfaceMixin:
|
|
|
232
230
|
state = self.handler.default_state
|
|
233
231
|
event = keymap + ' pressed'
|
|
234
232
|
|
|
235
|
-
assert state is not None, "Don't make keymap for None:state
|
|
233
|
+
assert state is not None, "Don't make keymap for None:state"
|
|
236
234
|
|
|
237
235
|
self.handler.update({ # DNA<KeyCtrlInterfaceMixin>
|
|
238
236
|
state : {
|
|
@@ -290,14 +288,12 @@ class KeyCtrlInterfaceMixin:
|
|
|
290
288
|
key += ' pressed'
|
|
291
289
|
|
|
292
290
|
if map not in self.handler:
|
|
293
|
-
|
|
294
|
-
stacklevel=2)
|
|
291
|
+
warn(f"New map to define_key {keymap!r} in {self}.")
|
|
295
292
|
self.make_keymap(map) # make new keymap
|
|
296
293
|
|
|
297
294
|
transaction = self.handler[map].get(key, [state])
|
|
298
295
|
if len(transaction) > 1:
|
|
299
|
-
|
|
300
|
-
stacklevel=2)
|
|
296
|
+
warn(f"Duplicate define_key {keymap!r} in {self}.")
|
|
301
297
|
|
|
302
298
|
if action is None:
|
|
303
299
|
self.handler[map].pop(key, None) # cf. undefine_key
|
|
@@ -322,10 +318,6 @@ class CtrlInterface(KeyCtrlInterfaceMixin):
|
|
|
322
318
|
handler = property(lambda self: self.__handler)
|
|
323
319
|
|
|
324
320
|
def __init__(self):
|
|
325
|
-
if hasattr(self, 'handler'):
|
|
326
|
-
warnings.warn(f"Duplicate iniheritance of CtrlInterface by {self}.",
|
|
327
|
-
stacklevel=2)
|
|
328
|
-
return
|
|
329
321
|
self.__key = ''
|
|
330
322
|
self.__button = ''
|
|
331
323
|
self.__isDragging = False
|
|
@@ -629,8 +621,7 @@ class MenuBar(wx.MenuBar, TreeList):
|
|
|
629
621
|
Call when the menulist is changed.
|
|
630
622
|
"""
|
|
631
623
|
if not self.Parent:
|
|
632
|
-
|
|
633
|
-
stacklevel=2)
|
|
624
|
+
warn(f"No parents bound to {self}.")
|
|
634
625
|
return
|
|
635
626
|
|
|
636
627
|
menu = self.getmenu(key)
|
|
@@ -657,8 +648,7 @@ class MenuBar(wx.MenuBar, TreeList):
|
|
|
657
648
|
Call when the menulist is changed.
|
|
658
649
|
"""
|
|
659
650
|
if not self.Parent:
|
|
660
|
-
|
|
661
|
-
stacklevel=2)
|
|
651
|
+
warn(f"No parents bound to {self}.")
|
|
662
652
|
return
|
|
663
653
|
|
|
664
654
|
for j in range(self.GetMenuCount()): # remove and del all top-level menu
|
mwx/graphman.py
CHANGED
|
@@ -9,7 +9,6 @@ from bdb import BdbQuit
|
|
|
9
9
|
import subprocess
|
|
10
10
|
import threading
|
|
11
11
|
import traceback
|
|
12
|
-
import warnings
|
|
13
12
|
import inspect
|
|
14
13
|
import sys
|
|
15
14
|
import os
|
|
@@ -26,6 +25,7 @@ from PIL import Image
|
|
|
26
25
|
from PIL.TiffImagePlugin import TiffImageFile
|
|
27
26
|
|
|
28
27
|
from . import framework as mwx
|
|
28
|
+
from .utilus import ignore, warn
|
|
29
29
|
from .utilus import funcall as _F
|
|
30
30
|
from .controls import ControlPanel, Icon
|
|
31
31
|
from .framework import CtrlInterface, AuiNotebook, Menu, FSM
|
|
@@ -310,7 +310,10 @@ class LayerInterface(CtrlInterface):
|
|
|
310
310
|
self.__artists.remove(art)
|
|
311
311
|
|
|
312
312
|
def __init__(self, parent, session=None):
|
|
313
|
-
|
|
313
|
+
if hasattr(self, 'handler'):
|
|
314
|
+
warn(f"Duplicate iniheritance of CtrlInterface by {self}.")
|
|
315
|
+
else:
|
|
316
|
+
CtrlInterface.__init__(self)
|
|
314
317
|
|
|
315
318
|
self.parent = parent
|
|
316
319
|
self.__artists = []
|
|
@@ -855,15 +858,14 @@ class Frame(mwx.Frame):
|
|
|
855
858
|
|
|
856
859
|
Editor = "notepad"
|
|
857
860
|
|
|
861
|
+
@ignore(ResourceWarning)
|
|
858
862
|
def edit(self, fn):
|
|
859
863
|
if hasattr(fn, '__file__'):
|
|
860
864
|
name, _ = os.path.splitext(fn.__file__)
|
|
861
865
|
fn = name + '.py'
|
|
862
866
|
cmd = '{} "{}"'.format(self.Editor, fn)
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
subprocess.Popen(cmd)
|
|
866
|
-
self.message(cmd)
|
|
867
|
+
subprocess.Popen(cmd)
|
|
868
|
+
self.message(cmd)
|
|
867
869
|
|
|
868
870
|
def set_title(self, frame):
|
|
869
871
|
ssn = os.path.basename(self.session_file or '--')
|
|
@@ -887,6 +889,20 @@ class Frame(mwx.Frame):
|
|
|
887
889
|
elif ret == wx.ID_CANCEL:
|
|
888
890
|
evt.Veto()
|
|
889
891
|
return
|
|
892
|
+
for name in self.plugins:
|
|
893
|
+
plug = self.get_plug(name)
|
|
894
|
+
if plug.thread and plug.thread.active:
|
|
895
|
+
if wx.MessageBox( # Confirm thread close.
|
|
896
|
+
"The thread is running.\n\n"
|
|
897
|
+
"Enter [q]uit to exit before closing.\n"
|
|
898
|
+
"Continue closing?",
|
|
899
|
+
"Close {!r}".format(plug.Name),
|
|
900
|
+
style=wx.YES_NO|wx.ICON_INFORMATION) != wx.YES:
|
|
901
|
+
self.message("The close has been canceled.")
|
|
902
|
+
evt.Veto()
|
|
903
|
+
return
|
|
904
|
+
self.Quit()
|
|
905
|
+
break
|
|
890
906
|
for frame in self.graph.all_frames:
|
|
891
907
|
if frame.pathname is None:
|
|
892
908
|
if wx.MessageBox( # Confirm close.
|
|
@@ -914,11 +930,9 @@ class Frame(mwx.Frame):
|
|
|
914
930
|
Args:
|
|
915
931
|
name : str or plug object.
|
|
916
932
|
"""
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
name = plug.category or
|
|
920
|
-
elif isinstance(name, LayerInterface):
|
|
921
|
-
name = name.category or name
|
|
933
|
+
plug = self.get_plug(name)
|
|
934
|
+
if plug:
|
|
935
|
+
name = plug.category or plug
|
|
922
936
|
if name:
|
|
923
937
|
return self._mgr.GetPane(name)
|
|
924
938
|
|
|
@@ -953,6 +967,7 @@ class Frame(mwx.Frame):
|
|
|
953
967
|
## Note: We need to distinguish cases whether:
|
|
954
968
|
## - pane.window is AuiNotebook or normal Panel,
|
|
955
969
|
## - pane.window is floating (win.Parent is AuiFloatingFrame) or docked.
|
|
970
|
+
|
|
956
971
|
plug = self.get_plug(name) # -> None if pane.window is a Graph
|
|
957
972
|
win = pane.window # -> Window (plug / notebook / Graph)
|
|
958
973
|
try:
|
|
@@ -1029,7 +1044,7 @@ class Frame(mwx.Frame):
|
|
|
1029
1044
|
win.handler('page_closed', win)
|
|
1030
1045
|
|
|
1031
1046
|
## --------------------------------
|
|
1032
|
-
## Plugin
|
|
1047
|
+
## Plugin <Layer> interface
|
|
1033
1048
|
## --------------------------------
|
|
1034
1049
|
plugins = property(lambda self: self.__plugins)
|
|
1035
1050
|
|
|
@@ -1063,15 +1078,14 @@ class Frame(mwx.Frame):
|
|
|
1063
1078
|
|
|
1064
1079
|
@staticmethod
|
|
1065
1080
|
def register(cls, module=None):
|
|
1066
|
-
"""Register dummy plug; Add module.Plugin
|
|
1081
|
+
"""Register dummy plug; Add module.Plugin <Layer>.
|
|
1067
1082
|
"""
|
|
1068
1083
|
if not module:
|
|
1069
1084
|
module = inspect.getmodule(cls) # rebase module or __main__
|
|
1070
1085
|
|
|
1071
1086
|
if issubclass(cls, LayerInterface):
|
|
1072
1087
|
cls.__module__ = module.__name__ # __main__ to module
|
|
1073
|
-
|
|
1074
|
-
stacklevel=2)
|
|
1088
|
+
warn(f"Duplicate iniheritance of LayerInterface by {cls}.")
|
|
1075
1089
|
module.Plugin = cls
|
|
1076
1090
|
return cls
|
|
1077
1091
|
|
|
@@ -1121,8 +1135,7 @@ class Frame(mwx.Frame):
|
|
|
1121
1135
|
## the module must have a class `Plugin`.
|
|
1122
1136
|
if not hasattr(module, 'Plugin'):
|
|
1123
1137
|
if isinstance(root, type):
|
|
1124
|
-
|
|
1125
|
-
stacklevel=3)
|
|
1138
|
+
warn(f"Use dummy plug for debugging {name!r}.")
|
|
1126
1139
|
module.__dummy_plug__ = root
|
|
1127
1140
|
self.register(root, module)
|
|
1128
1141
|
else:
|
|
@@ -1420,7 +1433,7 @@ class Frame(mwx.Frame):
|
|
|
1420
1433
|
"ALL files (*.*)|*.*",
|
|
1421
1434
|
style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST) as dlg:
|
|
1422
1435
|
if dlg.ShowModal() != wx.ID_OK:
|
|
1423
|
-
return
|
|
1436
|
+
return None
|
|
1424
1437
|
filename = dlg.Path
|
|
1425
1438
|
|
|
1426
1439
|
res, mis = self.read_attributes(filename)
|
|
@@ -1445,7 +1458,7 @@ class Frame(mwx.Frame):
|
|
|
1445
1458
|
if not frames:
|
|
1446
1459
|
frames = self.selected_view.all_frames
|
|
1447
1460
|
if not frames:
|
|
1448
|
-
return
|
|
1461
|
+
return None
|
|
1449
1462
|
|
|
1450
1463
|
if not filename:
|
|
1451
1464
|
fn = next((x.pathname for x in frames if x.pathname), '')
|
|
@@ -1455,7 +1468,7 @@ class Frame(mwx.Frame):
|
|
|
1455
1468
|
wildcard="Index (*.index)|*.index",
|
|
1456
1469
|
style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) as dlg:
|
|
1457
1470
|
if dlg.ShowModal() != wx.ID_OK:
|
|
1458
|
-
return
|
|
1471
|
+
return None
|
|
1459
1472
|
filename = dlg.Path
|
|
1460
1473
|
|
|
1461
1474
|
savedir = os.path.dirname(filename)
|
|
@@ -1608,6 +1621,7 @@ class Frame(mwx.Frame):
|
|
|
1608
1621
|
os.remove(path)
|
|
1609
1622
|
raise
|
|
1610
1623
|
|
|
1624
|
+
@ignore(ResourceWarning)
|
|
1611
1625
|
def load_buffer(self, paths=None, view=None):
|
|
1612
1626
|
"""Load buffers from paths to the view window.
|
|
1613
1627
|
|
|
@@ -1625,11 +1639,11 @@ class Frame(mwx.Frame):
|
|
|
1625
1639
|
style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST
|
|
1626
1640
|
|wx.FD_MULTIPLE) as dlg:
|
|
1627
1641
|
if dlg.ShowModal() != wx.ID_OK:
|
|
1628
|
-
return
|
|
1642
|
+
return None
|
|
1629
1643
|
paths = dlg.Paths
|
|
1644
|
+
frames = []
|
|
1645
|
+
frame = None
|
|
1630
1646
|
try:
|
|
1631
|
-
frames = []
|
|
1632
|
-
frame = None
|
|
1633
1647
|
for i, path in enumerate(paths):
|
|
1634
1648
|
fn = os.path.basename(path)
|
|
1635
1649
|
self.message("Loading {!r} ({} of {})...".format(fn, i+1, len(paths)))
|
|
@@ -1672,7 +1686,7 @@ class Frame(mwx.Frame):
|
|
|
1672
1686
|
if not frame:
|
|
1673
1687
|
frame = self.selected_view.frame
|
|
1674
1688
|
if not frame:
|
|
1675
|
-
return
|
|
1689
|
+
return None
|
|
1676
1690
|
|
|
1677
1691
|
if not path:
|
|
1678
1692
|
with wx.FileDialog(self, "Save buffer as",
|
|
@@ -1680,7 +1694,7 @@ class Frame(mwx.Frame):
|
|
|
1680
1694
|
wildcard='|'.join(self.wildcards),
|
|
1681
1695
|
style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) as dlg:
|
|
1682
1696
|
if dlg.ShowModal() != wx.ID_OK:
|
|
1683
|
-
return
|
|
1697
|
+
return None
|
|
1684
1698
|
path = dlg.Path
|
|
1685
1699
|
try:
|
|
1686
1700
|
name = os.path.basename(path)
|
|
@@ -1700,13 +1714,14 @@ class Frame(mwx.Frame):
|
|
|
1700
1714
|
except Exception as e:
|
|
1701
1715
|
self.message("\b failed.")
|
|
1702
1716
|
wx.MessageBox(str(e), style=wx.ICON_ERROR)
|
|
1717
|
+
return None
|
|
1703
1718
|
|
|
1704
1719
|
def save_buffers_as_tiffs(self, path=None, frames=None):
|
|
1705
1720
|
"""Export buffers to a file as a multi-page tiff."""
|
|
1706
1721
|
if not frames:
|
|
1707
1722
|
frames = self.selected_view.all_frames
|
|
1708
1723
|
if not frames:
|
|
1709
|
-
return
|
|
1724
|
+
return None
|
|
1710
1725
|
|
|
1711
1726
|
if not path:
|
|
1712
1727
|
with wx.FileDialog(self, "Save frames as stack-tiff",
|
|
@@ -1714,7 +1729,7 @@ class Frame(mwx.Frame):
|
|
|
1714
1729
|
wildcard="TIF file (*.tif)|*.tif",
|
|
1715
1730
|
style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) as dlg:
|
|
1716
1731
|
if dlg.ShowModal() != wx.ID_OK:
|
|
1717
|
-
return
|
|
1732
|
+
return None
|
|
1718
1733
|
path = dlg.Path
|
|
1719
1734
|
try:
|
|
1720
1735
|
name = os.path.basename(path)
|
|
@@ -1733,6 +1748,7 @@ class Frame(mwx.Frame):
|
|
|
1733
1748
|
except Exception as e:
|
|
1734
1749
|
self.message("\b failed.")
|
|
1735
1750
|
wx.MessageBox(str(e), style=wx.ICON_ERROR)
|
|
1751
|
+
return False
|
|
1736
1752
|
finally:
|
|
1737
1753
|
del busy
|
|
1738
1754
|
|
mwx/matplot2g.py
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
"""mwxlib graph plot for images.
|
|
3
3
|
"""
|
|
4
4
|
import traceback
|
|
5
|
-
import warnings
|
|
6
5
|
import wx
|
|
7
6
|
|
|
8
7
|
from matplotlib import cm
|
|
@@ -10,11 +9,12 @@ from matplotlib import patches
|
|
|
10
9
|
from PIL import Image
|
|
11
10
|
import cv2
|
|
12
11
|
import numpy as np
|
|
13
|
-
from numpy import pi
|
|
12
|
+
from numpy import pi
|
|
14
13
|
from scipy import ndimage as ndi
|
|
15
14
|
|
|
16
15
|
from . import framework as mwx
|
|
17
16
|
from .framework import Menu
|
|
17
|
+
from .utilus import warn
|
|
18
18
|
from .utilus import funcall as _F
|
|
19
19
|
from .controls import Clipboard
|
|
20
20
|
from .matplot2 import MatplotPanel
|
|
@@ -224,24 +224,26 @@ class AxesImagePhantom(object):
|
|
|
224
224
|
@property
|
|
225
225
|
def unit(self):
|
|
226
226
|
"""Logical length per pixel arb.unit [u/pixel]."""
|
|
227
|
-
return self.__localunit or self.parent.
|
|
227
|
+
return self.__localunit or self.parent.unit
|
|
228
228
|
|
|
229
229
|
@unit.setter
|
|
230
230
|
def unit(self, v):
|
|
231
231
|
u = self.unit
|
|
232
|
-
if v
|
|
233
|
-
v = self.parent.
|
|
232
|
+
if v is None:
|
|
233
|
+
v = self.parent.unit
|
|
234
234
|
self.__localunit = None
|
|
235
|
+
elif np.isnan(v) or np.isinf(v):
|
|
236
|
+
raise ValueError("The unit value cannot be NaN or Inf")
|
|
235
237
|
elif v <= 0:
|
|
236
|
-
raise
|
|
238
|
+
raise ValueError("The unit value must be greater than zero")
|
|
237
239
|
else:
|
|
238
240
|
if v == self.__localunit: # no effect when v is localunit
|
|
239
241
|
return
|
|
240
242
|
self.__localunit = v
|
|
241
243
|
self.__attributes['localunit'] = self.__localunit
|
|
242
244
|
self.update_extent()
|
|
243
|
-
self.parent.update_markup_ratio(v/u)
|
|
244
245
|
self.parent.handler('frame_updated', self)
|
|
246
|
+
self.parent.canvas.draw_idle()
|
|
245
247
|
|
|
246
248
|
@unit.deleter
|
|
247
249
|
def unit(self):
|
|
@@ -249,7 +251,7 @@ class AxesImagePhantom(object):
|
|
|
249
251
|
|
|
250
252
|
@property
|
|
251
253
|
def xy_unit(self):
|
|
252
|
-
u = self.__localunit or self.parent.
|
|
254
|
+
u = self.__localunit or self.parent.unit
|
|
253
255
|
return (u, u * self.__aspect_ratio)
|
|
254
256
|
|
|
255
257
|
@property
|
|
@@ -331,8 +333,7 @@ class AxesImagePhantom(object):
|
|
|
331
333
|
def _cast(n):
|
|
332
334
|
return np.int32(np.floor(np.round(n, 1)))
|
|
333
335
|
if y is None:
|
|
334
|
-
|
|
335
|
-
DeprecationWarning, stacklevel=2)
|
|
336
|
+
warn("Setting xy data with single tuple.", DeprecationWarning)
|
|
336
337
|
x, y = x
|
|
337
338
|
if isinstance(x, (list, tuple)):
|
|
338
339
|
x = np.array(x)
|
|
@@ -348,8 +349,7 @@ class AxesImagePhantom(object):
|
|
|
348
349
|
def xyfrompixel(self, nx, ny=None):
|
|
349
350
|
"""Convert pixel [nx,ny] -> (x,y) xydata (float number)."""
|
|
350
351
|
if ny is None:
|
|
351
|
-
|
|
352
|
-
DeprecationWarning, stacklevel=2)
|
|
352
|
+
warn("Setting xy data with single tuple.", DeprecationWarning)
|
|
353
353
|
nx, ny = nx
|
|
354
354
|
if isinstance(nx, (list, tuple)):
|
|
355
355
|
nx = np.array(nx)
|
|
@@ -658,8 +658,8 @@ class GraphPlot(MatplotPanel):
|
|
|
658
658
|
j = names.index(name) # existing frame
|
|
659
659
|
if j != -1:
|
|
660
660
|
art = self.__Arts[j]
|
|
661
|
-
art.update_buffer(buf)
|
|
662
|
-
art.update_attributes(kwargs) # => frame_updated
|
|
661
|
+
art.update_buffer(buf) # => [frame_modified]
|
|
662
|
+
art.update_attributes(kwargs) # => [frame_updated] localunit => [canvas_draw]
|
|
663
663
|
art.update_extent()
|
|
664
664
|
if show:
|
|
665
665
|
self.select(j)
|
|
@@ -674,7 +674,11 @@ class GraphPlot(MatplotPanel):
|
|
|
674
674
|
self.__Arts.insert(j, art)
|
|
675
675
|
self.handler('frame_loaded', art)
|
|
676
676
|
if show:
|
|
677
|
+
u = self.frame and self.frame.unit # current frame unit
|
|
677
678
|
self.select(j)
|
|
679
|
+
## Update view if the unit length is different from before selection
|
|
680
|
+
if u != art.unit:
|
|
681
|
+
self.axes.axis(art.get_extent())
|
|
678
682
|
return art
|
|
679
683
|
|
|
680
684
|
def select(self, j):
|
|
@@ -688,17 +692,10 @@ class GraphPlot(MatplotPanel):
|
|
|
688
692
|
self.handler('frame_hidden', self.frame)
|
|
689
693
|
|
|
690
694
|
if j is not None:
|
|
691
|
-
u = self.frame and self.frame.unit # current frame unit
|
|
692
|
-
|
|
693
695
|
art = self.__Arts[j]
|
|
694
696
|
art.set_visible(1)
|
|
695
697
|
self.__index = j % len(self)
|
|
696
698
|
self.handler('frame_shown', art)
|
|
697
|
-
|
|
698
|
-
## Update view if the unit length is different than before
|
|
699
|
-
if u != art.unit:
|
|
700
|
-
## self.update_axis()
|
|
701
|
-
self.axes.axis(art.get_extent())
|
|
702
699
|
else:
|
|
703
700
|
self.__index = None
|
|
704
701
|
|
|
@@ -828,10 +825,12 @@ class GraphPlot(MatplotPanel):
|
|
|
828
825
|
|
|
829
826
|
@unit.setter
|
|
830
827
|
def unit(self, v):
|
|
831
|
-
if v
|
|
832
|
-
raise
|
|
828
|
+
if v is None:
|
|
829
|
+
raise ValueError("The globalunit must be non-nil value")
|
|
830
|
+
elif np.isnan(v) or np.isinf(v):
|
|
831
|
+
raise ValueError("Axis limits cannot be NaN or Inf")
|
|
833
832
|
elif v <= 0:
|
|
834
|
-
raise
|
|
833
|
+
raise ValueError("The unit value must be greater than zero")
|
|
835
834
|
else:
|
|
836
835
|
if v == self.__unit: # no effect unless unit changes
|
|
837
836
|
return
|
|
@@ -839,19 +838,10 @@ class GraphPlot(MatplotPanel):
|
|
|
839
838
|
self.__unit = v
|
|
840
839
|
for art in self.__Arts:
|
|
841
840
|
art.update_extent()
|
|
842
|
-
else:
|
|
843
|
-
self.update_markup_ratio(v/u)
|
|
844
|
-
for art in self.__Arts:
|
|
845
841
|
self.handler('frame_updated', art)
|
|
842
|
+
self.canvas.draw_idle()
|
|
846
843
|
|
|
847
|
-
globalunit = unit
|
|
848
|
-
|
|
849
|
-
def update_markup_ratio(self, r):
|
|
850
|
-
"""Modify markup objects position."""
|
|
851
|
-
if self.Selector.size: self.Selector *= r
|
|
852
|
-
if self.Markers.size: self.Markers *= r
|
|
853
|
-
if self.Region.size: self.Region *= r
|
|
854
|
-
self.draw()
|
|
844
|
+
globalunit = unit # for backward compatibility
|
|
855
845
|
|
|
856
846
|
def kill_buffer(self):
|
|
857
847
|
if self.buffer is not None:
|
mwx/matplot2lg.py
CHANGED
|
@@ -623,7 +623,7 @@ class LineProfile(LinePlot):
|
|
|
623
623
|
with io.StringIO() as o:
|
|
624
624
|
for x, y in zip(X, Y):
|
|
625
625
|
o.write("{:g}\t{:g}\n".format(x, y))
|
|
626
|
-
Clipboard.write(o.getvalue()
|
|
626
|
+
Clipboard.write(o.getvalue())
|
|
627
627
|
self.message("Write data to clipboard.")
|
|
628
628
|
|
|
629
629
|
def annotate(self):
|
mwx/nutshell.py
CHANGED
|
@@ -7,7 +7,6 @@ from contextlib import contextmanager
|
|
|
7
7
|
from pprint import pformat
|
|
8
8
|
from bdb import BdbQuit
|
|
9
9
|
import traceback
|
|
10
|
-
import warnings
|
|
11
10
|
import inspect
|
|
12
11
|
import builtins
|
|
13
12
|
import dis
|
|
@@ -26,6 +25,7 @@ from wx.py.shell import Shell
|
|
|
26
25
|
from wx.py.editwindow import EditWindow
|
|
27
26
|
|
|
28
27
|
from .utilus import funcall as _F
|
|
28
|
+
from .utilus import ignore
|
|
29
29
|
from .utilus import split_words, split_paren, split_tokens, find_modules
|
|
30
30
|
from .framework import CtrlInterface, AuiNotebook, Menu
|
|
31
31
|
|
|
@@ -1986,7 +1986,7 @@ class EditorBook(AuiNotebook, CtrlInterface):
|
|
|
1986
1986
|
self.swap_buffer(buf, lineno)
|
|
1987
1987
|
return True
|
|
1988
1988
|
## return False
|
|
1989
|
-
raise Exception("The requested URL was not found
|
|
1989
|
+
raise Exception("The requested URL was not found")
|
|
1990
1990
|
if buf._load_file(filename):
|
|
1991
1991
|
self.swap_buffer(buf, lineno)
|
|
1992
1992
|
return True
|
|
@@ -2161,6 +2161,7 @@ class Interpreter(interpreter.Interpreter):
|
|
|
2161
2161
|
except AttributeError:
|
|
2162
2162
|
pass
|
|
2163
2163
|
|
|
2164
|
+
@ignore(DeprecationWarning)
|
|
2164
2165
|
def getCallTip(self, command='', *args, **kwargs):
|
|
2165
2166
|
"""Return call tip text for a command.
|
|
2166
2167
|
|
|
@@ -2169,12 +2170,10 @@ class Interpreter(interpreter.Interpreter):
|
|
|
2169
2170
|
(override) Ignore ValueError: no signature found for builtin
|
|
2170
2171
|
if the unwrapped function is a builtin function.
|
|
2171
2172
|
"""
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
except ValueError:
|
|
2177
|
-
return interpreter.Interpreter.getCallTip(self) # dummy
|
|
2173
|
+
try:
|
|
2174
|
+
return interpreter.Interpreter.getCallTip(self, command, *args, **kwargs)
|
|
2175
|
+
except ValueError:
|
|
2176
|
+
return interpreter.Interpreter.getCallTip(self) # dummy
|
|
2178
2177
|
|
|
2179
2178
|
|
|
2180
2179
|
class Nautilus(Shell, EditorInterface):
|
mwx/plugins/frame_listview.py
CHANGED
|
@@ -72,7 +72,6 @@ class CheckList(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
|
|
|
72
72
|
'Lbutton dblclick' : (0, self.OnShowItems), # -> frame_shown
|
|
73
73
|
'enter pressed' : (0, self.OnShowItems), # -> frame_shown
|
|
74
74
|
'delete pressed' : (0, self.OnRemoveItems), # -> frame_removed/shown
|
|
75
|
-
'f2 pressed' : (0, self.OnEditAnnotation),
|
|
76
75
|
'C-a pressed' : (0, self.OnSelectAllItems),
|
|
77
76
|
'C-o pressed' : (0, self.OnLoadItems),
|
|
78
77
|
'C-s pressed' : (0, self.OnSaveItems),
|
|
@@ -97,26 +96,17 @@ class CheckList(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
|
|
|
97
96
|
}
|
|
98
97
|
self.Target.handler.append(self.context)
|
|
99
98
|
|
|
100
|
-
def copy_info(all=True):
|
|
101
|
-
frames = self.Target.all_frames
|
|
102
|
-
if frames:
|
|
103
|
-
frame = frames[self.focused_item]
|
|
104
|
-
if all:
|
|
105
|
-
text = pformat(frame.attributes, sort_dicts=0)
|
|
106
|
-
else:
|
|
107
|
-
text = "{}\n{}".format(frame.name, frame.annotation)
|
|
108
|
-
Clipboard.write(text)
|
|
109
|
-
|
|
110
99
|
self.menu = [
|
|
111
|
-
(
|
|
112
|
-
self.
|
|
100
|
+
(100, "Edit localunit", Icon('image'),
|
|
101
|
+
self.OnEditUnit,
|
|
102
|
+
lambda v: v.Enable(self.focused_item != -1)),
|
|
103
|
+
|
|
104
|
+
(101, "Edit annotation", Icon('pencil'),
|
|
105
|
+
self.OnEditAnnotation,
|
|
106
|
+
lambda v: v.Enable(self.focused_item != -1)),
|
|
113
107
|
(),
|
|
114
108
|
(102, "Copy info", Icon('copy'),
|
|
115
|
-
|
|
116
|
-
lambda v: v.Enable(len(list(self.selected_items)))),
|
|
117
|
-
|
|
118
|
-
(103, "Copy ALL data", Icon('copy', '+'),
|
|
119
|
-
lambda v: copy_info(1),
|
|
109
|
+
self.OnCopyInfo,
|
|
120
110
|
lambda v: v.Enable(len(list(self.selected_items)))),
|
|
121
111
|
]
|
|
122
112
|
self.Bind(wx.EVT_CONTEXT_MENU,
|
|
@@ -183,26 +173,40 @@ class CheckList(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
|
|
|
183
173
|
self.parent.parent.load_index(view=self.Target)
|
|
184
174
|
|
|
185
175
|
def OnSaveItems(self, evt):
|
|
186
|
-
|
|
187
|
-
selected_frames = [frames[j] for j in self.selected_items]
|
|
176
|
+
selected_frames = [self.Target.all_frames[j] for j in self.selected_items]
|
|
188
177
|
if selected_frames:
|
|
189
178
|
self.parent.message("Exporting {} frames.".format(len(selected_frames)))
|
|
190
179
|
self.parent.parent.save_index(frames=selected_frames)
|
|
191
180
|
else:
|
|
192
181
|
self.parent.message("No frame selected.")
|
|
193
182
|
|
|
183
|
+
def OnCopyInfo(self, evt):
|
|
184
|
+
selected_frames = [self.Target.all_frames[j] for j in self.selected_items]
|
|
185
|
+
if selected_frames:
|
|
186
|
+
text = ''
|
|
187
|
+
for frame in selected_frames:
|
|
188
|
+
text += pformat(frame.attributes, sort_dicts=0) # ALL attributes
|
|
189
|
+
## text += '{}\n{}\n'.format(frame.name, frame.annotation)
|
|
190
|
+
Clipboard.write(text)
|
|
191
|
+
else:
|
|
192
|
+
self.parent.message("No frame selected.")
|
|
193
|
+
|
|
194
|
+
def OnEditUnit(self, evt):
|
|
195
|
+
frame = self.Target.all_frames[self.focused_item]
|
|
196
|
+
with wx.TextEntryDialog(self, frame.name,
|
|
197
|
+
'Enter localunit', repr(frame.localunit)) as dlg:
|
|
198
|
+
if dlg.ShowModal() == wx.ID_OK:
|
|
199
|
+
frame.unit = eval(dlg.Value or 'None')
|
|
200
|
+
|
|
194
201
|
def OnEditAnnotation(self, evt):
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if dlg.ShowModal() == wx.ID_OK:
|
|
201
|
-
frame.annotation = dlg.Value
|
|
202
|
+
frame = self.Target.all_frames[self.focused_item]
|
|
203
|
+
with wx.TextEntryDialog(self, frame.name,
|
|
204
|
+
'Enter an annotation', frame.annotation) as dlg:
|
|
205
|
+
if dlg.ShowModal() == wx.ID_OK:
|
|
206
|
+
frame.annotation = dlg.Value
|
|
202
207
|
|
|
203
208
|
def OnItemSelected(self, evt):
|
|
204
|
-
|
|
205
|
-
frame = frames[evt.Index]
|
|
209
|
+
frame = self.Target.all_frames[evt.Index]
|
|
206
210
|
self.parent.message(frame.pathname)
|
|
207
211
|
evt.Skip()
|
|
208
212
|
|
mwx/utilus.py
CHANGED
|
@@ -37,6 +37,16 @@ def ignore(*category):
|
|
|
37
37
|
yield
|
|
38
38
|
|
|
39
39
|
|
|
40
|
+
def warn(message, category=None):
|
|
41
|
+
frame = inspect.currentframe().f_back # previous call stack frame
|
|
42
|
+
skip = [frame.f_code.co_filename]
|
|
43
|
+
stacklevel = 1
|
|
44
|
+
while frame.f_code.co_filename in skip:
|
|
45
|
+
frame = frame.f_back
|
|
46
|
+
stacklevel += 1
|
|
47
|
+
return warnings.warn(message, category, stacklevel+1)
|
|
48
|
+
|
|
49
|
+
|
|
40
50
|
def atom(v):
|
|
41
51
|
return not hasattr(v, '__name__')
|
|
42
52
|
|
|
@@ -434,13 +444,12 @@ def find_modules(force=False, verbose=True):
|
|
|
434
444
|
lm = eval(o.read()) # read and evaluate module list
|
|
435
445
|
|
|
436
446
|
## Check additional packages and modules
|
|
437
|
-
verbose = False
|
|
447
|
+
## verbose = False
|
|
438
448
|
for info in walk_packages_no_import(['.']):
|
|
439
449
|
_callback('.', info.name)
|
|
440
450
|
else:
|
|
441
|
-
print("Please wait a moment "
|
|
442
|
-
|
|
443
|
-
"(This is executed once)".format(sys.winver))
|
|
451
|
+
print(f"Please wait a moment while Py{sys.winver} gathers a list of "
|
|
452
|
+
"all available modules... (This is executed once)")
|
|
444
453
|
|
|
445
454
|
lm = list(sys.builtin_module_names)
|
|
446
455
|
|
|
@@ -684,7 +693,6 @@ class FSM(dict):
|
|
|
684
693
|
" action : {}".format(typename(act)),
|
|
685
694
|
" args : {}".format(args),
|
|
686
695
|
" kwargs : {}".format(kwargs))
|
|
687
|
-
traceback.print_exc()
|
|
688
696
|
self.__matched_pattern = None
|
|
689
697
|
return retvals
|
|
690
698
|
|
|
@@ -728,12 +736,11 @@ class FSM(dict):
|
|
|
728
736
|
|
|
729
737
|
@staticmethod
|
|
730
738
|
def dump(*args):
|
|
731
|
-
print(*args, sep='\n', file=sys.__stderr__)
|
|
732
739
|
fn = get_rootpath("deb-dump.log")
|
|
733
740
|
with open(fn, 'a') as o:
|
|
734
741
|
print(time.strftime('!!! %Y/%m/%d %H:%M:%S'), file=o)
|
|
735
|
-
print(*args,
|
|
736
|
-
|
|
742
|
+
print(*args, traceback.format_exc(), sep='\n', file=o)
|
|
743
|
+
print(*args, traceback.format_exc(), sep='\n', file=sys.__stderr__)
|
|
737
744
|
|
|
738
745
|
@staticmethod
|
|
739
746
|
def duplicate(context):
|
|
@@ -810,11 +817,8 @@ class FSM(dict):
|
|
|
810
817
|
assert isinstance(event, str)
|
|
811
818
|
assert callable(action) or action is None
|
|
812
819
|
|
|
813
|
-
def warn(msg):
|
|
814
|
-
warnings.warn(msg, stacklevel=3)
|
|
815
|
-
|
|
816
820
|
if state not in self:
|
|
817
|
-
warn("- FSM
|
|
821
|
+
warn(f"- FSM [{state!r}] context newly created.")
|
|
818
822
|
self[state] = SSM() # new context
|
|
819
823
|
|
|
820
824
|
context = self[state]
|
|
@@ -823,16 +827,16 @@ class FSM(dict):
|
|
|
823
827
|
|
|
824
828
|
if event in context:
|
|
825
829
|
if state2 != context[event][0]:
|
|
826
|
-
warn("- FSM
|
|
827
|
-
" The state {
|
|
828
|
-
" {
|
|
830
|
+
warn(f"- FSM transaction may conflict.\n"
|
|
831
|
+
f" The state {state2!r} is different from the original state."
|
|
832
|
+
f" {event!r} : {state!r} --> {state2!r}")
|
|
829
833
|
pass
|
|
830
834
|
context[event][0] = state2 # update transition
|
|
831
835
|
else:
|
|
832
836
|
## if state2 not in self:
|
|
833
|
-
## warn("- FSM
|
|
834
|
-
## " The state {
|
|
835
|
-
## " {
|
|
837
|
+
## warn(f"- FSM transaction may contradict\n"
|
|
838
|
+
## f" The state {state2!r} is not found in the contexts."
|
|
839
|
+
## f" {event!r} : {state!r} --> {state2!r}")
|
|
836
840
|
## pass
|
|
837
841
|
context[event] = [state2] # new event:transaction
|
|
838
842
|
|
|
@@ -844,8 +848,8 @@ class FSM(dict):
|
|
|
844
848
|
try:
|
|
845
849
|
transaction.append(action)
|
|
846
850
|
except AttributeError:
|
|
847
|
-
warn("- FSM
|
|
848
|
-
" The transaction must be a list, not a tuple"
|
|
851
|
+
warn(f"- FSM cannot append new transaction ({state!r} : {event!r})\n"
|
|
852
|
+
f" The transaction must be a list, not a tuple")
|
|
849
853
|
return action
|
|
850
854
|
|
|
851
855
|
def unbind(self, event, action=None, state=None):
|
|
@@ -858,16 +862,13 @@ class FSM(dict):
|
|
|
858
862
|
"""
|
|
859
863
|
assert callable(action) or action is None
|
|
860
864
|
|
|
861
|
-
def warn(msg):
|
|
862
|
-
warnings.warn(msg, stacklevel=3)
|
|
863
|
-
|
|
864
865
|
if state not in self:
|
|
865
|
-
warn("- FSM
|
|
866
|
+
warn(f"- FSM [{state!r}] context does not exist.")
|
|
866
867
|
return
|
|
867
868
|
|
|
868
869
|
context = self[state]
|
|
869
870
|
if event not in context:
|
|
870
|
-
warn("- FSM
|
|
871
|
+
warn(f"- FSM has no such transaction ({state!r} : {event!r})")
|
|
871
872
|
return
|
|
872
873
|
|
|
873
874
|
transaction = context[event]
|
|
@@ -881,8 +882,8 @@ class FSM(dict):
|
|
|
881
882
|
transaction.remove(action)
|
|
882
883
|
return True
|
|
883
884
|
except AttributeError:
|
|
884
|
-
warn("- FSM
|
|
885
|
-
" The transaction must be a list, not a tuple"
|
|
885
|
+
warn(f"- FSM removing action from context ({state!r} : {event!r})\n"
|
|
886
|
+
f" The transaction must be a list, not a tuple")
|
|
886
887
|
return False
|
|
887
888
|
|
|
888
889
|
|
|
@@ -964,7 +965,7 @@ class TreeList(object):
|
|
|
964
965
|
else:
|
|
965
966
|
ls.append([key, value]) # append to items:list
|
|
966
967
|
except (ValueError, TypeError, AttributeError) as e:
|
|
967
|
-
|
|
968
|
+
warn(f"- TreeList:warning {e!r}: {key=!r}")
|
|
968
969
|
|
|
969
970
|
def _delf(self, ls, key):
|
|
970
971
|
if '/' in key:
|
mwx/wxmon.py
CHANGED
|
@@ -3,12 +3,11 @@
|
|
|
3
3
|
|
|
4
4
|
*** Inspired by wx.lib.eventwatcher ***
|
|
5
5
|
"""
|
|
6
|
-
import warnings
|
|
7
6
|
import wx
|
|
8
7
|
import wx.lib.eventwatcher as ew
|
|
9
8
|
from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin
|
|
10
9
|
|
|
11
|
-
from .utilus import where
|
|
10
|
+
from .utilus import where, ignore
|
|
12
11
|
from .controls import Icon, Clipboard
|
|
13
12
|
from .framework import CtrlInterface, Menu
|
|
14
13
|
|
|
@@ -176,8 +175,7 @@ class EventMonitor(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
|
|
|
176
175
|
source = ew._makeSourceString(obj) + " id=0x{:X}".format(id(evt))
|
|
177
176
|
stamp = 1
|
|
178
177
|
|
|
179
|
-
with
|
|
180
|
-
warnings.simplefilter('ignore', DeprecationWarning)
|
|
178
|
+
with ignore(DeprecationWarning):
|
|
181
179
|
attribs = ew._makeAttribString(evt)
|
|
182
180
|
|
|
183
181
|
data = self.__items
|
|
@@ -232,7 +230,7 @@ class EventMonitor(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
|
|
|
232
230
|
if self.IsSelected(i):
|
|
233
231
|
event, name, *_, attribs = self.__items[i]
|
|
234
232
|
text += "{}\t{}\n{}\n\n".format(event, name, attribs)
|
|
235
|
-
Clipboard.write(text
|
|
233
|
+
Clipboard.write(text[:-1])
|
|
236
234
|
|
|
237
235
|
def OnSortItems(self, evt): #<wx._controls.ListEvent>
|
|
238
236
|
n = self.ItemCount
|
mwx/wxwil.py
CHANGED
|
@@ -145,7 +145,7 @@ class LocalsWatcher(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
|
|
|
145
145
|
if self.IsSelected(i):
|
|
146
146
|
key, vstr = self.__items[i]
|
|
147
147
|
text += "{} = {}\n".format(key, vstr)
|
|
148
|
-
Clipboard.write(text
|
|
148
|
+
Clipboard.write(text)
|
|
149
149
|
|
|
150
150
|
def OnSortItems(self, evt): #<wx._controls.ListEvent>
|
|
151
151
|
n = self.ItemCount
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
mwx/__init__.py,sha256=nN62CGTWjME7Zz2h-jIRB8MxwuErIkHPGrlBzydkF0o,643
|
|
2
|
+
mwx/bookshelf.py,sha256=CjcgtHC33KR5mHp1lW6Bqfndpzr7hC8ICkFihw4kM3g,5134
|
|
3
|
+
mwx/controls.py,sha256=JGoDEqfa0m5unISRcAdTxqCXihfuFo1mnLQcMimpGdc,48445
|
|
4
|
+
mwx/framework.py,sha256=bP9D868lzBecp1ZRYEv_GupYtior0AoiK6M8B-yxBvw,75249
|
|
5
|
+
mwx/graphman.py,sha256=eNL1Uja1m4g8ER3emArTFPZllvxEjvdnZTc1y8QMciE,71267
|
|
6
|
+
mwx/images.py,sha256=gyvqW4TLWdJMKmsaWiPiV_PuHJM1GbHgeELERLwGzg8,45291
|
|
7
|
+
mwx/matplot2.py,sha256=-G7z0Osozm9NjLfXvX5UcdFviwbNUktjbd904_g-PqQ,33516
|
|
8
|
+
mwx/matplot2g.py,sha256=22rpdkqJQEJADINPaG5htACutbt8oG1ewO8LMpxaqH4,65237
|
|
9
|
+
mwx/matplot2lg.py,sha256=MDbkO0vn5yi9rwTBCBJ4rsIHcWyoGXeNTbp0xfrvTdM,27381
|
|
10
|
+
mwx/mgplt.py,sha256=ITzxA97yDwr_35BUk5OqnyskSuKVDbpf2AQCKY1jHTI,5671
|
|
11
|
+
mwx/nutshell.py,sha256=HNo8ZuhLZPKd_Cg4s9NN-KfuSXHRP_jaw1s59GVXkN4,136971
|
|
12
|
+
mwx/utilus.py,sha256=jTjeunx_9-HrjdWaceX1Xeq3pHMS4M7M9ma2i4uhKJY,37369
|
|
13
|
+
mwx/wxmon.py,sha256=f3V24EF7kdMlYF7usLYK9QE5KU6fSu0jVqsvwAiA-Ag,12647
|
|
14
|
+
mwx/wxpdb.py,sha256=lLowkkAgMhPFHAfklD7wZHq0qbSMjRxnBFtSajmVgME,19133
|
|
15
|
+
mwx/wxwil.py,sha256=0bzSTfMEjllJheKxZPb4p8Luz6Il3V29bCLBty72U2o,5576
|
|
16
|
+
mwx/wxwit.py,sha256=yU6XeCCWRBP7CLmpphjT072PfXAL30DNaxoChDX2p0I,7322
|
|
17
|
+
mwx/plugins/__init__.py,sha256=jnJ-Sl9XJ_7BFDslD_r7dsbxsOT57q_IaEriV53XIGY,41
|
|
18
|
+
mwx/plugins/ffmpeg_view.py,sha256=wZXRgsiPyIphcA8hvXQoE7NZp4cc_YBOO0ZpuKmUJKE,9369
|
|
19
|
+
mwx/plugins/fft_view.py,sha256=HcnBr-y_yFdSfASPRzMLANta4SwSDShd65QWnCU3XhM,2665
|
|
20
|
+
mwx/plugins/frame_listview.py,sha256=Li993CV0pPY23Jb8cGQkc3wVeDlHWLEe8RuDbNZeB8s,10351
|
|
21
|
+
mwx/plugins/line_profile.py,sha256=--9NIc3x5EfRB3L59JvD7rzENQHyiYfu7wWJo6AuMkA,820
|
|
22
|
+
mwx/py/__init__.py,sha256=xykgfOytOwNuvXsfkLoumFZSTN-iBsHOjczYXngjmUE,12
|
|
23
|
+
mwx/py/filling.py,sha256=KaHooM32hrGGgqw75Cbt8lAvACwC6RXadob9LGgNnEc,16806
|
|
24
|
+
mwxlib-0.96.4.dist-info/LICENSE,sha256=PGtRKCaTkmUDlBQwpptJAxJtdqxIUtAmdBsaT9nUVkA,1091
|
|
25
|
+
mwxlib-0.96.4.dist-info/METADATA,sha256=z1bx81IMuasnA9ZGE1vUidxqqh7cOC_LmB-Rdrqd0xw,1925
|
|
26
|
+
mwxlib-0.96.4.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
|
|
27
|
+
mwxlib-0.96.4.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
|
|
28
|
+
mwxlib-0.96.4.dist-info/RECORD,,
|
mwxlib-0.96.0.dist-info/RECORD
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
mwx/__init__.py,sha256=nN62CGTWjME7Zz2h-jIRB8MxwuErIkHPGrlBzydkF0o,643
|
|
2
|
-
mwx/bookshelf.py,sha256=DAhMQk3_J4rdE50adBMFu5wNz3WdMh_zzJ37O9ncceo,5103
|
|
3
|
-
mwx/controls.py,sha256=IAT3l3-azlPFtMc2VGNMiQhI390ExW0S4CgjEOKFI4s,48200
|
|
4
|
-
mwx/framework.py,sha256=Z-WbpepmraX_7wCq4jWpOCeDhUrUO5NlOmFLf2RjoLk,75666
|
|
5
|
-
mwx/graphman.py,sha256=4SRwCMs4-sS3n23FthythhuG9dBJ8TLz_TVyoYAbdoA,70639
|
|
6
|
-
mwx/images.py,sha256=gyvqW4TLWdJMKmsaWiPiV_PuHJM1GbHgeELERLwGzg8,45291
|
|
7
|
-
mwx/matplot2.py,sha256=-G7z0Osozm9NjLfXvX5UcdFviwbNUktjbd904_g-PqQ,33516
|
|
8
|
-
mwx/matplot2g.py,sha256=Ii0y4Ebod-9EJ-WPaCyZ-voM5uC3MTDmNktJD7OiTtA,65496
|
|
9
|
-
mwx/matplot2lg.py,sha256=pcu1oDPE_BlpFqNGPPKf9vpTuDs_h_u3OTRAJx5-Sds,27392
|
|
10
|
-
mwx/mgplt.py,sha256=ITzxA97yDwr_35BUk5OqnyskSuKVDbpf2AQCKY1jHTI,5671
|
|
11
|
-
mwx/nutshell.py,sha256=pbsQATwt906lOXGFWJmuwZIwU_ve78o46I2g5zNjvG4,137050
|
|
12
|
-
mwx/utilus.py,sha256=Uwj6vbNUUztwOswPG75xtsT2y_PZqh3QiJraxmA9iT0,37401
|
|
13
|
-
mwx/wxmon.py,sha256=6es-jVz9Ht7vZnG7VBJcaNYLHY0PnZtij60SXcZRTeY,12727
|
|
14
|
-
mwx/wxpdb.py,sha256=lLowkkAgMhPFHAfklD7wZHq0qbSMjRxnBFtSajmVgME,19133
|
|
15
|
-
mwx/wxwil.py,sha256=zP1-5Fpi1wpDQU977229zIH6QRuSkkyfuAlNKWjGoGg,5588
|
|
16
|
-
mwx/wxwit.py,sha256=yU6XeCCWRBP7CLmpphjT072PfXAL30DNaxoChDX2p0I,7322
|
|
17
|
-
mwx/plugins/__init__.py,sha256=jnJ-Sl9XJ_7BFDslD_r7dsbxsOT57q_IaEriV53XIGY,41
|
|
18
|
-
mwx/plugins/ffmpeg_view.py,sha256=wZXRgsiPyIphcA8hvXQoE7NZp4cc_YBOO0ZpuKmUJKE,9369
|
|
19
|
-
mwx/plugins/fft_view.py,sha256=HcnBr-y_yFdSfASPRzMLANta4SwSDShd65QWnCU3XhM,2665
|
|
20
|
-
mwx/plugins/frame_listview.py,sha256=RaYOj-YKrpLqhT8TkBRDX1TQnSPv90V185j8OjrWJTs,10108
|
|
21
|
-
mwx/plugins/line_profile.py,sha256=--9NIc3x5EfRB3L59JvD7rzENQHyiYfu7wWJo6AuMkA,820
|
|
22
|
-
mwx/py/__init__.py,sha256=xykgfOytOwNuvXsfkLoumFZSTN-iBsHOjczYXngjmUE,12
|
|
23
|
-
mwx/py/filling.py,sha256=KaHooM32hrGGgqw75Cbt8lAvACwC6RXadob9LGgNnEc,16806
|
|
24
|
-
mwxlib-0.96.0.dist-info/LICENSE,sha256=PGtRKCaTkmUDlBQwpptJAxJtdqxIUtAmdBsaT9nUVkA,1091
|
|
25
|
-
mwxlib-0.96.0.dist-info/METADATA,sha256=3UowIlnhpmH3yDgustsBu7iviC9fFKYIWtspEFsWYNs,1925
|
|
26
|
-
mwxlib-0.96.0.dist-info/WHEEL,sha256=cpQTJ5IWu9CdaPViMhC9YzF8gZuS5-vlfoFihTBC86A,91
|
|
27
|
-
mwxlib-0.96.0.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
|
|
28
|
-
mwxlib-0.96.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|