mwxlib 1.1.7__py3-none-any.whl → 1.2.3__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/__init__.py +1 -1
- mwx/controls.py +21 -17
- mwx/framework.py +1 -1
- mwx/graphman.py +16 -11
- mwx/matplot2.py +4 -4
- mwx/matplot2g.py +95 -82
- mwx/mgplt.py +1 -1
- mwx/nutshell.py +60 -77
- mwx/plugins/ffmpeg_view.py +11 -15
- {mwxlib-1.1.7.dist-info → mwxlib-1.2.3.dist-info}/METADATA +1 -1
- {mwxlib-1.1.7.dist-info → mwxlib-1.2.3.dist-info}/RECORD +14 -14
- {mwxlib-1.1.7.dist-info → mwxlib-1.2.3.dist-info}/LICENSE +0 -0
- {mwxlib-1.1.7.dist-info → mwxlib-1.2.3.dist-info}/WHEEL +0 -0
- {mwxlib-1.1.7.dist-info → mwxlib-1.2.3.dist-info}/top_level.txt +0 -0
mwx/__init__.py
CHANGED
|
@@ -8,7 +8,7 @@ from .framework import Frame, MiniFrame, ShellFrame, deb
|
|
|
8
8
|
|
|
9
9
|
## Controls
|
|
10
10
|
from .controls import Param, LParam, Knob, ControlPanel, Clipboard, Icon
|
|
11
|
-
from .controls import Button, ToggleButton, ClassicButton,
|
|
11
|
+
from .controls import Button, ToggleButton, ClassicButton, TextBox, Choice, Gauge, Indicator
|
|
12
12
|
|
|
13
13
|
## Plugman
|
|
14
14
|
## from .graphman import Frame as GraphmanFrame, Layer, Thread, Graph
|
mwx/controls.py
CHANGED
|
@@ -712,24 +712,25 @@ class KnobCtrlPanel(scrolled.ScrolledPanel):
|
|
|
712
712
|
return params
|
|
713
713
|
return filter(lambda c: getattr(c, 'check', None), params)
|
|
714
714
|
|
|
715
|
-
def set_params(self, argv
|
|
715
|
+
def set_params(self, argv, checked_only=False):
|
|
716
716
|
params = self.get_params(checked_only)
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
for p, v in zip(params, argv):
|
|
725
|
-
try:
|
|
726
|
-
p.reset(v) # eval v:str -> value
|
|
727
|
-
except AttributeError:
|
|
728
|
-
p.value = v
|
|
729
|
-
except Exception as e: # failed to eval
|
|
730
|
-
print(f"- Failed to reset {p!r}.", e)
|
|
717
|
+
for p, v in zip(params, argv):
|
|
718
|
+
try:
|
|
719
|
+
p.reset(v) # eval v:str -> value
|
|
720
|
+
except AttributeError:
|
|
721
|
+
p.value = v
|
|
722
|
+
except Exception as e:
|
|
723
|
+
print(f"- Failed to eval {v}:", e)
|
|
731
724
|
|
|
732
|
-
reset_params =
|
|
725
|
+
def reset_params(self, checked_only=False):
|
|
726
|
+
params = self.get_params(checked_only)
|
|
727
|
+
for p in params:
|
|
728
|
+
try:
|
|
729
|
+
p.reset()
|
|
730
|
+
except (AttributeError, TypeError):
|
|
731
|
+
## TypeError might occur if p.reset(v) is called with
|
|
732
|
+
## missing 1 required positional argument.
|
|
733
|
+
pass
|
|
733
734
|
|
|
734
735
|
def copy_to_clipboard(self, checked_only=False):
|
|
735
736
|
params = self.get_params(checked_only)
|
|
@@ -1041,7 +1042,7 @@ class ToggleButton(wx.ToggleButton):
|
|
|
1041
1042
|
self.SetBitmap(Icon(icon))
|
|
1042
1043
|
|
|
1043
1044
|
|
|
1044
|
-
class
|
|
1045
|
+
class TextBox(wx.Control):
|
|
1045
1046
|
"""Text control
|
|
1046
1047
|
|
|
1047
1048
|
Args:
|
|
@@ -1095,6 +1096,9 @@ class TextCtrl(wx.Control):
|
|
|
1095
1096
|
pass
|
|
1096
1097
|
|
|
1097
1098
|
|
|
1099
|
+
TextCtrl = TextBox #: for backward compatibility
|
|
1100
|
+
|
|
1101
|
+
|
|
1098
1102
|
class Choice(wx.Control):
|
|
1099
1103
|
"""Editable Choice (ComboBox) control
|
|
1100
1104
|
|
mwx/framework.py
CHANGED
mwx/graphman.py
CHANGED
|
@@ -16,6 +16,7 @@ import platform
|
|
|
16
16
|
import re
|
|
17
17
|
import wx
|
|
18
18
|
from wx import aui
|
|
19
|
+
from wx import stc
|
|
19
20
|
|
|
20
21
|
from matplotlib import cm
|
|
21
22
|
from matplotlib import colors
|
|
@@ -322,18 +323,22 @@ class LayerInterface(CtrlInterface):
|
|
|
322
323
|
except AttributeError:
|
|
323
324
|
self.parameters = None
|
|
324
325
|
|
|
325
|
-
def copy_params(
|
|
326
|
-
if
|
|
327
|
-
|
|
326
|
+
def copy_params(evt, checked_only=False):
|
|
327
|
+
if isinstance(evt.EventObject, (wx.TextEntry, stc.StyledTextCtrl)):
|
|
328
|
+
evt.Skip()
|
|
329
|
+
elif self.parameters:
|
|
330
|
+
self.copy_to_clipboard(checked_only)
|
|
328
331
|
|
|
329
|
-
def paste_params(
|
|
330
|
-
if
|
|
331
|
-
|
|
332
|
+
def paste_params(evt, checked_only=False):
|
|
333
|
+
if isinstance(evt.EventObject, (wx.TextEntry, stc.StyledTextCtrl)):
|
|
334
|
+
evt.Skip()
|
|
335
|
+
elif self.parameters:
|
|
336
|
+
self.paste_from_clipboard(checked_only)
|
|
332
337
|
|
|
333
|
-
def reset_params(
|
|
338
|
+
def reset_params(evt, checked_only=False):
|
|
334
339
|
self.Draw(None)
|
|
335
340
|
if self.parameters:
|
|
336
|
-
|
|
341
|
+
self.reset_params(checked_only)
|
|
337
342
|
|
|
338
343
|
self.handler.append({ # DNA<Layer>
|
|
339
344
|
None : {
|
|
@@ -356,15 +361,15 @@ class LayerInterface(CtrlInterface):
|
|
|
356
361
|
})
|
|
357
362
|
self.menu = [
|
|
358
363
|
(wx.ID_COPY, "&Copy params\t(C-c)", "Copy params",
|
|
359
|
-
lambda v: copy_params(checked_only=wx.GetKeyState(wx.WXK_SHIFT)),
|
|
364
|
+
lambda v: copy_params(v, checked_only=wx.GetKeyState(wx.WXK_SHIFT)),
|
|
360
365
|
lambda v: v.Enable(bool(self.parameters))),
|
|
361
366
|
|
|
362
367
|
(wx.ID_PASTE, "&Paste params\t(C-v)", "Read params",
|
|
363
|
-
lambda v: paste_params(checked_only=wx.GetKeyState(wx.WXK_SHIFT)),
|
|
368
|
+
lambda v: paste_params(v, checked_only=wx.GetKeyState(wx.WXK_SHIFT)),
|
|
364
369
|
lambda v: v.Enable(bool(self.parameters))),
|
|
365
370
|
(),
|
|
366
371
|
(wx.ID_RESET, "&Reset params\t(C-n)", "Reset params", Icon('-'),
|
|
367
|
-
lambda v: reset_params(checked_only=wx.GetKeyState(wx.WXK_SHIFT)),
|
|
372
|
+
lambda v: reset_params(v, checked_only=wx.GetKeyState(wx.WXK_SHIFT)),
|
|
368
373
|
lambda v: v.Enable(bool(self.parameters))),
|
|
369
374
|
(),
|
|
370
375
|
(wx.ID_EDIT, "&Edit module", "Edit module", Icon('pen'),
|
mwx/matplot2.py
CHANGED
|
@@ -348,22 +348,22 @@ class MatplotPanel(wx.Panel):
|
|
|
348
348
|
xbound = property(
|
|
349
349
|
lambda self: np.array(self.axes.get_xbound()),
|
|
350
350
|
lambda self,v: self.axes.set_xbound(v),
|
|
351
|
-
doc="
|
|
351
|
+
doc="X-axis numerical bounds where lowerBound < upperBound)")
|
|
352
352
|
|
|
353
353
|
ybound = property(
|
|
354
354
|
lambda self: np.array(self.axes.get_ybound()),
|
|
355
355
|
lambda self,v: self.axes.set_ybound(v),
|
|
356
|
-
doc="
|
|
356
|
+
doc="Y-axis numerical bounds where lowerBound < upperBound)")
|
|
357
357
|
|
|
358
358
|
xlim = property(
|
|
359
359
|
lambda self: np.array(self.axes.get_xlim()),
|
|
360
360
|
lambda self,v: self.axes.set_xlim(v),
|
|
361
|
-
doc="
|
|
361
|
+
doc="X-axis range [left, right]")
|
|
362
362
|
|
|
363
363
|
ylim = property(
|
|
364
364
|
lambda self: np.array(self.axes.get_ylim()),
|
|
365
365
|
lambda self,v: self.axes.set_ylim(v),
|
|
366
|
-
doc="
|
|
366
|
+
doc="Y-axis range [bottom, top]")
|
|
367
367
|
|
|
368
368
|
@property
|
|
369
369
|
def ddpu(self):
|
mwx/matplot2g.py
CHANGED
|
@@ -14,7 +14,7 @@ from scipy import ndimage as ndi
|
|
|
14
14
|
|
|
15
15
|
from . import framework as mwx
|
|
16
16
|
from .framework import Menu
|
|
17
|
-
|
|
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
|
|
@@ -88,7 +88,7 @@ def _to_image(src, cutoff=0, threshold=None, binning=1):
|
|
|
88
88
|
if src.dtype == np.uint8: # RGB or gray image <uint8>
|
|
89
89
|
return bins, (0, 255), src
|
|
90
90
|
|
|
91
|
-
if hasattr(cutoff, '__iter__'): # cutoff vlim:
|
|
91
|
+
if hasattr(cutoff, '__iter__'): # cutoff vlim: (vmin, vmax) is specified.
|
|
92
92
|
a, b = cutoff
|
|
93
93
|
elif cutoff > 0:
|
|
94
94
|
a = np.percentile(src, cutoff)
|
|
@@ -129,7 +129,7 @@ class AxesImagePhantom:
|
|
|
129
129
|
"""
|
|
130
130
|
def __init__(self, parent, buf, name, show=True,
|
|
131
131
|
localunit=None, aspect=1.0, **attributes):
|
|
132
|
-
self.
|
|
132
|
+
self.parent = parent
|
|
133
133
|
self.__name = name
|
|
134
134
|
self.__localunit = localunit or None # [+] value, no assertion
|
|
135
135
|
self.__aspect_ratio = aspect
|
|
@@ -141,7 +141,7 @@ class AxesImagePhantom:
|
|
|
141
141
|
threshold = self.parent.nbytes_threshold,
|
|
142
142
|
)
|
|
143
143
|
self.__bins = bins
|
|
144
|
-
self.
|
|
144
|
+
self.__cuts = vlim
|
|
145
145
|
self.__art = parent.axes.imshow(img,
|
|
146
146
|
cmap = cm.gray,
|
|
147
147
|
aspect = 'equal',
|
|
@@ -157,39 +157,6 @@ class AxesImagePhantom:
|
|
|
157
157
|
def __eq__(self, x):
|
|
158
158
|
return x is self.__art
|
|
159
159
|
|
|
160
|
-
parent = property(lambda self: self.__owner)
|
|
161
|
-
artist = property(lambda self: self.__art)
|
|
162
|
-
name = property(lambda self: self.__name)
|
|
163
|
-
buffer = property(lambda self: self.__buf) # buffer.setter is defined below.
|
|
164
|
-
binning = property(lambda self: self.__bins)
|
|
165
|
-
|
|
166
|
-
image = property(
|
|
167
|
-
lambda self: self.__art.get_array(),
|
|
168
|
-
doc="A displayed image array<uint8>.")
|
|
169
|
-
|
|
170
|
-
vlim = property(
|
|
171
|
-
lambda self: self.__vlim,
|
|
172
|
-
doc="Image lower/upper values.")
|
|
173
|
-
|
|
174
|
-
clim = property(
|
|
175
|
-
lambda self: self.__art.get_clim(),
|
|
176
|
-
lambda self,v: self.__art.set_clim(v),
|
|
177
|
-
doc="Buffer lower/upper values.")
|
|
178
|
-
|
|
179
|
-
attributes = property(
|
|
180
|
-
lambda self: self.__attributes,
|
|
181
|
-
doc="Miscellaneous info about the frame/buffer.")
|
|
182
|
-
|
|
183
|
-
pathname = property(
|
|
184
|
-
lambda self: self.__attributes.get('pathname'),
|
|
185
|
-
lambda self,v: self.update_attributes({'pathname': v}),
|
|
186
|
-
doc="A fullpath of buffer, when bounds to file.")
|
|
187
|
-
|
|
188
|
-
annotation = property(
|
|
189
|
-
lambda self: self.__attributes.get('annotation', ''),
|
|
190
|
-
lambda self,v: self.update_attributes({'annotation': v}),
|
|
191
|
-
doc="Annotation of the buffer.")
|
|
192
|
-
|
|
193
160
|
def update_attributes(self, attr=None, **kwargs):
|
|
194
161
|
"""Update frame-specifc attributes.
|
|
195
162
|
The frame holds any attributes with dictionary
|
|
@@ -215,10 +182,70 @@ class AxesImagePhantom:
|
|
|
215
182
|
if {'pathname', 'annotation'} & attr.keys():
|
|
216
183
|
self.parent.handler('frame_updated', self)
|
|
217
184
|
|
|
185
|
+
def update_buffer(self, buf=None):
|
|
186
|
+
"""Update buffer and the image (internal use only)."""
|
|
187
|
+
if buf is not None:
|
|
188
|
+
self.__buf = _to_buffer(buf)
|
|
189
|
+
|
|
190
|
+
bins, vlim, img = _to_image(self.__buf,
|
|
191
|
+
cutoff = self.parent.score_percentile,
|
|
192
|
+
threshold = self.parent.nbytes_threshold,
|
|
193
|
+
)
|
|
194
|
+
self.__bins = bins
|
|
195
|
+
self.__cuts = vlim
|
|
196
|
+
self.__art.set_array(img)
|
|
197
|
+
self.parent.handler('frame_modified', self)
|
|
198
|
+
|
|
199
|
+
def update_extent(self):
|
|
200
|
+
"""Update logical extent of the image (internal use only)."""
|
|
201
|
+
h, w = self.__buf.shape[:2]
|
|
202
|
+
ux, uy = self.xy_unit
|
|
203
|
+
w *= ux/2
|
|
204
|
+
h *= uy/2
|
|
205
|
+
self.__art.set_extent((-w,w,-h,h))
|
|
206
|
+
|
|
218
207
|
selector = _Property('Selector')
|
|
219
208
|
markers = _Property('Markers')
|
|
220
209
|
region = _Property('Region')
|
|
221
210
|
|
|
211
|
+
artist = property(
|
|
212
|
+
lambda self: self.__art)
|
|
213
|
+
|
|
214
|
+
binning = property(
|
|
215
|
+
lambda self: self.__bins,
|
|
216
|
+
doc="Binning value resulting from the score_percentile.")
|
|
217
|
+
|
|
218
|
+
cuts = property(
|
|
219
|
+
lambda self: self.__cuts,
|
|
220
|
+
doc="Lower/Upper cutoff values of the buffer.")
|
|
221
|
+
|
|
222
|
+
image = property(
|
|
223
|
+
lambda self: self.__art.get_array(),
|
|
224
|
+
doc="A displayed image array<uint8>.")
|
|
225
|
+
|
|
226
|
+
clim = property(
|
|
227
|
+
lambda self: self.__art.get_clim(),
|
|
228
|
+
lambda self,v: self.__art.set_clim(v),
|
|
229
|
+
doc="Lower/Upper color limit values of the buffer.")
|
|
230
|
+
|
|
231
|
+
attributes = property(
|
|
232
|
+
lambda self: self.__attributes,
|
|
233
|
+
doc="Miscellaneous info about the frame/buffer.")
|
|
234
|
+
|
|
235
|
+
pathname = property(
|
|
236
|
+
lambda self: self.__attributes.get('pathname'),
|
|
237
|
+
lambda self,v: self.update_attributes({'pathname': v}),
|
|
238
|
+
doc="A fullpath of buffer, when bounds to file.")
|
|
239
|
+
|
|
240
|
+
annotation = property(
|
|
241
|
+
lambda self: self.__attributes.get('annotation', ''),
|
|
242
|
+
lambda self,v: self.update_attributes({'annotation': v}),
|
|
243
|
+
doc="Annotation of the buffer.")
|
|
244
|
+
|
|
245
|
+
@property
|
|
246
|
+
def name(self):
|
|
247
|
+
return self.__name
|
|
248
|
+
|
|
222
249
|
@name.setter
|
|
223
250
|
def name(self, v):
|
|
224
251
|
self.__name = v
|
|
@@ -278,28 +305,6 @@ class AxesImagePhantom:
|
|
|
278
305
|
"""Page number in the parent book."""
|
|
279
306
|
return self.parent.index(self)
|
|
280
307
|
|
|
281
|
-
def update_buffer(self, buf=None):
|
|
282
|
-
"""Update buffer and the image (internal use only)."""
|
|
283
|
-
if buf is not None:
|
|
284
|
-
self.__buf = _to_buffer(buf)
|
|
285
|
-
|
|
286
|
-
bins, vlim, img = _to_image(self.__buf,
|
|
287
|
-
cutoff = self.parent.score_percentile,
|
|
288
|
-
threshold = self.parent.nbytes_threshold,
|
|
289
|
-
)
|
|
290
|
-
self.__bins = bins
|
|
291
|
-
self.__vlim = vlim
|
|
292
|
-
self.__art.set_array(img)
|
|
293
|
-
self.parent.handler('frame_modified', self)
|
|
294
|
-
|
|
295
|
-
def update_extent(self):
|
|
296
|
-
"""Update logical extent of the image (internal use only)."""
|
|
297
|
-
h, w = self.__buf.shape[:2]
|
|
298
|
-
ux, uy = self.xy_unit
|
|
299
|
-
w *= ux/2
|
|
300
|
-
h *= uy/2
|
|
301
|
-
self.__art.set_extent((-w,w,-h,h))
|
|
302
|
-
|
|
303
308
|
@property
|
|
304
309
|
def roi(self):
|
|
305
310
|
"""Current buffer ROI (region of interest)."""
|
|
@@ -315,9 +320,14 @@ class AxesImagePhantom:
|
|
|
315
320
|
self.roi[:] = v # cannot broadcast input array into different shape
|
|
316
321
|
self.update_buffer()
|
|
317
322
|
|
|
323
|
+
@property
|
|
324
|
+
def buffer(self):
|
|
325
|
+
return self.__buf
|
|
326
|
+
|
|
318
327
|
@buffer.setter
|
|
319
328
|
def buffer(self, v):
|
|
320
329
|
self.update_buffer(v)
|
|
330
|
+
self.update_extent()
|
|
321
331
|
|
|
322
332
|
def xytoc(self, x, y=None, nearest=True):
|
|
323
333
|
"""Convert xydata (x,y) -> data[(x,y)] value of neaerst pixel.
|
|
@@ -618,9 +628,6 @@ class GraphPlot(MatplotPanel):
|
|
|
618
628
|
- aspect : aspect ratio
|
|
619
629
|
- pathname : full path of the buffer file
|
|
620
630
|
"""
|
|
621
|
-
if buf is None:
|
|
622
|
-
return
|
|
623
|
-
|
|
624
631
|
if isinstance(buf, str):
|
|
625
632
|
buf = Image.open(buf)
|
|
626
633
|
|
|
@@ -687,9 +694,6 @@ class GraphPlot(MatplotPanel):
|
|
|
687
694
|
j = self.index(j)
|
|
688
695
|
|
|
689
696
|
buffers = [art.buffer for art in self.__Arts]
|
|
690
|
-
if hasattr(j, '__iter__'):
|
|
691
|
-
return [buffers[i] for i in j]
|
|
692
|
-
|
|
693
697
|
return buffers[j] # j can also be slicing
|
|
694
698
|
|
|
695
699
|
def __setitem__(self, j, v):
|
|
@@ -699,14 +703,14 @@ class GraphPlot(MatplotPanel):
|
|
|
699
703
|
except ValueError:
|
|
700
704
|
return self.load(v, name=j) # new buffer
|
|
701
705
|
|
|
702
|
-
if
|
|
703
|
-
raise ValueError("attempt to assign buffers
|
|
706
|
+
if isinstance(j, slice):
|
|
707
|
+
raise ValueError("attempt to assign buffers via slicing")
|
|
704
708
|
|
|
705
709
|
if v is None:
|
|
706
|
-
|
|
710
|
+
raise ValueError("values must be buffers, not NoneType.")
|
|
707
711
|
else:
|
|
708
712
|
art = self.__Arts[j]
|
|
709
|
-
art.update_buffer(v)
|
|
713
|
+
art.update_buffer(v) # update buffer
|
|
710
714
|
art.update_extent()
|
|
711
715
|
self.select(j)
|
|
712
716
|
|
|
@@ -714,9 +718,7 @@ class GraphPlot(MatplotPanel):
|
|
|
714
718
|
if isinstance(j, str):
|
|
715
719
|
j = self.index(j)
|
|
716
720
|
|
|
717
|
-
if
|
|
718
|
-
arts = [self.__Arts[i] for i in j]
|
|
719
|
-
elif isinstance(j, slice):
|
|
721
|
+
if isinstance(j, slice):
|
|
720
722
|
arts = self.__Arts[j]
|
|
721
723
|
else:
|
|
722
724
|
arts = [self.__Arts[j]]
|
|
@@ -784,16 +786,27 @@ class GraphPlot(MatplotPanel):
|
|
|
784
786
|
if self.__Arts and self.__index is not None:
|
|
785
787
|
return self.__Arts[self.__index]
|
|
786
788
|
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
789
|
+
@property
|
|
790
|
+
def buffer(self):
|
|
791
|
+
"""Current buffer array."""
|
|
792
|
+
if self.frame:
|
|
793
|
+
return self.frame.buffer
|
|
794
|
+
|
|
795
|
+
@buffer.setter
|
|
796
|
+
def buffer(self, v):
|
|
797
|
+
if self.frame:
|
|
798
|
+
self.__setitem__(self.__index, v)
|
|
799
|
+
else:
|
|
800
|
+
self.load(v)
|
|
801
|
+
|
|
802
|
+
@property
|
|
803
|
+
def newbuffer(self):
|
|
804
|
+
"""New buffer loader."""
|
|
805
|
+
return None
|
|
792
806
|
|
|
793
|
-
newbuffer
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
doc="new buffer loader")
|
|
807
|
+
@newbuffer.setter
|
|
808
|
+
def newbuffer(self, v):
|
|
809
|
+
self.load(v)
|
|
797
810
|
|
|
798
811
|
@property
|
|
799
812
|
def unit(self):
|
|
@@ -951,7 +964,7 @@ class GraphPlot(MatplotPanel):
|
|
|
951
964
|
data = frame.roi
|
|
952
965
|
GraphPlot.clipboard_name = name
|
|
953
966
|
GraphPlot.clipboard_data = data
|
|
954
|
-
bins, vlim, img = _to_image(data, frame.
|
|
967
|
+
bins, vlim, img = _to_image(data, frame.cuts)
|
|
955
968
|
Clipboard.imwrite(img)
|
|
956
969
|
self.message("Write buffer to clipboard.")
|
|
957
970
|
except Exception as e:
|
mwx/mgplt.py
CHANGED
|
@@ -139,7 +139,7 @@ class GnuplotFrame(mwx.Frame):
|
|
|
139
139
|
lambda v: self.panel.paste_from_clipboard()),
|
|
140
140
|
(),
|
|
141
141
|
(wx.ID_RESET, "&Reset params\tCtrl-n", "Reset params to ini-value",
|
|
142
|
-
lambda v: self.panel.
|
|
142
|
+
lambda v: self.panel.reset_params()),
|
|
143
143
|
]
|
|
144
144
|
self.menubar["Gnuplot"] = [
|
|
145
145
|
(mwx.ID_(80), "&Gnuplot setting\tCtrl-g", "Edit settings",
|
mwx/nutshell.py
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
from functools import wraps
|
|
5
5
|
from importlib import import_module
|
|
6
6
|
from contextlib import contextmanager
|
|
7
|
+
from pathlib import Path
|
|
7
8
|
from pprint import pformat
|
|
8
9
|
from bdb import BdbQuit
|
|
9
10
|
import traceback
|
|
@@ -32,7 +33,8 @@ from .framework import CtrlInterface, AuiNotebook, Menu
|
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
## URL pattern (flag = re.M | re.A)
|
|
35
|
-
url_re = r"https?://[\w/:%#$&?()~.=+-]+"
|
|
36
|
+
## url_re = r"https?://[\w/:%#$&?()~.=+-]+"
|
|
37
|
+
url_re = r"https?://[\w/:%#$&?~.=+-]+" # excluding ()
|
|
36
38
|
|
|
37
39
|
## no-file pattern
|
|
38
40
|
nofile_re = r'[\/:*?"<>|]'
|
|
@@ -220,21 +222,21 @@ class AutoCompInterfaceMixin:
|
|
|
220
222
|
if self.CallTipActive():
|
|
221
223
|
self.CallTipCancel()
|
|
222
224
|
|
|
223
|
-
text =
|
|
225
|
+
text = self.SelectedText or self.expr_at_caret or self.line_at_caret
|
|
224
226
|
if text:
|
|
225
227
|
text = introspect.getRoot(text, terminator='(')
|
|
226
228
|
try:
|
|
227
229
|
obj = self.eval(text)
|
|
228
230
|
self.help(obj)
|
|
229
231
|
except Exception as e:
|
|
230
|
-
self.message(
|
|
232
|
+
self.message(e)
|
|
231
233
|
|
|
232
234
|
def call_helpTip(self, evt):
|
|
233
235
|
"""Show a calltip for the selected function."""
|
|
234
236
|
if self.CallTipActive():
|
|
235
237
|
self.CallTipCancel()
|
|
236
238
|
|
|
237
|
-
text =
|
|
239
|
+
text = self.SelectedText or self.expr_at_caret or self.line_at_caret
|
|
238
240
|
if text:
|
|
239
241
|
p = self.cpos
|
|
240
242
|
self.autoCallTipShow(text,
|
|
@@ -629,7 +631,7 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
|
|
|
629
631
|
|
|
630
632
|
## Custom indicators ([BUG] indicator=1 is reset when the buffer is udpated.)
|
|
631
633
|
## [10-11] filter_text
|
|
632
|
-
## [2] URL
|
|
634
|
+
## [2] URL
|
|
633
635
|
## [3] match_paren
|
|
634
636
|
self.IndicatorSetStyle(10, stc.STC_INDIC_TEXTFORE)
|
|
635
637
|
self.IndicatorSetForeground(10, "red")
|
|
@@ -1721,10 +1723,18 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
1721
1723
|
return self.__filename
|
|
1722
1724
|
|
|
1723
1725
|
def update_filestamp(self, fn):
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
+
self.__path = Path(fn)
|
|
1727
|
+
if self.__path.is_file():
|
|
1728
|
+
self.__mtime = self.__path.stat().st_mtime # update timestamp (modified time)
|
|
1729
|
+
elif re.match(url_re, fn):
|
|
1730
|
+
self.__mtime = -1
|
|
1726
1731
|
else:
|
|
1727
|
-
|
|
1732
|
+
try:
|
|
1733
|
+
self.__path.resolve(True) # Check if the path format is valid.
|
|
1734
|
+
except FileNotFoundError:
|
|
1735
|
+
self.__mtime = False # valid path (but not found)
|
|
1736
|
+
except OSError:
|
|
1737
|
+
self.__mtime = None # *invalid path*
|
|
1728
1738
|
if self.__filename != fn:
|
|
1729
1739
|
self.__filename = fn
|
|
1730
1740
|
self.update_caption()
|
|
@@ -1735,16 +1745,31 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
1735
1745
|
|
|
1736
1746
|
Returns:
|
|
1737
1747
|
None : no file
|
|
1738
|
-
= 0 : a file
|
|
1748
|
+
= 0 : a file (even if not found)
|
|
1739
1749
|
> 0 : a file edited externally
|
|
1740
1750
|
< 0 : a url file
|
|
1741
1751
|
"""
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1752
|
+
try:
|
|
1753
|
+
return self.__path.stat().st_mtime - self.__mtime
|
|
1754
|
+
except FileNotFoundError:
|
|
1755
|
+
self.__mtime = False # valid path (but not found)
|
|
1756
|
+
except OSError:
|
|
1757
|
+
pass
|
|
1758
|
+
return self.__mtime
|
|
1759
|
+
|
|
1760
|
+
@property
|
|
1761
|
+
def need_buffer_save(self):
|
|
1762
|
+
"""Returns whether the buffer should be saved.
|
|
1763
|
+
The file has been modified internally.
|
|
1764
|
+
"""
|
|
1765
|
+
return self.mtdelta is not None and self.IsModified()
|
|
1766
|
+
|
|
1767
|
+
@property
|
|
1768
|
+
def need_buffer_load(self):
|
|
1769
|
+
"""Returns whether the buffer should be loaded.
|
|
1770
|
+
The file has been modified externally.
|
|
1771
|
+
"""
|
|
1772
|
+
return self.mtdelta is not None and self.mtdelta > 0
|
|
1748
1773
|
|
|
1749
1774
|
@property
|
|
1750
1775
|
def caption_prefix(self):
|
|
@@ -1769,20 +1794,6 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
1769
1794
|
except AttributeError:
|
|
1770
1795
|
pass
|
|
1771
1796
|
|
|
1772
|
-
@property
|
|
1773
|
-
def need_buffer_save(self):
|
|
1774
|
-
"""Returns whether the buffer should be saved.
|
|
1775
|
-
The file has been modified internally.
|
|
1776
|
-
"""
|
|
1777
|
-
return self.mtdelta is not None and self.IsModified()
|
|
1778
|
-
|
|
1779
|
-
@property
|
|
1780
|
-
def need_buffer_load(self):
|
|
1781
|
-
"""Returns whether the buffer should be loaded.
|
|
1782
|
-
The file has been modified externally.
|
|
1783
|
-
"""
|
|
1784
|
-
return self.mtdelta is not None and self.mtdelta > 0
|
|
1785
|
-
|
|
1786
1797
|
def __init__(self, parent, filename, **kwargs):
|
|
1787
1798
|
EditWindow.__init__(self, parent, **kwargs)
|
|
1788
1799
|
EditorInterface.__init__(self)
|
|
@@ -1952,20 +1963,20 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
1952
1963
|
## Processing text selection, dragging, or dragging+
|
|
1953
1964
|
evt.Skip()
|
|
1954
1965
|
return
|
|
1966
|
+
|
|
1955
1967
|
pos = evt.Position
|
|
1968
|
+
self.goto_char(pos) # Clear selection
|
|
1956
1969
|
i = 2
|
|
1957
1970
|
if self.IndicatorValueAt(i, pos): # [C-indic click]
|
|
1958
1971
|
p = self.IndicatorStart(i, pos)
|
|
1959
1972
|
q = self.IndicatorEnd(i, pos)
|
|
1960
1973
|
url = self.GetTextRange(p, q).strip()
|
|
1961
|
-
self.message("URL {!r}".format(url))
|
|
1962
1974
|
if wx.GetKeyState(wx.WXK_SHIFT): # [C-S-indic click]
|
|
1963
1975
|
import webbrowser
|
|
1964
1976
|
return webbrowser.open(url)
|
|
1965
1977
|
else:
|
|
1966
1978
|
## Note: post-call for the confirmation dialog.
|
|
1967
1979
|
wx.CallAfter(self.parent.load_file, url)
|
|
1968
|
-
self.anchor = pos # Clear selection
|
|
1969
1980
|
|
|
1970
1981
|
def on_modified(self, buf):
|
|
1971
1982
|
"""Called when the buffer is modified."""
|
|
@@ -2083,34 +2094,21 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
2083
2094
|
dispatcher.send(signal='Interpreter.push',
|
|
2084
2095
|
sender=self, command=None, more=False)
|
|
2085
2096
|
|
|
2086
|
-
def gen_text_at_caret(self):
|
|
2087
|
-
"""Generates the selected text,
|
|
2088
|
-
otherwise the line or expression at the caret.
|
|
2089
|
-
"""
|
|
2090
|
-
def _gen_text():
|
|
2091
|
-
text = self.SelectedText
|
|
2092
|
-
if text:
|
|
2093
|
-
yield text
|
|
2094
|
-
else:
|
|
2095
|
-
yield self.line_at_caret
|
|
2096
|
-
yield self.expr_at_caret
|
|
2097
|
-
return filter(None, _gen_text())
|
|
2098
|
-
|
|
2099
2097
|
def eval_line(self):
|
|
2100
2098
|
if self.CallTipActive():
|
|
2101
2099
|
self.CallTipCancel()
|
|
2102
2100
|
|
|
2103
|
-
|
|
2104
|
-
|
|
2101
|
+
text = self.SelectedText or self.expr_at_caret
|
|
2102
|
+
if text:
|
|
2105
2103
|
try:
|
|
2106
2104
|
obj = eval(text, self.globals, self.locals)
|
|
2107
2105
|
except Exception as e:
|
|
2108
|
-
|
|
2106
|
+
self.message(e)
|
|
2109
2107
|
else:
|
|
2110
2108
|
self.CallTipShow(self.cpos, pformat(obj))
|
|
2111
2109
|
self.message(text)
|
|
2112
|
-
|
|
2113
|
-
|
|
2110
|
+
else:
|
|
2111
|
+
self.message("No words")
|
|
2114
2112
|
|
|
2115
2113
|
def exec_region(self):
|
|
2116
2114
|
try:
|
|
@@ -2419,14 +2417,14 @@ class EditorBook(AuiNotebook, CtrlInterface):
|
|
|
2419
2417
|
buf._load_textfile(res.text, filename)
|
|
2420
2418
|
self.swap_buffer(buf, lineno)
|
|
2421
2419
|
return True
|
|
2422
|
-
|
|
2423
|
-
|
|
2420
|
+
## raise Exception("URL not found:", filename)
|
|
2421
|
+
res.raise_for_status() # raise HTTP error
|
|
2424
2422
|
if buf._load_file(filename):
|
|
2425
2423
|
self.swap_buffer(buf, lineno)
|
|
2426
2424
|
return True
|
|
2427
2425
|
return False
|
|
2428
|
-
except OSError as e:
|
|
2429
|
-
self.post_message(e)
|
|
2426
|
+
except (OSError, UnicodeDecodeError) as e:
|
|
2427
|
+
self.post_message("Failed to load:", e)
|
|
2430
2428
|
self.delete_buffer(buf)
|
|
2431
2429
|
return False
|
|
2432
2430
|
|
|
@@ -2441,11 +2439,10 @@ class EditorBook(AuiNotebook, CtrlInterface):
|
|
|
2441
2439
|
for fn in dlg.Paths:
|
|
2442
2440
|
self.find_file(fn)
|
|
2443
2441
|
return
|
|
2444
|
-
if self.load_file(filename) == False: # not None
|
|
2442
|
+
if self.load_file(filename) == False: # noqa: not None
|
|
2445
2443
|
buf = self.create_buffer(filename)
|
|
2446
|
-
buf._Buffer__mtime = 0 # => need_buffer_save
|
|
2447
2444
|
self.swap_buffer(buf)
|
|
2448
|
-
self.post_message(
|
|
2445
|
+
self.post_message("New file.")
|
|
2449
2446
|
|
|
2450
2447
|
def save_file(self, filename, buf=None, verbose=True):
|
|
2451
2448
|
"""Save the current buffer to a file.
|
|
@@ -2467,8 +2464,8 @@ class EditorBook(AuiNotebook, CtrlInterface):
|
|
|
2467
2464
|
self.default_buffer = None
|
|
2468
2465
|
return True
|
|
2469
2466
|
return False
|
|
2470
|
-
except
|
|
2471
|
-
self.post_message(
|
|
2467
|
+
except (OSError, UnicodeDecodeError) as e:
|
|
2468
|
+
self.post_message("Failed to save:", e)
|
|
2472
2469
|
return False
|
|
2473
2470
|
|
|
2474
2471
|
def load_buffer(self, buf=None):
|
|
@@ -3592,39 +3589,25 @@ class Nautilus(EditorInterface, Shell):
|
|
|
3592
3589
|
self.cpos, self.anchor = self.anchor, self.cpos
|
|
3593
3590
|
self.EnsureCaretVisible()
|
|
3594
3591
|
|
|
3595
|
-
def gen_text_at_caret(self):
|
|
3596
|
-
"""Generates the selected text,
|
|
3597
|
-
otherwise the line or expression at the caret.
|
|
3598
|
-
(override) Generates command line (that starts with a prompt).
|
|
3599
|
-
"""
|
|
3600
|
-
def _gen_text():
|
|
3601
|
-
text = self.SelectedText
|
|
3602
|
-
if text:
|
|
3603
|
-
yield text
|
|
3604
|
-
else:
|
|
3605
|
-
yield self.getCommand() # self.line_at_caret
|
|
3606
|
-
yield self.expr_at_caret
|
|
3607
|
-
return filter(None, _gen_text())
|
|
3608
|
-
|
|
3609
3592
|
def eval_line(self, evt):
|
|
3610
3593
|
"""Evaluate the selected word or line."""
|
|
3611
3594
|
if self.CallTipActive():
|
|
3612
3595
|
self.CallTipCancel()
|
|
3613
3596
|
|
|
3614
|
-
|
|
3615
|
-
|
|
3597
|
+
text = self.SelectedText or self.expr_at_caret
|
|
3598
|
+
if text:
|
|
3616
3599
|
tokens = split_words(text)
|
|
3617
3600
|
try:
|
|
3618
3601
|
cmd = self.magic_interpret(tokens)
|
|
3619
3602
|
cmd = self.regulate_cmd(cmd)
|
|
3620
3603
|
obj = self.eval(cmd)
|
|
3621
3604
|
except Exception as e:
|
|
3622
|
-
|
|
3605
|
+
self.message(e)
|
|
3623
3606
|
else:
|
|
3624
3607
|
self.CallTipShow(self.cpos, pformat(obj))
|
|
3625
3608
|
self.message(cmd)
|
|
3626
|
-
|
|
3627
|
-
|
|
3609
|
+
else:
|
|
3610
|
+
self.message("No words")
|
|
3628
3611
|
|
|
3629
3612
|
def exec_region(self, evt):
|
|
3630
3613
|
"""Execute the the selected region."""
|
mwx/plugins/ffmpeg_view.py
CHANGED
|
@@ -10,7 +10,7 @@ import wx.media
|
|
|
10
10
|
|
|
11
11
|
from mwx.framework import _F, hotkey
|
|
12
12
|
from mwx.graphman import Layer
|
|
13
|
-
from mwx.controls import LParam, Icon, Button,
|
|
13
|
+
from mwx.controls import LParam, Icon, Button, TextBox
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def read_info(path):
|
|
@@ -101,7 +101,7 @@ class Plugin(Layer):
|
|
|
101
101
|
handler=self.set_offset,
|
|
102
102
|
updater=self.get_offset,
|
|
103
103
|
)
|
|
104
|
-
self.crop =
|
|
104
|
+
self.crop = TextBox(self, icon="cut", size=(130,-1),
|
|
105
105
|
handler=self.set_crop,
|
|
106
106
|
updater=self.get_crop,
|
|
107
107
|
)
|
|
@@ -210,20 +210,18 @@ class Plugin(Layer):
|
|
|
210
210
|
|
|
211
211
|
def set_offset(self, tc):
|
|
212
212
|
"""Set offset value by referring to ss/to value."""
|
|
213
|
-
|
|
213
|
+
if self._path:
|
|
214
214
|
self.mc.Seek(self.DELTA + int(tc.value * 1000))
|
|
215
|
-
except Exception:
|
|
216
|
-
pass
|
|
217
215
|
|
|
218
216
|
def get_offset(self, tc):
|
|
219
217
|
"""Get offset value and assigns it to ss/to value."""
|
|
220
|
-
|
|
218
|
+
if self._path:
|
|
221
219
|
tc.value = round(self.mc.Tell()) / 1000
|
|
222
|
-
except Exception:
|
|
223
|
-
pass
|
|
224
220
|
|
|
225
221
|
def set_crop(self):
|
|
226
222
|
"""Set crop area (W:H:Left:Top) to roi."""
|
|
223
|
+
if not self._path:
|
|
224
|
+
return
|
|
227
225
|
frame = self.graph.frame
|
|
228
226
|
if frame:
|
|
229
227
|
try:
|
|
@@ -238,6 +236,8 @@ class Plugin(Layer):
|
|
|
238
236
|
|
|
239
237
|
def get_crop(self):
|
|
240
238
|
"""Get crop area (W:H:Left:Top) from roi."""
|
|
239
|
+
if not self._path:
|
|
240
|
+
return
|
|
241
241
|
crop = ''
|
|
242
242
|
frame = self.graph.frame
|
|
243
243
|
if frame:
|
|
@@ -246,28 +246,24 @@ class Plugin(Layer):
|
|
|
246
246
|
xo, yo = nx[0], ny[1]
|
|
247
247
|
xp, yp = nx[1], ny[0]
|
|
248
248
|
crop = "{}:{}:{}:{}".format(xp-xo, yp-yo, xo, yo)
|
|
249
|
-
if
|
|
249
|
+
if not crop:
|
|
250
250
|
crop = "{}:{}:0:0".format(*self.video_size)
|
|
251
251
|
self.crop.Value = crop
|
|
252
252
|
|
|
253
253
|
def seekto(self, offset):
|
|
254
254
|
"""Seek position with offset [ms] from the `to` position."""
|
|
255
|
-
|
|
255
|
+
if self._path:
|
|
256
256
|
t = self.to.value + offset/1000
|
|
257
257
|
if 0 <= t < self.video_dur:
|
|
258
258
|
self.to.value = round(t, 3)
|
|
259
259
|
self.set_offset(self.to)
|
|
260
|
-
except AttributeError:
|
|
261
|
-
pass
|
|
262
260
|
|
|
263
261
|
def seekd(self, offset):
|
|
264
262
|
"""Seek position with offset [ms] from the current position."""
|
|
265
|
-
|
|
263
|
+
if self._path:
|
|
266
264
|
t = self.mc.Tell() + offset
|
|
267
265
|
if 0 <= t < self.video_dur * 1000:
|
|
268
266
|
self.mc.Seek(self.DELTA + t)
|
|
269
|
-
except AttributeError:
|
|
270
|
-
pass
|
|
271
267
|
|
|
272
268
|
def snapshot(self):
|
|
273
269
|
"""Create a snapshot of the current frame.
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
mwx/__init__.py,sha256=
|
|
1
|
+
mwx/__init__.py,sha256=pS7ZG8QKRypiFFiaWAq_opBB6I_1viZ0zUMk2TbjzE0,667
|
|
2
2
|
mwx/bookshelf.py,sha256=b_TMDaNIzLHoL0xbbqb3tt0BnRvhLAqaCn_pBdrigZw,7523
|
|
3
|
-
mwx/controls.py,sha256=
|
|
4
|
-
mwx/framework.py,sha256=
|
|
5
|
-
mwx/graphman.py,sha256=
|
|
3
|
+
mwx/controls.py,sha256=X4zx2h6oggUsQxi2PRk4RUsJieYTmcAPIvWwaz-ysTI,48107
|
|
4
|
+
mwx/framework.py,sha256=wXI4nzQcG0NV3c5ne4io9HJ1y7jd7xbjB_cOao8HKsU,76125
|
|
5
|
+
mwx/graphman.py,sha256=RqD0W9I2BvJ3Q2kyMiyyg4n-T4-_x7PDuCI5bGAg5k4,70110
|
|
6
6
|
mwx/images.py,sha256=oxCn0P-emiWujSS2gUgU5TUnr5cPjix2jBcjOBDr24I,48701
|
|
7
|
-
mwx/matplot2.py,sha256=
|
|
8
|
-
mwx/matplot2g.py,sha256=
|
|
7
|
+
mwx/matplot2.py,sha256=Zwte-wwzCg_OHzsBniVgKdaNLzsvJaa1gc0n7VdAqxw,33150
|
|
8
|
+
mwx/matplot2g.py,sha256=tShPGy7whj51yvANja-MDmjfxiLubQ1C6rCsBZ0DAnY,64473
|
|
9
9
|
mwx/matplot2lg.py,sha256=JRWjWnLJUytbSq6wxs4P0gbVUr3xoLSF6Wwqd5V_pJI,27404
|
|
10
|
-
mwx/mgplt.py,sha256=
|
|
11
|
-
mwx/nutshell.py,sha256=
|
|
10
|
+
mwx/mgplt.py,sha256=8mXbHpCmm7lz3XbAxOg7IVC7DaSGBEby1UfTlMl9kjk,5604
|
|
11
|
+
mwx/nutshell.py,sha256=7nQ7UUFM9kvjDjHNUEdOkkeqZPiU6zOERwamqBdJpQs,140856
|
|
12
12
|
mwx/testsuite.py,sha256=kiM3-BVhr42LRRN7xG7pYl3at8o2vnypWSxD8KRvA7c,1228
|
|
13
13
|
mwx/utilus.py,sha256=HFvP682SyeSp8yNfUrdUXPhWdLuWVlsUSg6LqNBJOT8,37451
|
|
14
14
|
mwx/wxmon.py,sha256=yzWqrbY6LzpfRwQeytYUeqFhFuLVm_XEvrVAL_k0HBQ,12756
|
|
@@ -16,14 +16,14 @@ mwx/wxpdb.py,sha256=AObuf4JLAmlQLj-yf0_mkBBd-Bhhz2Vb8hbTVcHEZOs,18875
|
|
|
16
16
|
mwx/wxwil.py,sha256=hhyB1lPrF9ixeObxCOKQv0Theu-B-kpJg_yVU3EGSNg,5406
|
|
17
17
|
mwx/wxwit.py,sha256=1hHtMi2YEy2T_LnUpwdmrIdtCuvxMOFyykqnbq6jLP0,7294
|
|
18
18
|
mwx/plugins/__init__.py,sha256=jnJ-Sl9XJ_7BFDslD_r7dsbxsOT57q_IaEriV53XIGY,41
|
|
19
|
-
mwx/plugins/ffmpeg_view.py,sha256=
|
|
19
|
+
mwx/plugins/ffmpeg_view.py,sha256=NIHFJLPeliOXH3ke0NvQzYBhY0oeEP6dgZQofB5Ry1c,11031
|
|
20
20
|
mwx/plugins/fft_view.py,sha256=08A_Y73XirV7kXpwf-v0mUA0Hr0MOfdMXv3tvL1hvWA,2789
|
|
21
21
|
mwx/plugins/frame_listview.py,sha256=gowjQ-ARNonMkDSXkQgPKq4U9YBJ-vQ0jK2krBVOdCs,10420
|
|
22
22
|
mwx/plugins/line_profile.py,sha256=zzm6_7lnAnNepLbh07ordp3nRWDFQJtu719ZVjrVf8s,819
|
|
23
23
|
mwx/py/__init__.py,sha256=xykgfOytOwNuvXsfkLoumFZSTN-iBsHOjczYXngjmUE,12
|
|
24
24
|
mwx/py/filling.py,sha256=fumUG1F5M9TL-Dfqni4G85uk7TmvnUunTbdcPDV0vfo,16857
|
|
25
|
-
mwxlib-1.
|
|
26
|
-
mwxlib-1.
|
|
27
|
-
mwxlib-1.
|
|
28
|
-
mwxlib-1.
|
|
29
|
-
mwxlib-1.
|
|
25
|
+
mwxlib-1.2.3.dist-info/LICENSE,sha256=PGtRKCaTkmUDlBQwpptJAxJtdqxIUtAmdBsaT9nUVkA,1091
|
|
26
|
+
mwxlib-1.2.3.dist-info/METADATA,sha256=2sSF51qYRi78w0McPUzYn2yr9H1ISRKXMfvWSB-ATls,7258
|
|
27
|
+
mwxlib-1.2.3.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
28
|
+
mwxlib-1.2.3.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
|
|
29
|
+
mwxlib-1.2.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|