mwxlib 0.96.1__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 CHANGED
@@ -1,4 +1,5 @@
1
1
  #! python3
2
+ from functools import partial
2
3
  import re
3
4
  import wx
4
5
 
mwx/controls.py CHANGED
@@ -8,6 +8,7 @@ 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
 
@@ -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):
@@ -295,7 +296,6 @@ class Knob(wx.Panel):
295
296
  None -> static text (default)
296
297
  chkbox -> label with check box
297
298
  button -> label with flat button
298
- editable: textctrl is editable or readonly
299
299
  cw : width of ctrl
300
300
  lw : width of label
301
301
  tw : width of textbox
@@ -355,23 +355,22 @@ class Knob(wx.Panel):
355
355
  else:
356
356
  raise Exception("unknown style: {!r}".format(style))
357
357
 
358
- self.label.Enable(lw)
359
358
  self.label.Bind(wx.EVT_MIDDLE_DOWN, lambda v: self.__par.reset())
360
-
361
359
  self.label.SetToolTip(self.__par._tooltip)
360
+ self.label.Enable(lw) # skip focus
362
361
 
363
- if editable:
364
- self.text = wx.TextCtrl(self, size=(tw,h), style=wx.TE_PROCESS_ENTER)
365
- self.text.Bind(wx.EVT_TEXT_ENTER, self.OnTextEnter)
366
- self.text.Bind(wx.EVT_KILL_FOCUS, self.OnTextExit)
367
- self.text.Bind(wx.EVT_KEY_DOWN, self.OnTextKeyDown)
368
- self.text.Bind(wx.EVT_KEY_UP, self.OnTextKeyUp)
369
- self.text.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
370
- self.text.Bind(wx.EVT_MIDDLE_DOWN, lambda v: self.__par.reset())
371
- else:
372
- self.text = wx.TextCtrl(self, size=(tw,h), style=wx.TE_READONLY)
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())
373
372
 
374
- self.text.Enable(tw)
373
+ self.text.Enable(tw) # skip focus
375
374
 
376
375
  if type == 'slider':
377
376
  self.ctrl = wx.Slider(self, size=(cw,h), style=wx.SL_HORIZONTAL)
@@ -405,8 +404,8 @@ class Knob(wx.Panel):
405
404
  else:
406
405
  raise Exception("unknown type: {!r}".format(type))
407
406
 
408
- self.ctrl.Enable(cw != 0)
409
407
  self.ctrl.Bind(wx.EVT_MIDDLE_DOWN, lambda v: self.__par.reset())
408
+ self.ctrl.Enable(cw) # skip focus
410
409
 
411
410
  c = (cw and type != 'vspin')
412
411
  self.SetSizer(
@@ -426,6 +425,7 @@ class Knob(wx.Panel):
426
425
  evt.Skip()
427
426
 
428
427
  def update_range(self):
428
+ """Called when range is being changed (internal use only)."""
429
429
  v = self.__par
430
430
  if isinstance(self.ctrl, wx.Choice): #<wx.Choice>
431
431
  items = [v.__str__(x) for x in v.range]
@@ -436,6 +436,7 @@ class Knob(wx.Panel):
436
436
  self.ctrl.SetRange(0, len(v)-1) #<wx.Slider> <wx.SpinButton>
437
437
 
438
438
  def update_label(self):
439
+ """Called when label is being changed (internal use only)."""
439
440
  v = self.__par
440
441
  if isinstance(self.label, wx.CheckBox):
441
442
  self.label.SetValue(v.check)
@@ -446,6 +447,7 @@ class Knob(wx.Panel):
446
447
  self.label.Refresh()
447
448
 
448
449
  def update_ctrl(self, valid=True, notify=False):
450
+ """Called when value is being changed (internal use only)."""
449
451
  v = self.__par
450
452
  try:
451
453
  j = v.index
@@ -766,32 +768,32 @@ class Clipboard:
766
768
  The clipboard data cannot be transferred unless wx.Frame exists.
767
769
  """
768
770
  @staticmethod
769
- def read(verbose=True):
771
+ def read(verbose=False):
770
772
  do = wx.TextDataObject()
771
773
  if wx.TheClipboard.Open():
772
774
  wx.TheClipboard.GetData(do)
773
775
  wx.TheClipboard.Close()
774
776
  text = do.GetText()
775
777
  if verbose:
776
- print("From clipboard: {}".format(text))
778
+ print(f"From clipboard:\n{text}")
777
779
  return text
778
780
  else:
779
781
  print("- Unable to open clipboard.")
780
782
 
781
783
  @staticmethod
782
- def write(text, verbose=True):
784
+ def write(text, verbose=False):
783
785
  do = wx.TextDataObject(str(text))
784
786
  if wx.TheClipboard.Open():
785
787
  wx.TheClipboard.SetData(do)
786
788
  wx.TheClipboard.Flush()
787
789
  wx.TheClipboard.Close()
788
790
  if verbose:
789
- print("To clipboard: {}".format(text))
791
+ print(f"To clipboard:\n{text}")
790
792
  else:
791
793
  print("- Unable to open clipboard.")
792
794
 
793
795
  @staticmethod
794
- def imread(verbose=True):
796
+ def imread(verbose=False):
795
797
  do = wx.BitmapDataObject()
796
798
  if wx.TheClipboard.Open():
797
799
  wx.TheClipboard.GetData(do)
@@ -805,14 +807,14 @@ class Clipboard:
805
807
  img = bmp.ConvertToImage()
806
808
  buf = np.array(img.GetDataBuffer()) # do copy, don't ref
807
809
  if verbose:
808
- print("From clipboard {:.1f} Mb data".format(buf.nbytes/1e6))
810
+ print("From clipboard: {:.1f} Mb data read.".format(buf.nbytes/1e6))
809
811
  w, h = img.GetSize()
810
812
  return buf.reshape(h, w, 3)
811
813
  except Exception:
812
814
  print("- The contents of the clipboard are not images.")
813
815
 
814
816
  @staticmethod
815
- def imwrite(buf, verbose=True):
817
+ def imwrite(buf, verbose=False):
816
818
  try:
817
819
  ## Convert buf --> bmp
818
820
  h, w = buf.shape[:2]
@@ -830,7 +832,7 @@ class Clipboard:
830
832
  wx.TheClipboard.Flush()
831
833
  wx.TheClipboard.Close()
832
834
  if verbose:
833
- print("To clipboard: {:.1f} Mb data".format(buf.nbytes/1e6))
835
+ print("To clipboard: {:.1f} Mb data written.".format(buf.nbytes/1e6))
834
836
  else:
835
837
  print("- Unable to open clipboard.")
836
838
 
mwx/framework.py CHANGED
@@ -1,14 +1,12 @@
1
1
  #! python3
2
2
  """mwxlib framework.
3
3
  """
4
- __version__ = "0.96.1"
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):
@@ -290,14 +288,12 @@ class KeyCtrlInterfaceMixin:
290
288
  key += ' pressed'
291
289
 
292
290
  if map not in self.handler:
293
- warnings.warn(f"New map to define_key {keymap!r} in {self}.",
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
- warnings.warn(f"Duplicate define_key {keymap!r} in {self}.",
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
- warnings.warn(f"No parents bound to {self}.",
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
- warnings.warn(f"No parents bound to {self}.",
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
- CtrlInterface.__init__(self)
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
- with warnings.catch_warnings():
864
- warnings.simplefilter("ignore", ResourceWarning)
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
- if name in self.plugins:
918
- plug = self.plugins[name].__plug__
919
- name = plug.category or name
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 (Layer) interface
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(Layer).
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
- warnings.warn(f"Duplicate iniheritance of LayerInterface by {cls}.",
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
- warnings.warn(f"Use dummy plug for debugging {name!r}.",
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
@@ -15,6 +14,7 @@ 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
@@ -242,8 +242,8 @@ class AxesImagePhantom(object):
242
242
  self.__localunit = v
243
243
  self.__attributes['localunit'] = self.__localunit
244
244
  self.update_extent()
245
- self.parent.update_markup_ratio(v/u)
246
245
  self.parent.handler('frame_updated', self)
246
+ self.parent.canvas.draw_idle()
247
247
 
248
248
  @unit.deleter
249
249
  def unit(self):
@@ -333,8 +333,7 @@ class AxesImagePhantom(object):
333
333
  def _cast(n):
334
334
  return np.int32(np.floor(np.round(n, 1)))
335
335
  if y is None:
336
- warnings.warn("Setting xy data with single tuple is deprecated.",
337
- DeprecationWarning, stacklevel=2)
336
+ warn("Setting xy data with single tuple.", DeprecationWarning)
338
337
  x, y = x
339
338
  if isinstance(x, (list, tuple)):
340
339
  x = np.array(x)
@@ -350,8 +349,7 @@ class AxesImagePhantom(object):
350
349
  def xyfrompixel(self, nx, ny=None):
351
350
  """Convert pixel [nx,ny] -> (x,y) xydata (float number)."""
352
351
  if ny is None:
353
- warnings.warn("Setting xy data with single tuple is deprecated.",
354
- DeprecationWarning, stacklevel=2)
352
+ warn("Setting xy data with single tuple.", DeprecationWarning)
355
353
  nx, ny = nx
356
354
  if isinstance(nx, (list, tuple)):
357
355
  nx = np.array(nx)
@@ -660,8 +658,8 @@ class GraphPlot(MatplotPanel):
660
658
  j = names.index(name) # existing frame
661
659
  if j != -1:
662
660
  art = self.__Arts[j]
663
- art.update_buffer(buf) # => frame_modified
664
- art.update_attributes(kwargs) # => frame_updated
661
+ art.update_buffer(buf) # => [frame_modified]
662
+ art.update_attributes(kwargs) # => [frame_updated] localunit => [canvas_draw]
665
663
  art.update_extent()
666
664
  if show:
667
665
  self.select(j)
@@ -676,7 +674,11 @@ class GraphPlot(MatplotPanel):
676
674
  self.__Arts.insert(j, art)
677
675
  self.handler('frame_loaded', art)
678
676
  if show:
677
+ u = self.frame and self.frame.unit # current frame unit
679
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())
680
682
  return art
681
683
 
682
684
  def select(self, j):
@@ -690,17 +692,10 @@ class GraphPlot(MatplotPanel):
690
692
  self.handler('frame_hidden', self.frame)
691
693
 
692
694
  if j is not None:
693
- u = self.frame and self.frame.unit # current frame unit
694
-
695
695
  art = self.__Arts[j]
696
696
  art.set_visible(1)
697
697
  self.__index = j % len(self)
698
698
  self.handler('frame_shown', art)
699
-
700
- ## Update view if the unit length is different than before
701
- if u != art.unit:
702
- ## self.update_axis()
703
- self.axes.axis(art.get_extent())
704
699
  else:
705
700
  self.__index = None
706
701
 
@@ -843,20 +838,11 @@ class GraphPlot(MatplotPanel):
843
838
  self.__unit = v
844
839
  for art in self.__Arts:
845
840
  art.update_extent()
846
- else:
847
- self.update_markup_ratio(v/u)
848
- for art in self.__Arts:
849
841
  self.handler('frame_updated', art)
842
+ self.canvas.draw_idle()
850
843
 
851
844
  globalunit = unit # for backward compatibility
852
845
 
853
- def update_markup_ratio(self, r):
854
- """Modify markup objects position."""
855
- if self.Selector.size: self.Selector *= r
856
- if self.Markers.size: self.Markers *= r
857
- if self.Region.size: self.Region *= r
858
- self.draw()
859
-
860
846
  def kill_buffer(self):
861
847
  if self.buffer is not None:
862
848
  del self.buffer
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(), verbose=0)
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
 
@@ -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
- with warnings.catch_warnings():
2173
- warnings.simplefilter('ignore', DeprecationWarning)
2174
- try:
2175
- return interpreter.Interpreter.getCallTip(self, command, *args, **kwargs)
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):
@@ -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
- (101, "&Edit annotation", "Edit annotation", Icon('pencil'),
112
- self.OnEditAnnotation),
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
- lambda v: copy_info(0),
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
- frames = self.Target.all_frames
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
- frames = self.Target.all_frames
196
- if frames:
197
- frame = frames[self.focused_item]
198
- with wx.TextEntryDialog(self, frame.name,
199
- 'Enter an annotation', frame.annotation) as dlg:
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
- frames = self.Target.all_frames
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,7 +444,7 @@ 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:
@@ -807,11 +817,8 @@ class FSM(dict):
807
817
  assert isinstance(event, str)
808
818
  assert callable(action) or action is None
809
819
 
810
- def warn(msg):
811
- warnings.warn(msg, stacklevel=3)
812
-
813
820
  if state not in self:
814
- warn("- FSM warning: [{!r}] context newly created.".format(state))
821
+ warn(f"- FSM [{state!r}] context newly created.")
815
822
  self[state] = SSM() # new context
816
823
 
817
824
  context = self[state]
@@ -820,16 +827,16 @@ class FSM(dict):
820
827
 
821
828
  if event in context:
822
829
  if state2 != context[event][0]:
823
- warn("- FSM warning: transaction may conflict.\n"
824
- " The state {2!r} and the original state is not the same."
825
- " {0!r} : {1!r} --> {2!r}".format(event, state, state2))
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}")
826
833
  pass
827
834
  context[event][0] = state2 # update transition
828
835
  else:
829
836
  ## if state2 not in self:
830
- ## warn("- FSM warning: transaction may contradict\n"
831
- ## " The state {2!r} is not found in the contexts."
832
- ## " {0!r} : {1!r} --> {2!r}".format(event, state, state2))
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}")
833
840
  ## pass
834
841
  context[event] = [state2] # new event:transaction
835
842
 
@@ -841,8 +848,8 @@ class FSM(dict):
841
848
  try:
842
849
  transaction.append(action)
843
850
  except AttributeError:
844
- warn("- FSM warning: cannot append new transaction ({!r} : {!r})\n"
845
- " The transaction must be a list, not a tuple".format(state, event))
851
+ warn(f"- FSM cannot append new transaction ({state!r} : {event!r})\n"
852
+ f" The transaction must be a list, not a tuple")
846
853
  return action
847
854
 
848
855
  def unbind(self, event, action=None, state=None):
@@ -855,16 +862,13 @@ class FSM(dict):
855
862
  """
856
863
  assert callable(action) or action is None
857
864
 
858
- def warn(msg):
859
- warnings.warn(msg, stacklevel=3)
860
-
861
865
  if state not in self:
862
- warn("- FSM warning: [{!r}] context does not exist.".format(state))
866
+ warn(f"- FSM [{state!r}] context does not exist.")
863
867
  return
864
868
 
865
869
  context = self[state]
866
870
  if event not in context:
867
- warn("- FSM warning: No such transaction ({!r} : {!r})".format(state, event))
871
+ warn(f"- FSM has no such transaction ({state!r} : {event!r})")
868
872
  return
869
873
 
870
874
  transaction = context[event]
@@ -878,8 +882,8 @@ class FSM(dict):
878
882
  transaction.remove(action)
879
883
  return True
880
884
  except AttributeError:
881
- warn("- FSM warning: removing action from context ({!r} : {!r})\n"
882
- " The transaction must be a list, not a tuple".format(state, event))
885
+ warn(f"- FSM removing action from context ({state!r} : {event!r})\n"
886
+ f" The transaction must be a list, not a tuple")
883
887
  return False
884
888
 
885
889
 
@@ -961,7 +965,7 @@ class TreeList(object):
961
965
  else:
962
966
  ls.append([key, value]) # append to items:list
963
967
  except (ValueError, TypeError, AttributeError) as e:
964
- print(f"- TreeList:warning {e!r}: {key=!r}")
968
+ warn(f"- TreeList:warning {e!r}: {key=!r}")
965
969
 
966
970
  def _delf(self, ls, key):
967
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 warnings.catch_warnings():
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.strip('\n'))
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.strip('\n'))
148
+ Clipboard.write(text)
149
149
 
150
150
  def OnSortItems(self, evt): #<wx._controls.ListEvent>
151
151
  n = self.ItemCount
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mwxlib
3
- Version: 0.96.1
3
+ Version: 0.96.4
4
4
  Summary: A wrapper of matplotlib and wxPython (phoenix)
5
5
  Home-page: https://github.com/komoto48g/mwxlib
6
6
  Author: Kazuya O'moto
@@ -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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.1.1)
2
+ Generator: setuptools (70.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -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=2US02WAmYVydsPJ8ILzZ7opV83giX1P6kY5rr_ZTX2E,48278
4
- mwx/framework.py,sha256=rzhushWI0BYuGeorx4M6ElKEtpMxrQIrlKOxqqEIokI,75665
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=2vDx1pY89b4A7uaLd_RHK2HQ5hnwtH4C4wiYZLzuQjw,65707
9
- mwx/matplot2lg.py,sha256=pcu1oDPE_BlpFqNGPPKf9vpTuDs_h_u3OTRAJx5-Sds,27392
10
- mwx/mgplt.py,sha256=ITzxA97yDwr_35BUk5OqnyskSuKVDbpf2AQCKY1jHTI,5671
11
- mwx/nutshell.py,sha256=yQbih2Q1SXexJPuFNSwJnky5teRHXEKks12laHo6joo,137049
12
- mwx/utilus.py,sha256=YShC4f67dIyjIOSZhSOEgBUfNR1nVOS6pxtm0GKMWrA,37320
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.1.dist-info/LICENSE,sha256=PGtRKCaTkmUDlBQwpptJAxJtdqxIUtAmdBsaT9nUVkA,1091
25
- mwxlib-0.96.1.dist-info/METADATA,sha256=0D7iaLq2lSivCrt81_r6TINYUkXkU-tUAdsIVugNrrY,1925
26
- mwxlib-0.96.1.dist-info/WHEEL,sha256=mguMlWGMX-VHnMpKOjjQidIo1ssRlCFu4a4mBpz1s2M,91
27
- mwxlib-0.96.1.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
28
- mwxlib-0.96.1.dist-info/RECORD,,