mwxlib 1.6.8__py3-none-any.whl → 1.7.0__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.

@@ -62,7 +62,7 @@ class MyFileDropLoader(wx.FileDropTarget):
62
62
  def __init__(self, target):
63
63
  wx.FileDropTarget.__init__(self)
64
64
  self.target = target
65
-
65
+
66
66
  def OnDropFiles(self, x, y, filenames):
67
67
  path = filenames[-1] # Only the last one will be loaded.
68
68
  if len(filenames) > 1:
@@ -77,7 +77,7 @@ class Plugin(Layer):
77
77
  """
78
78
  menukey = "Plugins/Extensions/FFMpeg viewer"
79
79
  dockable = False
80
-
80
+
81
81
  def Init(self):
82
82
  self.mc = wx.media.MediaCtrl()
83
83
  self.mc.Create(self, size=(300,300),
@@ -156,25 +156,25 @@ class Plugin(Layer):
156
156
 
157
157
  self.mc.Bind(wx.EVT_KEY_DOWN, self.on_hotkey_down)
158
158
  self.mc.Bind(wx.EVT_KEY_UP, self.on_hotkey_up)
159
-
159
+
160
160
  def Destroy(self):
161
161
  self.parent.handler.unbind("unknown_format", self.load_media)
162
162
  if self.mc:
163
163
  self.mc.Destroy()
164
164
  return Layer.Destroy(self)
165
-
165
+
166
166
  def OnShow(self, evt):
167
167
  if not evt.IsShown():
168
168
  if self.mc:
169
169
  self.mc.Stop()
170
170
  Layer.OnShow(self, evt)
171
-
171
+
172
172
  def OnMediaLoaded(self, evt):
173
173
  self.ss.range = (0, self.video_dur, 0.01)
174
174
  self.to.range = (0, self.video_dur, 0.01)
175
175
  self.Show()
176
176
  evt.Skip()
177
-
177
+
178
178
  def load_media(self, path=None):
179
179
  if path is None:
180
180
  with wx.FileDialog(self, "Choose a media file",
@@ -202,19 +202,19 @@ class Plugin(Layer):
202
202
  else:
203
203
  self.message(f"Failed to load file {path!r}.")
204
204
  return False
205
-
205
+
206
206
  DELTA = 1000 # correction ▲理由は不明 (WMP10 backend only?)
207
-
207
+
208
208
  def set_offset(self, tc):
209
209
  """Set offset value by referring to ss/to value."""
210
210
  if self._path:
211
211
  self.mc.Seek(self.DELTA + int(tc.value * 1000))
212
-
212
+
213
213
  def get_offset(self, tc):
214
214
  """Get offset value and assigns it to ss/to value."""
215
215
  if self._path:
216
216
  tc.value = round(self.mc.Tell()) / 1000
217
-
217
+
218
218
  def set_crop(self):
219
219
  """Set crop area (W:H:Left:Top) to ROI."""
220
220
  if not self._path:
@@ -230,7 +230,7 @@ class Plugin(Layer):
230
230
  frame.region = frame.xyfrompixel(nx, ny)
231
231
  except Exception:
232
232
  self.message("Failed to evaluate crop text.")
233
-
233
+
234
234
  def get_crop(self):
235
235
  """Get crop area (W:H:Left:Top) from ROI."""
236
236
  if not self._path:
@@ -246,7 +246,7 @@ class Plugin(Layer):
246
246
  if not crop:
247
247
  crop = "{}:{}:0:0".format(*self.video_size)
248
248
  self.crop.Value = crop
249
-
249
+
250
250
  def seekto(self, offset):
251
251
  """Seek position with offset [ms] from the `to` position."""
252
252
  if self._path:
@@ -254,14 +254,14 @@ class Plugin(Layer):
254
254
  if 0 <= t < self.video_dur:
255
255
  self.to.value = round(t, 3)
256
256
  self.set_offset(self.to)
257
-
257
+
258
258
  def seekd(self, offset):
259
259
  """Seek position with offset [ms] from the current position."""
260
260
  if self._path:
261
261
  t = self.mc.Tell() + offset
262
262
  if 0 <= t < self.video_dur * 1000:
263
263
  self.mc.Seek(self.DELTA + t)
264
-
264
+
265
265
  def snapshot(self):
266
266
  """Create a snapshot of the current frame.
267
267
  Load the snapshot image into the graph window.
@@ -273,7 +273,7 @@ class Plugin(Layer):
273
273
  buf = capture_video(self._path, t/1000).reshape((h,w,3))
274
274
  name = "{}-ss{}".format(os.path.basename(self._path), int(t))
275
275
  self.graph.load(buf, name)
276
-
276
+
277
277
  def export(self):
278
278
  """Export the cropped / clipped data to a media file."""
279
279
  if not self._path:
mwx/plugins/fft_view.py CHANGED
@@ -28,7 +28,7 @@ class Plugin(Layer):
28
28
  """
29
29
  menukey = "Plugins/Extensions/&FFT view\tAlt+f"
30
30
  caption = "FFT view"
31
-
31
+
32
32
  def Init(self):
33
33
  self.pchk = wx.CheckBox(self, label="logical unit")
34
34
  self.pchk.Value = True
@@ -40,12 +40,12 @@ class Plugin(Layer):
40
40
 
41
41
  self.parent.define_key('C-f', self.newfft)
42
42
  self.parent.define_key('C-S-f', self.newifft)
43
-
43
+
44
44
  def Destroy(self):
45
45
  self.parent.undefine_key('C-f')
46
46
  self.parent.undefine_key('C-S-f')
47
47
  return Layer.Destroy(self)
48
-
48
+
49
49
  def newfft(self):
50
50
  """New FFT of graph to output."""
51
51
  frame = self.graph.frame
@@ -62,7 +62,7 @@ class Plugin(Layer):
62
62
  u /= frame.unit
63
63
  self.output.load(dst, f"*fft of {frame.name}*", localunit=u)
64
64
  self.message("\b done")
65
-
65
+
66
66
  def newifft(self):
67
67
  """New inverse FFT of output to graph."""
68
68
  frame = self.output.frame
@@ -21,15 +21,15 @@ class CheckList(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
21
21
  @property
22
22
  def selected_items(self):
23
23
  return filter(self.IsSelected, range(self.ItemCount))
24
-
24
+
25
25
  @property
26
26
  def checked_items(self):
27
27
  return filter(self.IsItemChecked, range(self.ItemCount))
28
-
28
+
29
29
  @property
30
30
  def focused_item(self):
31
31
  return self.FocusedItem
32
-
32
+
33
33
  @property
34
34
  def all_items(self):
35
35
  rows = range(self.ItemCount)
@@ -37,7 +37,7 @@ class CheckList(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
37
37
  ## return [[self.GetItemText(j, k) for k in cols] for j in rows]
38
38
  for j in rows:
39
39
  yield [self.GetItemText(j, k) for k in cols]
40
-
40
+
41
41
  def __init__(self, parent, target, **kwargs):
42
42
  wx.ListCtrl.__init__(self, parent, size=(400,130),
43
43
  style=wx.LC_REPORT|wx.LC_HRULES, **kwargs)
@@ -115,11 +115,11 @@ class CheckList(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
115
115
  ]
116
116
  self.Bind(wx.EVT_CONTEXT_MENU,
117
117
  lambda v: Menu.Popup(self, self.menu))
118
-
118
+
119
119
  def Destroy(self):
120
120
  self.Target.handler.remove(self.context)
121
121
  return wx.ListCtrl.Destroy(self)
122
-
122
+
123
123
  def UpdateInfo(self, frame):
124
124
  ls = ("{}".format(frame.index),
125
125
  "{}".format(frame.name),
@@ -134,13 +134,13 @@ class CheckList(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
134
134
  self.SetItem(j, k, v)
135
135
  if frame.pathname:
136
136
  self.CheckItem(j)
137
-
137
+
138
138
  def OnShowItems(self, evt):
139
139
  self.Target.select(self.focused_item)
140
-
140
+
141
141
  def OnRemoveItems(self, evt):
142
142
  del self.Target[self.selected_items]
143
-
143
+
144
144
  def OnSortItems(self, evt): #<wx._controls.ListEvent>
145
145
  col = evt.Column
146
146
  if col == 0: # reverse the first column
@@ -166,14 +166,14 @@ class CheckList(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
166
166
  for k, v in enumerate(c[1:]): # update data except for id(0)
167
167
  self.SetItem(j, k+1, v)
168
168
  self.Target.select(frame) # invokes [frame_shown] to select the item
169
-
169
+
170
170
  def OnSelectAllItems(self, evt):
171
171
  for j in range(self.ItemCount):
172
172
  self.Select(j)
173
-
173
+
174
174
  def OnLoadItems(self, evt):
175
175
  self.parent.parent.load_index(view=self.Target)
176
-
176
+
177
177
  def OnSaveItems(self, evt):
178
178
  selected_frames = [self.Target.all_frames[j] for j in self.selected_items]
179
179
  if selected_frames:
@@ -181,7 +181,7 @@ class CheckList(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
181
181
  self.parent.parent.save_index(frames=selected_frames)
182
182
  else:
183
183
  self.parent.message("No frame selected.")
184
-
184
+
185
185
  def OnCopyInfo(self, evt):
186
186
  selected_frames = [self.Target.all_frames[j] for j in self.selected_items]
187
187
  if selected_frames:
@@ -191,7 +191,7 @@ class CheckList(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
191
191
  Clipboard.write('\n'.join(text))
192
192
  else:
193
193
  self.parent.message("No frame selected.")
194
-
194
+
195
195
  def OnEditLocalUnit(self, evt):
196
196
  frame = self.Target.all_frames[self.focused_item]
197
197
  with wx.TextEntryDialog(self, frame.name,
@@ -199,7 +199,7 @@ class CheckList(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
199
199
  if dlg.ShowModal() == wx.ID_OK:
200
200
  frame.unit = eval(dlg.Value or 'None')
201
201
  self.SetFocus()
202
-
202
+
203
203
  def OnEditAnnotation(self, evt):
204
204
  frame = self.Target.all_frames[self.focused_item]
205
205
  with wx.TextEntryDialog(self, frame.name,
@@ -207,34 +207,34 @@ class CheckList(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
207
207
  if dlg.ShowModal() == wx.ID_OK:
208
208
  frame.annotation = dlg.Value
209
209
  self.SetFocus()
210
-
210
+
211
211
  def OnItemSelected(self, evt):
212
212
  frame = self.Target.all_frames[evt.Index]
213
213
  self.parent.message(frame.pathname)
214
214
  evt.Skip()
215
-
215
+
216
216
  ## --------------------------------
217
217
  ## Actions of frame-handler
218
218
  ## --------------------------------
219
-
219
+
220
220
  def on_frame_loaded(self, frame):
221
221
  j = frame.index
222
222
  self.InsertItem(j, str(j))
223
223
  for k in range(j+1, self.ItemCount): # id(0) を更新する
224
224
  self.SetItem(k, 0, str(k))
225
225
  self.UpdateInfo(frame)
226
-
226
+
227
227
  def on_frame_shown(self, frame):
228
228
  j = frame.index
229
229
  self.SetItemFont(j, self.Font.Bold())
230
230
  self.Select(j)
231
231
  self.Focus(j)
232
-
232
+
233
233
  def on_frame_hidden(self, frame):
234
234
  j = frame.index
235
235
  self.SetItemFont(j, self.Font)
236
236
  self.Select(j, False)
237
-
237
+
238
238
  def on_frames_removed(self, indices):
239
239
  with wx.FrozenWindow(self):
240
240
  for j in reversed(indices):
@@ -249,15 +249,15 @@ class Plugin(Layer):
249
249
  menukey = "Plugins/Extensions/&Buffer listbox\tAlt+b"
250
250
  caption = "Property list"
251
251
  dockable = False
252
-
252
+
253
253
  @property
254
254
  def all_pages(self):
255
255
  return [self.nb.GetPage(i) for i in range(self.nb.PageCount)]
256
-
256
+
257
257
  @property
258
258
  def message(self):
259
259
  return self.statusline
260
-
260
+
261
261
  def Init(self):
262
262
  self.nb = aui.AuiNotebook(self, size=(400,150),
263
263
  style = (aui.AUI_NB_DEFAULT_STYLE|aui.AUI_NB_RIGHT)
@@ -278,12 +278,12 @@ class Plugin(Layer):
278
278
  self.parent.select_view(self.nb.CurrentPage.Target)
279
279
  evt.Skip()
280
280
  self.nb.Bind(wx.EVT_CHILD_FOCUS, on_focus_set)
281
-
281
+
282
282
  def attach(self, target, caption):
283
283
  if target not in [lc.Target for lc in self.all_pages]:
284
284
  lc = CheckList(self, target)
285
285
  self.nb.AddPage(lc, caption)
286
-
286
+
287
287
  def detach(self, target):
288
288
  for k, lc in enumerate(self.all_pages):
289
289
  if target is lc.Target:
@@ -11,7 +11,7 @@ class Plugin(Layer):
11
11
  menukey = "Plugins/Extensions/&Line profile\tAlt+l"
12
12
  caption = "Line profile"
13
13
  dockable = False
14
-
14
+
15
15
  def Init(self):
16
16
  self.plot = LineProfile(self, log=self.message, size=(300,200))
17
17
 
mwx/utilus.py CHANGED
@@ -467,15 +467,15 @@ def get_rootpath(fn):
467
467
  ## --------------------------------
468
468
 
469
469
  class SSM(dict):
470
- """Single State Machine/Context of FSM
470
+ """Single State Machine/Context of FSM.
471
471
  """
472
472
  def __call__(self, event, *args, **kwargs):
473
473
  for act in self[event]:
474
474
  act(*args, **kwargs)
475
-
475
+
476
476
  def __repr__(self):
477
477
  return "<{} object at 0x{:X}>".format(self.__class__.__name__, id(self))
478
-
478
+
479
479
  def __str__(self):
480
480
  def _lstr(v):
481
481
  def _name(a):
@@ -484,7 +484,7 @@ class SSM(dict):
484
484
  return repr(a)
485
485
  return ', '.join(_name(a) for a in v)
486
486
  return '\n'.join("{:>32} : {}".format(str(k), _lstr(v)) for k, v in self.items())
487
-
487
+
488
488
  def bind(self, event, action=None):
489
489
  """Append a transaction to the context."""
490
490
  assert callable(action) or action is None
@@ -496,7 +496,7 @@ class SSM(dict):
496
496
  if action not in transaction:
497
497
  transaction.append(action)
498
498
  return action
499
-
499
+
500
500
  def unbind(self, event, action=None):
501
501
  """Remove a transaction from the context."""
502
502
  assert callable(action) or action is None
@@ -513,7 +513,7 @@ class SSM(dict):
513
513
 
514
514
 
515
515
  class FSM(dict):
516
- """Finite State Machine
516
+ """Finite State Machine.
517
517
 
518
518
  Args:
519
519
  contexts: map of context <DNA>
@@ -544,20 +544,20 @@ class FSM(dict):
544
544
  There is no enter/exit event handler.
545
545
  """
546
546
  debug = 0
547
-
547
+
548
548
  default_state = None
549
549
  current_state = property(lambda self: self.__state)
550
550
  previous_state = property(lambda self: self.__prev_state)
551
-
551
+
552
552
  current_event = property(lambda self: self.__event)
553
553
  previous_event = property(lambda self: self.__prev_event)
554
-
554
+
555
555
  @current_state.setter
556
556
  def current_state(self, state):
557
557
  self.__state = state
558
558
  self.__event = '*forced*'
559
559
  self.__debcall__(self.__event)
560
-
560
+
561
561
  def clear(self, state):
562
562
  """Reset current and previous states."""
563
563
  self.__state = state
@@ -565,7 +565,7 @@ class FSM(dict):
565
565
  self.__event = None
566
566
  self.__prev_event = None
567
567
  self.__matched_pattern = None
568
-
568
+
569
569
  def __init__(self, contexts=None, default=None):
570
570
  dict.__init__(self) # update dict, however, it does not clear
571
571
  dict.clear(self) # if and when __init__ is called, all contents are cleared
@@ -577,16 +577,16 @@ class FSM(dict):
577
577
  self.default_state = default
578
578
  self.clear(default) # the first clear creates object localvars
579
579
  self.update(contexts)
580
-
580
+
581
581
  def __missing__(self, key):
582
582
  raise Exception("FSM logic-error: undefined state {!r}".format(key))
583
-
583
+
584
584
  def __repr__(self):
585
585
  return "<{} object at 0x{:X}>".format(self.__class__.__name__, id(self))
586
-
586
+
587
587
  def __str__(self):
588
588
  return '\n'.join("[ {!r} ]\n{!s}".format(k, v) for k, v in self.items())
589
-
589
+
590
590
  def __call__(self, event, *args, **kwargs):
591
591
  """Handle the event.
592
592
 
@@ -629,7 +629,7 @@ class FSM(dict):
629
629
  self.__prev_state = self.__state
630
630
  if recept:
631
631
  return retvals
632
-
632
+
633
633
  def fork(self, event, *args, **kwargs):
634
634
  """Invoke the event handlers (internal use only).
635
635
 
@@ -640,7 +640,7 @@ class FSM(dict):
640
640
  ret = self.call(event, *args, **kwargs)
641
641
  self.__prev_event = self.__event
642
642
  return ret
643
-
643
+
644
644
  def call(self, event, *args, **kwargs):
645
645
  """Invoke the event handlers (internal use only).
646
646
 
@@ -690,7 +690,7 @@ class FSM(dict):
690
690
 
691
691
  self.__debcall__(event, *args, **kwargs) # check when no transition
692
692
  return None # no event, no action
693
-
693
+
694
694
  def __debcall__(self, pattern, *args, **kwargs):
695
695
  v = self.debug
696
696
  if v and self.__state is not None:
@@ -715,11 +715,11 @@ class FSM(dict):
715
715
 
716
716
  if v > 7: # max verbose level puts all args
717
717
  self.log("\t:", args, kwargs)
718
-
718
+
719
719
  @staticmethod
720
720
  def log(*args):
721
721
  print(*args, file=sys.__stdout__)
722
-
722
+
723
723
  @staticmethod
724
724
  def dump(*args):
725
725
  fn = get_rootpath("deb-dump.log")
@@ -727,7 +727,7 @@ class FSM(dict):
727
727
  print(time.strftime('!!! %Y/%m/%d %H:%M:%S'), file=o)
728
728
  print(*args, traceback.format_exc(), sep='\n', file=o)
729
729
  print(*args, traceback.format_exc(), sep='\n', file=sys.__stderr__)
730
-
730
+
731
731
  @staticmethod
732
732
  def duplicate(context):
733
733
  """Duplicate the transaction:list in the context.
@@ -736,7 +736,7 @@ class FSM(dict):
736
736
  so that the original transaction (if they are lists) is not removed.
737
737
  """
738
738
  return {event: transaction[:] for event, transaction in context.items()}
739
-
739
+
740
740
  def validate(self, state):
741
741
  """Sort and move to end items with key which includes ``*?[]``."""
742
742
  context = self[state]
@@ -753,7 +753,7 @@ class FSM(dict):
753
753
  context.update(temp)
754
754
  context.update(sorted(bra, reverse=1))
755
755
  context.update(sorted(ast, reverse=1, key=lambda v: len(v[0])))
756
-
756
+
757
757
  def update(self, contexts):
758
758
  """Update each context or Add new contexts."""
759
759
  for k, v in contexts.items():
@@ -762,7 +762,7 @@ class FSM(dict):
762
762
  else:
763
763
  self[k] = SSM(self.duplicate(v)) # new context
764
764
  self.validate(k)
765
-
765
+
766
766
  def append(self, contexts):
767
767
  """Append new contexts."""
768
768
  for k, v in contexts.items():
@@ -776,7 +776,7 @@ class FSM(dict):
776
776
  else:
777
777
  self[k] = SSM(self.duplicate(v)) # new context
778
778
  self.validate(k)
779
-
779
+
780
780
  def remove(self, contexts):
781
781
  """Remove old contexts."""
782
782
  for k, v in contexts.items():
@@ -791,7 +791,7 @@ class FSM(dict):
791
791
  for k, v in list(self.items()): # self mutates during iteration
792
792
  if not v:
793
793
  del self[k]
794
-
794
+
795
795
  def bind(self, event, action=None, state=None, state2=None):
796
796
  """Append a transaction to the context.
797
797
 
@@ -835,7 +835,7 @@ class FSM(dict):
835
835
  warn(f"- FSM cannot append new transaction ({state!r} : {event!r}).\n"
836
836
  f" The transaction must be a list, not a tuple.")
837
837
  return action
838
-
838
+
839
839
  def binds(self, event, action=None, state=None, state2=None):
840
840
  """Append a one-time transaction to the context.
841
841
 
@@ -851,7 +851,7 @@ class FSM(dict):
851
851
  finally:
852
852
  self.unbind(event, _act, state)
853
853
  return self.bind(event, _act, state, state2)
854
-
854
+
855
855
  def unbind(self, event, action=None, state=None):
856
856
  """Remove a transaction from the context.
857
857
 
@@ -901,41 +901,41 @@ class TreeList:
901
901
  """
902
902
  def __init__(self, ls=None):
903
903
  self.__items = ls or []
904
-
904
+
905
905
  def __call__(self, k):
906
906
  return TreeList(self[k])
907
-
907
+
908
908
  def __len__(self):
909
909
  return len(self.__items)
910
-
910
+
911
911
  def __contains__(self, k):
912
912
  return self._getf(self.__items, k)
913
-
913
+
914
914
  def __iter__(self):
915
915
  return self.__items.__iter__()
916
-
916
+
917
917
  def __getitem__(self, k):
918
918
  if isinstance(k, str):
919
919
  return self._getf(self.__items, k)
920
920
  return self.__items.__getitem__(k)
921
-
921
+
922
922
  def __setitem__(self, k, v):
923
923
  if isinstance(k, str):
924
924
  return self._setf(self.__items, k, v)
925
925
  return self.__items.__setitem__(k, v)
926
-
926
+
927
927
  def __delitem__(self, k):
928
928
  if isinstance(k, str):
929
929
  return self._delf(self.__items, k)
930
930
  return self.__items.__delitem__(k)
931
-
931
+
932
932
  def _find_item(self, ls, key):
933
933
  for x in ls:
934
934
  if isinstance(x, (tuple, list)) and x and x[0] == key:
935
935
  if len(x) < 2:
936
936
  raise ValueError(f"No value for {key=!r}")
937
937
  return x
938
-
938
+
939
939
  def _getf(self, ls, key):
940
940
  if '/' in key:
941
941
  a, b = key.split('/', 1)
@@ -946,7 +946,7 @@ class TreeList:
946
946
  li = self._find_item(ls, key)
947
947
  if li is not None:
948
948
  return li[-1]
949
-
949
+
950
950
  def _setf(self, ls, key, value):
951
951
  if '/' in key:
952
952
  a, b = key.split('/', 1)
@@ -966,7 +966,7 @@ class TreeList:
966
966
  ls.append([key, value]) # append to items:list
967
967
  except (ValueError, TypeError, AttributeError) as e:
968
968
  warn(f"- TreeList {e!r}: {key=!r}")
969
-
969
+
970
970
  def _delf(self, ls, key):
971
971
  if '/' in key:
972
972
  p, key = key.rsplit('/', 1)
@@ -1055,7 +1055,7 @@ def get_fullargspec(f):
1055
1055
 
1056
1056
 
1057
1057
  def funcall(f, *args, doc=None, alias=None, **kwargs):
1058
- """Decorator of event handler
1058
+ """Decorator of event handler.
1059
1059
 
1060
1060
  Check if the event argument can be omitted and if any other
1061
1061
  required arguments are specified in args and kwargs.