mwxlib 1.1.1__py3-none-any.whl → 1.1.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of mwxlib might be problematic. Click here for more details.

mwx/bookshelf.py CHANGED
@@ -2,13 +2,59 @@
2
2
  import re
3
3
  import wx
4
4
 
5
- from .framework import CtrlInterface, postcall
5
+ from .framework import CtrlInterface
6
+
7
+
8
+ class MyDropTarget(wx.DropTarget):
9
+ """DnD loader for files and URL text.
10
+ """
11
+ def __init__(self, tree):
12
+ wx.DropTarget.__init__(self)
13
+
14
+ self.tree = tree
15
+ self.datado = wx.CustomDataObject("TreeItem")
16
+ self.filedo = wx.FileDataObject()
17
+ self.do = wx.DataObjectComposite()
18
+ self.do.Add(self.datado)
19
+ self.do.Add(self.filedo)
20
+ self.SetDataObject(self.do)
21
+
22
+ def OnDragOver(self, x, y, result):
23
+ item, flags = self.tree.HitTest((x, y))
24
+ items = list(self.tree._gen_items(self.tree.RootItem)) # first level items
25
+ if not item:
26
+ item = items[0]
27
+ if item in items and item != self.tree.Selection:
28
+ self.tree.SelectItem(item)
29
+ return result
30
+
31
+ def OnData(self, x, y, result):
32
+ item = self.tree.Selection
33
+ name = self.tree.GetItemText(item)
34
+ editor = self.tree.Parent.FindWindow(name) # window.Name (not page.caption)
35
+ def _load(f):
36
+ if editor.load_file(f):
37
+ editor.buffer.SetFocus()
38
+ editor.message(f"Loaded {f!r} successfully.")
39
+ self.GetData()
40
+ data = self.datado.Data
41
+ if data:
42
+ f = data.tobytes().decode()
43
+ _load(f)
44
+ self.datado.SetData(b"")
45
+ else:
46
+ for f in self.filedo.Filenames:
47
+ _load(f)
48
+ self.filedo.SetData(wx.DF_FILENAME, None)
49
+ return result
6
50
 
7
51
 
8
52
  class EditorTreeCtrl(wx.TreeCtrl, CtrlInterface):
9
53
  """TreeList/Ctrl
10
54
 
11
55
  Construct treectrl in the order of tree:list.
56
+ Note:
57
+ This only works with single selection mode.
12
58
  """
13
59
  def __init__(self, parent, *args, **kwargs):
14
60
  wx.TreeCtrl.__init__(self, parent, *args, **kwargs)
@@ -22,6 +68,10 @@ class EditorTreeCtrl(wx.TreeCtrl, CtrlInterface):
22
68
  self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged)
23
69
  self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
24
70
 
71
+ self.SetDropTarget(MyDropTarget(self))
72
+
73
+ self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnBeginDrag)
74
+
25
75
  def dispatch(evt):
26
76
  """Fork events to the parent."""
27
77
  self.parent.handler(self.handler.current_event, evt)
@@ -34,7 +84,6 @@ class EditorTreeCtrl(wx.TreeCtrl, CtrlInterface):
34
84
  },
35
85
  0 : {
36
86
  'delete pressed' : (0, self._delete),
37
- 'f5 pressed' : (0, self._refresh),
38
87
  },
39
88
  })
40
89
  self.context = { # DNA<EditorBook>
@@ -61,26 +110,10 @@ class EditorTreeCtrl(wx.TreeCtrl, CtrlInterface):
61
110
  editor.handler.remove(self.context)
62
111
  evt.Skip()
63
112
 
64
- def _refresh(self, evt):
65
- def _item(editor):
66
- return self._get_item(self.RootItem, editor.Name)
67
- ls = []
68
- for editor in self.parent.all_editors:
69
- if self.IsExpanded(_item(editor)):
70
- ls.append(editor)
71
- data = None
72
- if self.Selection.IsOk():
73
- data = self.GetItemData(self.Selection)
74
- if data:
75
- wx.CallAfter(data.SetFocus)
76
- wx.CallAfter(self.SetFocus)
77
- self.build_tree()
78
- for editor in ls:
79
- self.Expand(_item(editor))
80
-
81
113
  def _delete(self, evt):
82
- if self.Selection.IsOk():
83
- data = self.GetItemData(self.Selection)
114
+ item = self.Selection
115
+ if item:
116
+ data = self.GetItemData(item)
84
117
  if data:
85
118
  data.parent.kill_buffer(data) # the focus moves
86
119
  wx.CallAfter(self.SetFocus)
@@ -100,22 +133,26 @@ class EditorTreeCtrl(wx.TreeCtrl, CtrlInterface):
100
133
  self._set_item(self.RootItem, editor.Name, editor.all_buffers)
101
134
  self.Refresh()
102
135
 
103
- def _gen_item(self, root, key):
136
+ def _gen_items(self, root, key=None):
104
137
  """Generates the [root/key] items."""
105
138
  item, cookie = self.GetFirstChild(root)
106
139
  while item:
107
- caption = self.GetItemText(item)
108
- if key == re.sub(r"^\W+\s+(.*)", r"\1", caption):
140
+ if not key:
109
141
  yield item
142
+ else:
143
+ ## キャプション先頭の識別子 %* を除外して比較する
144
+ caption = self.GetItemText(item)
145
+ if key == re.sub(r"^\W+\s+(.*)", r"\1", caption):
146
+ yield item
110
147
  item, cookie = self.GetNextChild(root, cookie)
111
148
 
112
149
  def _get_item(self, root, key):
113
150
  """Get the first [root/key] item found."""
114
- return next(self._gen_item(root, key), None)
151
+ return next(self._gen_items(root, key), None)
115
152
 
116
153
  def _set_item(self, root, key, data):
117
154
  """Set the [root/key] item with data recursively."""
118
- for item in self._gen_item(root, key):
155
+ for item in self._gen_items(root, key):
119
156
  buf = self.GetItemData(item)
120
157
  if not buf or buf is data:
121
158
  break
@@ -142,10 +179,9 @@ class EditorTreeCtrl(wx.TreeCtrl, CtrlInterface):
142
179
 
143
180
  ## Note: [buffer_activated][EVT_SET_FOCUS] > [buffer_new] の順で呼ばれる
144
181
  ## buf.__itemId がない場合がある (delete_buffer 直後など)
145
- @postcall
146
182
  def on_buffer_selected(self, buf):
147
183
  if self and buf:
148
- self.SelectItem(buf.__itemId)
184
+ wx.CallAfter(lambda: self.SelectItem(buf.__itemId))
149
185
 
150
186
  def on_buffer_filename(self, buf):
151
187
  if self and buf:
@@ -156,5 +192,20 @@ class EditorTreeCtrl(wx.TreeCtrl, CtrlInterface):
156
192
  data = self.GetItemData(evt.Item)
157
193
  if data:
158
194
  data.SetFocus()
159
- self.SetFocus()
195
+ else:
196
+ name = self.GetItemText(evt.Item)
197
+ editor = self.Parent.FindWindow(name) # window.Name (not page.caption)
198
+ if not editor.IsShown():
199
+ ## editor.SetFocus()
200
+ self.Parent.Selection = self.Parent.FindPage(editor)
201
+ wx.CallAfter(self.SetFocus)
160
202
  evt.Skip()
203
+
204
+ def OnBeginDrag(self, evt):
205
+ data = self.GetItemData(evt.Item)
206
+ if data:
207
+ dd = wx.CustomDataObject("TreeItem")
208
+ dd.SetData(data.filename.encode())
209
+ dropSource = wx.DropSource()
210
+ dropSource.SetData(dd)
211
+ dropSource.DoDragDrop(wx.Drag_AllowMove) # -> wx.DragResult
mwx/framework.py CHANGED
@@ -1,7 +1,7 @@
1
1
  #! python3
2
2
  """mwxlib framework.
3
3
  """
4
- __version__ = "1.1.1"
4
+ __version__ = "1.1.5"
5
5
  __author__ = "Kazuya O'moto <komoto@jeol.co.jp>"
6
6
 
7
7
  from contextlib import contextmanager
@@ -1024,31 +1024,39 @@ class FileDropLoader(wx.DropTarget):
1024
1024
  self.target = target
1025
1025
  self.textdo = wx.TextDataObject()
1026
1026
  self.filedo = wx.FileDataObject()
1027
- self.DataObject = wx.DataObjectComposite()
1028
- self.DataObject.Add(self.textdo)
1029
- self.DataObject.Add(self.filedo, True)
1027
+ self.do = wx.DataObjectComposite()
1028
+ self.do.Add(self.textdo)
1029
+ self.do.Add(self.filedo)
1030
+ self.SetDataObject(self.do)
1031
+
1032
+ def OnDragOver(self, x, y, result):
1033
+ index, flags = self.target.HitTest((x, y))
1034
+ if index != -1:
1035
+ self.target.Selection = index
1036
+ return result
1030
1037
 
1031
1038
  def OnData(self, x, y, result):
1032
- editor = self.target.current_editor
1039
+ editor = self.target.Parent.current_editor
1033
1040
  self.GetData()
1034
1041
  if self.textdo.TextLength > 1:
1035
1042
  f = self.textdo.Text.strip()
1036
1043
  res = editor.load_file(f)
1037
1044
  if res:
1038
1045
  editor.buffer.SetFocus()
1046
+ editor.message(f"Loaded {f!r} successfully.")
1039
1047
  result = wx.DragCopy
1040
1048
  elif res is None:
1041
- editor.post_message("Load canceled.")
1049
+ editor.message(f"Loading {f!r} canceled.")
1042
1050
  result = wx.DragCancel
1043
1051
  else:
1044
- editor.post_message(f"Loading {f!r} failed.")
1052
+ editor.message(f"Loading {f!r} failed.")
1045
1053
  result = wx.DragNone
1046
- self.textdo.Text = ''
1054
+ self.textdo.SetText('')
1047
1055
  else:
1048
1056
  for f in self.filedo.Filenames:
1049
1057
  if editor.load_file(f):
1050
1058
  editor.buffer.SetFocus()
1051
- editor.post_message(f"Loaded {f!r} successfully.")
1059
+ editor.message(f"Loaded {f!r} successfully.")
1052
1060
  self.filedo.SetData(wx.DF_FILENAME, None)
1053
1061
  return result
1054
1062
 
@@ -1159,7 +1167,7 @@ class ShellFrame(MiniFrame):
1159
1167
 
1160
1168
  self.ghost.AddPage(self.Bookshelf, "Bookshelf", bitmap=Icon('book'))
1161
1169
 
1162
- self.ghost.SetDropTarget(FileDropLoader(self))
1170
+ self.ghost.SetDropTarget(FileDropLoader(self.ghost))
1163
1171
 
1164
1172
  self.watcher = AuiNotebook(self, size=(600,400), name="watcher")
1165
1173
  self.watcher.AddPage(self.ginfo, "globals")
@@ -1649,6 +1657,8 @@ class ShellFrame(MiniFrame):
1649
1657
  self.linfo.watch(obj.__dict__)
1650
1658
  self.ginfo.watch(None)
1651
1659
  self.popup_window(self.linfo)
1660
+ else:
1661
+ raise TypeError("primitive objects cannot be set as watch targets")
1652
1662
 
1653
1663
  def highlight(self, obj, *args, **kwargs):
1654
1664
  self.inspector.highlight(obj, *args, **kwargs)
mwx/graphman.py CHANGED
@@ -1451,7 +1451,7 @@ class Frame(mwx.Frame):
1451
1451
  frame.name = os.path.basename(fn) # new name and pathname
1452
1452
  output_frames.append(frame)
1453
1453
  print(' ', self.message("\b done."))
1454
- except (PermissionError, OSError) as e:
1454
+ except OSError as e:
1455
1455
  print('-', self.message("\b failed.", e))
1456
1456
 
1457
1457
  frames = output_frames
mwx/nutshell.py CHANGED
@@ -667,6 +667,9 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
667
667
  self.__mark = -1
668
668
  self.__stylus = {}
669
669
 
670
+ __dnd_from = None
671
+ __dnd_flag = 0
672
+
670
673
  def OnDrag(self, evt): #<wx._core.StyledTextEvent>
671
674
  EditorInterface.__dnd_from = evt.EventObject
672
675
  try:
@@ -2327,7 +2330,7 @@ class EditorBook(AuiNotebook, CtrlInterface):
2327
2330
  self.set_attributes(buf, **self.defaultBufferStyle)
2328
2331
  if index is None:
2329
2332
  index = self.PageCount
2330
- self.InsertPage(index, buf, buf.name)
2333
+ self.InsertPage(index, buf, buf.name) # => [buffer_activated]
2331
2334
  self.handler('buffer_new', buf)
2332
2335
  return buf
2333
2336
  finally:
@@ -2421,20 +2424,16 @@ class EditorBook(AuiNotebook, CtrlInterface):
2421
2424
  buf._load_textfile(res.text, filename)
2422
2425
  self.swap_buffer(buf, lineno)
2423
2426
  return True
2424
- ## return False
2425
- raise Exception("The requested URL was not found")
2427
+ return False
2428
+ ## raise Exception("The requested URL was not found", filename)
2426
2429
  if buf._load_file(filename):
2427
2430
  self.swap_buffer(buf, lineno)
2428
2431
  return True
2429
2432
  return False
2430
- except FileNotFoundError:
2431
- self.post_message(f"New file: {filename!r}.")
2433
+ except OSError as e:
2434
+ self.post_message(e)
2432
2435
  self.delete_buffer(buf)
2433
2436
  return False
2434
- except Exception as e:
2435
- self.post_message(f"Failed to load {filename!r}.", e)
2436
- self.delete_buffer(buf)
2437
- raise
2438
2437
 
2439
2438
  def find_file(self, filename=None):
2440
2439
  """Open the specified file."""
@@ -2451,6 +2450,7 @@ class EditorBook(AuiNotebook, CtrlInterface):
2451
2450
  buf = self.create_buffer(filename)
2452
2451
  buf._Buffer__mtime = 0 # => need_buffer_save
2453
2452
  self.swap_buffer(buf)
2453
+ self.post_message(f"New file: {filename!r}.")
2454
2454
 
2455
2455
  def save_file(self, filename, buf=None, verbose=True):
2456
2456
  """Save the current buffer to a file.
@@ -2697,7 +2697,7 @@ class Nautilus(EditorInterface, Shell):
2697
2697
  """Reset the shell target object; Rename the parent title.
2698
2698
  """
2699
2699
  if not hasattr(obj, '__dict__'):
2700
- raise TypeError("primitive objects cannot be targeted")
2700
+ raise TypeError("primitive objects cannot be targets")
2701
2701
 
2702
2702
  self.__target = obj
2703
2703
  self.locals = obj.__dict__
mwx/utilus.py CHANGED
@@ -323,7 +323,8 @@ def split_tokens(text, comment=True):
323
323
  j, k = 1, 0
324
324
  for type, string, start, end, line in tokens:
325
325
  l, m = start
326
- if type in (tokenize.ENDMARKER, tokenize.INDENT, tokenize.DEDENT):
326
+ if type in (tokenize.INDENT, tokenize.DEDENT) or not string:
327
+ ## Empty strings such as NEWLINE and ENDMARKER are also skipped.
327
328
  continue
328
329
  if type == tokenize.COMMENT and not comment:
329
330
  token = next(tokens) # eats a trailing token
@@ -358,6 +359,8 @@ def _extract_words_from_tokens(tokens, reverse=False):
358
359
  stack = []
359
360
  words = []
360
361
  for j, c in enumerate(tokens):
362
+ if not c:
363
+ continue
361
364
  if c in p:
362
365
  stack.append(c)
363
366
  elif c in q:
@@ -389,6 +392,8 @@ def _extract_paren_from_tokens(tokens, reverse=False):
389
392
  stack = []
390
393
  words = []
391
394
  for j, c in enumerate(tokens):
395
+ if not c:
396
+ continue
392
397
  if c in p:
393
398
  stack.append(c)
394
399
  elif c in q:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mwxlib
3
- Version: 1.1.1
3
+ Version: 1.1.5
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
@@ -1,16 +1,16 @@
1
1
  mwx/__init__.py,sha256=psabnAMei5VzB2TsB2qBNLrIZMX0LiqjlXCpNGmDejk,668
2
- mwx/bookshelf.py,sha256=so-xSLq08sMlJBErTxOaDoKUAMa_g1CkIP2pNnff68c,5607
2
+ mwx/bookshelf.py,sha256=b_TMDaNIzLHoL0xbbqb3tt0BnRvhLAqaCn_pBdrigZw,7523
3
3
  mwx/controls.py,sha256=cNZkgwSv90lPIz61FvMtYxHIt8hJD_RQYXxsgTQIdLc,47949
4
- mwx/framework.py,sha256=dF11HNsJRJ6ybpWR674H29CNGj59L1MnCV8K5QmNCdE,75759
5
- mwx/graphman.py,sha256=04bEw7TEIs6X1QrgqBSLJoIhJnW5TwHTW_wZOvJYSwo,69840
4
+ mwx/framework.py,sha256=KobxKW3ogvEBdm1I6cKr_4xyP5JTmxpDK3AsnQbLk90,76125
5
+ mwx/graphman.py,sha256=LjN1R8UZxHycrgAfnl_SoTT_vHuKcSISr5VVf0cMflM,69821
6
6
  mwx/images.py,sha256=oxCn0P-emiWujSS2gUgU5TUnr5cPjix2jBcjOBDr24I,48701
7
7
  mwx/matplot2.py,sha256=RuVWXC2A_qgZRNmBBptbHDn5MyxaWBqp3ru4bP_lDE0,33150
8
8
  mwx/matplot2g.py,sha256=4G5uZJZzATEC3QEVZ4pGHetEDfu5NJNUFyeAaQScK5s,64495
9
9
  mwx/matplot2lg.py,sha256=JRWjWnLJUytbSq6wxs4P0gbVUr3xoLSF6Wwqd5V_pJI,27404
10
10
  mwx/mgplt.py,sha256=M5rt-H7Uq1OHnlFvMA4a3945UBvppbR9L_mw8NL_YZ0,5602
11
- mwx/nutshell.py,sha256=MLE667zDFB2iZSpW1m0AwLxRAh6HUYLMyl4OLV_VXAI,141532
11
+ mwx/nutshell.py,sha256=5X3o2TTXWxZ9pyXy-6XRsIKu09q8_lIWUDoST59FoIA,141488
12
12
  mwx/testsuite.py,sha256=kiM3-BVhr42LRRN7xG7pYl3at8o2vnypWSxD8KRvA7c,1228
13
- mwx/utilus.py,sha256=sZehJJHBQ7aGpzEMClmowqExVO7esyVMK7Tk-MJO6tQ,37293
13
+ mwx/utilus.py,sha256=HFvP682SyeSp8yNfUrdUXPhWdLuWVlsUSg6LqNBJOT8,37451
14
14
  mwx/wxmon.py,sha256=yzWqrbY6LzpfRwQeytYUeqFhFuLVm_XEvrVAL_k0HBQ,12756
15
15
  mwx/wxpdb.py,sha256=--TQr-_zs9dWPYV2V4s3Zr4abvN14o5wD8anT9frHUg,18875
16
16
  mwx/wxwil.py,sha256=hhyB1lPrF9ixeObxCOKQv0Theu-B-kpJg_yVU3EGSNg,5406
@@ -22,8 +22,8 @@ mwx/plugins/frame_listview.py,sha256=gowjQ-ARNonMkDSXkQgPKq4U9YBJ-vQ0jK2krBVOdCs
22
22
  mwx/plugins/line_profile.py,sha256=zzm6_7lnAnNepLbh07ordp3nRWDFQJtu719ZVjrVf8s,819
23
23
  mwx/py/__init__.py,sha256=xykgfOytOwNuvXsfkLoumFZSTN-iBsHOjczYXngjmUE,12
24
24
  mwx/py/filling.py,sha256=fumUG1F5M9TL-Dfqni4G85uk7TmvnUunTbdcPDV0vfo,16857
25
- mwxlib-1.1.1.dist-info/LICENSE,sha256=PGtRKCaTkmUDlBQwpptJAxJtdqxIUtAmdBsaT9nUVkA,1091
26
- mwxlib-1.1.1.dist-info/METADATA,sha256=-2RieR9LO8AM21AP3Msu7qCp2Krjm23TSAlgiXT285M,7259
27
- mwxlib-1.1.1.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
28
- mwxlib-1.1.1.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
29
- mwxlib-1.1.1.dist-info/RECORD,,
25
+ mwxlib-1.1.5.dist-info/LICENSE,sha256=PGtRKCaTkmUDlBQwpptJAxJtdqxIUtAmdBsaT9nUVkA,1091
26
+ mwxlib-1.1.5.dist-info/METADATA,sha256=Gr1yxZsOVwU-M2UA0fLOrj78gjkJShfJfx7IwwBO4OU,7259
27
+ mwxlib-1.1.5.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
28
+ mwxlib-1.1.5.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
29
+ mwxlib-1.1.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.3.0)
2
+ Generator: setuptools (75.5.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5