Merge lp:~spud/spud/copy-paste-fix into lp:spud
- copy-paste-fix
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Patrick Farrell |
Approved revision: | 432 |
Merged at revision: | 435 |
Proposed branch: | lp:~spud/spud/copy-paste-fix |
Merge into: | lp:spud |
Diff against target: |
482 lines (+86/-108) 4 files modified
diamond/diamond/choice.py (+23/-47) diamond/diamond/interface.py (+41/-29) diamond/diamond/schema.py (+16/-21) diamond/diamond/tree.py (+6/-11) |
To merge this branch: | bzr merge lp:~spud/spud/copy-paste-fix |
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Fraser Waters | Approve | ||
Patrick Farrell | Approve | ||
Cian Wilson | Approve | ||
Review via email:
|
This proposal supersedes a proposal from 2011-07-27.
Commit message
Description of the change
Fix for bug #811200 and #812348. on_paste was not handling MixedTree's in the same way as on_copy. on_paste was not handling choices correctly.

Cian Wilson (cwilson) wrote : Posted in a previous version of this proposal | # |

Patrick Farrell (pefarrell) wrote : Posted in a previous version of this proposal | # |
I attempted to replicate #811200 with this branch.
I don't get Cian's terminal error; I think that's been fixed, and I suspect it's something to do with running the wrong version of diamond. Cian: when you check out a branch, just do
cd branch
./configure
python diamond/bin/diamond [args]
and it will automatically use the right code.
But I get a different bug. It doesn't give any exception, but when I save the file I get
<?xml version='1.0' encoding='utf-8'?>
<dummy_options>
<system name="Dummy">
<nonlinear_
<type name="SNES">
<python name="Jacobian" rank="1">
</python>
</type>
</nonlinear
<nonlinear_
<type name="SNES">
<python name="Jacobian" rank="1">
</python>
</type>
</nonlinear
</system>
</dummy_options>
Note that the second nonlinear solver has a) lost its name, and b) lost its python code. It *looks* fine in the live diamond window, but if you save it it gets lost. (If you open it up again, you'll get all sorts of lost element errors.)

Cian Wilson (cwilson) wrote : Posted in a previous version of this proposal | # |
> cd branch
> ./configure
> python diamond/bin/diamond [args]
I get the same error (terminal output and all) running the command this way:
cwilson@
Just to confirm it's the branch I'm running:
cwilson@
Repository tree (format: 2a)
Location:
shared repository: /home/cwilson/
repository branch: .
Related branches:
parent branch: bzr+ssh:
> <?xml version='1.0' encoding='utf-8'?>
> <dummy_options>
> <system name="Dummy">
> <nonlinear_solver name="Simple">
> <type name="SNES">
> <python name="Jacobian" rank="1">
> <string_value lines="20" type="python">some python code
> here</string_value>
> </python>
> </type>
> </nonlinear_solver>
> <nonlinear_solver>
> <type name="SNES">
> <python name="Jacobian" rank="1">
> <string_value type="python" lines="20"/>
> </python>
> </type>
> </nonlinear_solver>
> </system>
> </dummy_options>
>
> Note that the second nonlinear solver has a) lost its name, and b) lost its
> python code. It *looks* fine in the live diamond window, but if you save it it
> gets lost. (If you open it up again, you'll get all sorts of lost element
> errors.)
With the exception of looking fine in the diamond window before I close it (i.e. it doesn't look like it's copied to me and diamond shows elements as blue still) that sounds like the same behaviour I see on reopening the file.

Patrick Farrell (pefarrell) wrote : Posted in a previous version of this proposal | # |
Also: I seem to get different behaviour depending on whether I CTRL+C/CTRL+V, or right-click copy, right-click paste. When I right-click copy, I get the following error in the terminal:
Traceback (most recent call last):
File "/data/
if widget is not self.treeview and gobject.
TypeError: type must be instantiable or an interface
The XML appears correct regardless of which approach is taken.
When I paste onto the blank nonlinear_solver, it doesn't have the right cardinality: it doesn't have the '-' on the right-hand side of the treeview to deactivate it.

Cian Wilson (cwilson) wrote : Posted in a previous version of this proposal | # |
The above was done by first adding a new nonlinear_solver element then running CTRL+C on the old copy nonlinear_
If instead I use the right-click feature I get:
Traceback (most recent call last):
File "/home/
if widget is not self.treeview and gobject.
TypeError: type must be instantiable or an interface
on copy and:
Traceback (most recent call last):
File "/home/
if widget is not self.treeview and gobject.
TypeError: type must be instantiable or an interface
on paste.

Fraser Waters (fraser-waters08) wrote : Posted in a previous version of this proposal | # |
"TypeError: type must be instantiable or an interface"
I found the cause of that, it's fixed in my local version.
The rest I'm not sure, I'll look into it more it's probably some confusion between Choices, Trees and MixedTrees. Really need to standardize them at some point.

Cian Wilson (cwilson) wrote : Posted in a previous version of this proposal | # |
Repeating the steps (and using the schema and options file) in bug #811200 (i.e. activating a new nonlinear_solver element, copying nonlinear_
File "/usr/lib/
newnode = self.s.read(ios, node)
File "/usr/lib/
datatree = self.valid_
File "/usr/lib/
xpath = self.tree.
File "lxml.etree.pyx", line 2029, in lxml.etree.
File "xpath.pxi", line 363, in lxml.etree.
File "apihelpers.pxi", line 1364, in lxml.etree._utf8 (src/lxml/
TypeError: Argument must be bytes or unicode, got 'Choice'
Nothing appears in the pasted to element.
If I then delete the node that I just failed to copy information to and save the file, close it and reopen it, it reappears as I last saw (and saved) it so that part of the bug appears fixed.
I get the same error using right-click copy and paste and if the element being pasted to is active or not.
Can anyone reproduce this with this branch? I've built packages from this branch and overwritten my previously installed spud so am reasonably confident I'm not getting paths muddled.

Patrick Farrell (pefarrell) wrote : Posted in a previous version of this proposal | # |
Cian: yes, I can reproduce your behaviour. Thanks again for your thorough testing.
We know that the way choices are handled needs to be changed (there's another bug I didn't bother writing up), so Fraser will start on that soon.

Fraser Waters (fraser-waters08) wrote : Posted in a previous version of this proposal | # |
Yes just to confirm. Choice nodes aren't being handled correctly at the moment. I'm working on it. Trying to paste on a choice should always fail at the moment. If your getting bugs with normal nodes keep reporting them, because they SHOULD work.

Fraser Waters (fraser-waters08) wrote : Posted in a previous version of this proposal | # |
Choice nodes should be handled correctly now.

Cian Wilson (cwilson) wrote : | # |
A thing of beauty.
(Have tested it on both schemas in #812348 and #811200, both work fine with the workflow described in the bug reports with both Ctrl+C&V and right-click and for active and inactive elements.)

Patrick Farrell (pefarrell) wrote : | # |
Yep, I can't seem to break it. So I think you're good to go!

Fraser Waters (fraser-waters08) : | # |
Preview Diff
1 | === modified file 'diamond/diamond/choice.py' |
2 | --- diamond/diamond/choice.py 2011-07-26 14:04:07 +0000 |
3 | +++ diamond/diamond/choice.py 2011-07-28 14:01:27 +0000 |
4 | @@ -31,23 +31,23 @@ |
5 | __gsignals__ = { "on-set-data" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (str,)), |
6 | "on-set-attr" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (str, str))} |
7 | |
8 | - def __init__(self, l, cardinality=''): |
9 | + def __init__(self, choices, schemaname="", cardinality=''): |
10 | gobject.GObject.__init__(self) |
11 | |
12 | - self.l = l |
13 | - if l == []: |
14 | + self.choices = choices |
15 | + if choices == []: |
16 | raise Exception |
17 | self.index = 0 |
18 | name = "" |
19 | - for choice in l: |
20 | + for choice in choices: |
21 | assert choice.__class__ is tree.Tree |
22 | - name = name + choice.name + ":" |
23 | choice.connect("on-set-data", self._on_set_data) |
24 | choice.connect("on-set-attr", self._on_set_attr) |
25 | |
26 | - name = name[:-1] |
27 | + name = ":".join(choice.name for choice in choices) |
28 | + |
29 | self.name = name |
30 | - self.schemaname = name |
31 | + self.schemaname = schemaname |
32 | self.cardinality = cardinality |
33 | self.parent = None |
34 | self.set_default_active() |
35 | @@ -67,21 +67,21 @@ |
36 | self.index = i |
37 | |
38 | def find_tree(self, name): |
39 | - for t in self.l: |
40 | + for t in self.choices: |
41 | if t.name == name: |
42 | return t |
43 | |
44 | debug.deprint("self.name == %s" % self.name, 0) |
45 | - for choice in self.l: |
46 | + for choice in self.choices: |
47 | debug.deprint("choice.name == %s" % choice.name, 0) |
48 | raise Exception, "No such choice name: %s" % name |
49 | |
50 | def set_active_choice_by_name(self, name): |
51 | matched = False |
52 | - for t in self.l: |
53 | + for t in self.choices: |
54 | if t.name == name.strip(): |
55 | matched = True |
56 | - self.index = self.l.index(t) |
57 | + self.index = self.choices.index(t) |
58 | |
59 | if not matched: |
60 | raise Exception, "no such name %s found" % name |
61 | @@ -89,11 +89,11 @@ |
62 | self.recompute_validity() |
63 | |
64 | def set_active_choice_by_ref(self, ref): |
65 | - self.index = self.l.index(ref) |
66 | + self.index = self.choices.index(ref) |
67 | self.recompute_validity() |
68 | |
69 | def get_current_tree(self): |
70 | - return self.l[self.index] |
71 | + return self.choices[self.index] |
72 | |
73 | def add_children(self, schema): |
74 | return self.get_current_tree().add_children(schema) |
75 | @@ -106,7 +106,7 @@ |
76 | |
77 | def copy(self): |
78 | new_choices = [] |
79 | - for choice in self.l: |
80 | + for choice in self.choices: |
81 | new_choices.append(choice.copy()) |
82 | |
83 | new_choice = Choice(new_choices) |
84 | @@ -114,37 +114,23 @@ |
85 | setattr(new_choice, attr, copy.copy(getattr(self, attr))) |
86 | |
87 | new_choice.set_parent(self.parent) |
88 | - for choice in new_choice.l: |
89 | + for choice in new_choice.choices: |
90 | choice.children = copy.copy([]) |
91 | |
92 | return new_choice |
93 | |
94 | def get_possible_names(self): |
95 | - return [x.name for x in self.l] |
96 | + return [x.name for x in self.choices] |
97 | |
98 | def set_parent(self, parent): |
99 | self.parent = parent |
100 | - for choice in self.l: |
101 | + for choice in self.choices: |
102 | choice.parent = parent |
103 | |
104 | def write_core(self, parent): |
105 | - l = self.l |
106 | - for i in range(len(l)): |
107 | - if self.index == i: |
108 | - l[i].write_core(parent) |
109 | -# else: |
110 | -# root=etree.Element(parent.tag) |
111 | -# l[i].write_core(root) |
112 | -# comment_buffer = StringIO.StringIO(etree.tostring(root)) |
113 | -# comment_text = ("DIAMOND MAGIC COMMENT (neglected choice subtree %s):\n" % l[i].schemaname) |
114 | -# comment_text = comment_text + base64.b64encode(bz2.compress(comment_buffer.getvalue())) |
115 | -# parent.append(etree.Comment(unicode(comment_text))) |
116 | - |
117 | + self.choices[self.index].write_core(parent) |
118 | return parent |
119 | |
120 | - def choices(self): |
121 | - return self.l |
122 | - |
123 | def is_comment(self): |
124 | return False |
125 | |
126 | @@ -167,7 +153,7 @@ |
127 | return [self.get_current_tree()] |
128 | |
129 | def get_choices(self): |
130 | - return self.l |
131 | + return self.choices |
132 | |
133 | def is_hidden(self): |
134 | """ |
135 | @@ -176,20 +162,7 @@ |
136 | return False |
137 | |
138 | def get_name_path(self, leaf = True): |
139 | - name = self.get_display_name() if leaf else self.get_name() |
140 | - |
141 | - if self.parent is None: |
142 | - return name |
143 | - else: |
144 | - |
145 | - pname = self.parent.get_name_path(False) |
146 | - |
147 | - if name is None: |
148 | - return pname |
149 | - elif pname is None: |
150 | - return name |
151 | - else: |
152 | - return pname + "/" + name |
153 | + return self.get_current_tree().get_name_path(leaf) |
154 | |
155 | def get_mixed_data(self): |
156 | return self |
157 | @@ -203,4 +176,7 @@ |
158 | """ |
159 | return self.get_display_name() |
160 | |
161 | + def __repr__(self): |
162 | + return self.get_name_path() + "[" + self.name + "]" |
163 | + |
164 | gobject.type_register(Choice) |
165 | |
166 | === modified file 'diamond/diamond/interface.py' |
167 | --- diamond/diamond/interface.py 2011-07-28 12:03:24 +0000 |
168 | +++ diamond/diamond/interface.py 2011-07-28 14:01:27 +0000 |
169 | @@ -283,9 +283,6 @@ |
170 | # if we have a relative path, make it absolute |
171 | filename = os.path.abspath(filename) |
172 | |
173 | - if filename == self.filename: |
174 | - return |
175 | - |
176 | try: |
177 | os.stat(filename) |
178 | except OSError: |
179 | @@ -638,12 +635,19 @@ |
180 | else: |
181 | return self._get_focus_widget(focus) |
182 | |
183 | + def _handle_clipboard(self, widget, signal): |
184 | + if isinstance(widget, gtk.MenuItem): |
185 | + return False |
186 | + else: |
187 | + widget = self._get_focus_widget(self.main_window) |
188 | + if widget is not self.treeview and gobject.signal_lookup(signal + "-clipboard", widget): |
189 | + widget.emit(signal + "-clipboard") |
190 | + return True |
191 | + return False |
192 | + |
193 | def on_copy(self, widget=None): |
194 | - if not isinstance(widget, gtk.MenuItem): |
195 | - widget = self._get_focus_widget(self.main_window) |
196 | - if widget is not self.treeview and gobject.signal_lookup("copy-clipboard", widget): |
197 | - widget.emit("copy-clipboard") |
198 | - return |
199 | + if self._handle_clipboard(widget, "copy"): |
200 | + return |
201 | |
202 | if isinstance(self.selected_node, mixedtree.MixedTree): |
203 | node = self.selected_node.parent |
204 | @@ -662,28 +666,39 @@ |
205 | return |
206 | |
207 | def on_paste(self, widget=None): |
208 | - if not isinstance(widget, gtk.MenuItem): |
209 | - widget = self._get_focus_widget(self.main_window) |
210 | - if widget is not self.treeview and gobject.signal_lookup("paste-clipboard", widget): |
211 | - widget.emit("paste-clipboard") |
212 | - return |
213 | + if self._handle_clipboard(widget, "paste"): |
214 | + return |
215 | |
216 | clipboard = gtk.clipboard_get() |
217 | ios = StringIO.StringIO(clipboard.wait_for_text()) |
218 | |
219 | if self.selected_iter is not None: |
220 | - node = self.treestore.get_value(self.selected_iter, 1) |
221 | + node = self.treestore.get_value(self.selected_iter, 0) |
222 | |
223 | if node != None: |
224 | + |
225 | + expand = not node.active |
226 | + if expand: |
227 | + self.expand_tree(self.selected_iter) |
228 | |
229 | newnode = self.s.read(ios, node) |
230 | |
231 | if newnode is None: |
232 | + if expand: |
233 | + self.collapse_tree(self.selected_iter, False) |
234 | self.statusbar.set_statusbar("Trying to paste invalid XML.") |
235 | return |
236 | |
237 | - if not node.active: |
238 | - self.expand_tree(self.selected_iter) |
239 | + if node.parent is not None: |
240 | + newnode.set_parent(node.parent) |
241 | + children = node.parent.get_children() |
242 | + children.insert(children.index(node), newnode) |
243 | + children.remove(node) |
244 | + |
245 | + self.set_treestore(self.selected_iter, [newnode], True, True) |
246 | + |
247 | + newnode.recompute_validity() |
248 | + self.treeview.queue_draw() |
249 | |
250 | # Extract and display validation errors |
251 | lost_eles, added_eles, lost_attrs, added_attrs = self.s.read_errors() |
252 | @@ -710,12 +725,6 @@ |
253 | dialogs.long_message(self.main_window, msg) |
254 | |
255 | self.set_saved(False) |
256 | - |
257 | - self.treeview.freeze_child_notify() |
258 | - iter = self.set_treestore(self.selected_iter, [newnode], True, True) |
259 | - self.treeview.thaw_child_notify() |
260 | - |
261 | - self.treeview.get_selection().select_iter(iter) |
262 | |
263 | return |
264 | |
265 | @@ -907,7 +916,7 @@ |
266 | if replace: |
267 | replacediter = iter |
268 | iter = self.treestore.iter_parent(replacediter) |
269 | - else: |
270 | + else: |
271 | self.remove_children(iter) |
272 | |
273 | for t in new_tree: |
274 | @@ -1119,7 +1128,7 @@ |
275 | |
276 | return |
277 | |
278 | - def collapse_tree(self, iter): |
279 | + def collapse_tree(self, iter, confirm = True): |
280 | """ |
281 | Collapses part of the tree. |
282 | """ |
283 | @@ -1147,7 +1156,7 @@ |
284 | self.set_saved(False) |
285 | self.remove_children(iter) |
286 | else: |
287 | - self.delete_tree(iter) |
288 | + self.delete_tree(iter, confirm) |
289 | |
290 | elif choice_or_tree.cardinality == "+": |
291 | count = parent_tree.count_children_by_schemaname(choice_or_tree.schemaname) |
292 | @@ -1155,20 +1164,23 @@ |
293 | # do nothing |
294 | return |
295 | else: # count > 2 |
296 | - self.delete_tree(iter) |
297 | + self.delete_tree(iter, confirm) |
298 | |
299 | parent_tree.recompute_validity() |
300 | self.treeview.queue_draw() |
301 | return |
302 | |
303 | - def delete_tree(self, iter): |
304 | + def delete_tree(self, iter, confirm): |
305 | choice_or_tree, = self.treestore.get(iter, 0) |
306 | parent_tree = choice_or_tree.parent |
307 | isSelected = self.treeview.get_selection().iter_is_selected(iter) |
308 | sibling = self.treestore.iter_next(iter) |
309 | |
310 | - confirm = dialogs.prompt(self.main_window, "Are you sure you want to delete this node?") |
311 | - if confirm == gtk.RESPONSE_YES: |
312 | + if confirm: |
313 | + response = dialogs.prompt(self.main_window, "Are you sure you want to delete this node?") |
314 | + |
315 | + # not A or B == A implies B |
316 | + if not confirm or response == gtk.RESPONSE_YES: |
317 | parent_tree.delete_child_by_ref(choice_or_tree) |
318 | self.remove_children(iter) |
319 | self.treestore.remove(iter) |
320 | |
321 | === modified file 'diamond/diamond/schema.py' |
322 | --- diamond/diamond/schema.py 2011-07-18 11:49:27 +0000 |
323 | +++ diamond/diamond/schema.py 2011-07-28 14:01:27 +0000 |
324 | @@ -142,10 +142,10 @@ |
325 | return results |
326 | |
327 | def valid_node(self, eid): |
328 | - if isinstance(eid, tree.Tree): |
329 | + if isinstance(eid, tree.Tree) or isinstance(eid, choice.Choice): |
330 | eidtree = eid |
331 | eid = eid.schemaname |
332 | - |
333 | + |
334 | if eid == ":start": |
335 | try: |
336 | node = self.tree.xpath('/t:grammar/t:start', namespaces={'t': 'http://relaxng.org/ns/structure/1.0'})[0] |
337 | @@ -162,12 +162,8 @@ |
338 | node = self.to_tree(node) |
339 | |
340 | if eidtree is not None: |
341 | - if eidtree.parent is not None: |
342 | - eidtree.parent.children.append(node) |
343 | - eidtree.parent.children.remove(eidtree) |
344 | - node.set_parent(eidtree.parent) |
345 | - node.attrs = eidtree.attrs |
346 | node.cardinality = eidtree.cardinality |
347 | + node.parent = eidtree.parent |
348 | |
349 | return node |
350 | |
351 | @@ -176,7 +172,7 @@ |
352 | f = self.callbacks[tag] |
353 | facts = {} |
354 | x = f(element, facts) |
355 | - return x |
356 | + return x |
357 | |
358 | ############################################# |
359 | # Beginning of schema processing functions. # |
360 | @@ -389,20 +385,19 @@ |
361 | if "schemaname" in facts: |
362 | return |
363 | |
364 | + facts['schemaname'] = self.tree.getpath(element) |
365 | + |
366 | r = [] |
367 | children = self.choice_children(self.element_children(element)) |
368 | |
369 | # bloody simplified RNG |
370 | if len(children) == 2: |
371 | empty = [x for x in children if self.tag(x) == "empty"] |
372 | - nonempty = [x for x in children if self.tag(x) != "empty"] |
373 | - if len(empty) > 0: |
374 | + if empty: |
375 | + nonempty = [x for x in children if self.tag(x) != "empty"] |
376 | tag = self.tag(nonempty[0]) |
377 | - if tag == "oneOrMore": |
378 | - return self.cb_oneormore(element, facts) |
379 | - else: |
380 | - f = self.callbacks[tag] |
381 | - return f(element, facts) |
382 | + f = self.callbacks[tag] |
383 | + return f(element, facts) |
384 | |
385 | for child in children: |
386 | newfacts = {} |
387 | @@ -533,7 +528,7 @@ |
388 | |
389 | xmlnode = doc.getroot() |
390 | self.xml_read_merge(datatree, xmlnode) |
391 | - self.xml_read_core(datatree, xmlnode, doc) |
392 | + self.xml_read_core(datatree.get_current_tree(), xmlnode, doc) |
393 | |
394 | if len(self.lost_eles) != 0: |
395 | debug.deprint("WARNING: Lost XML elements:\n" + str(self.lost_eles)) |
396 | @@ -564,7 +559,7 @@ |
397 | xmlname = xmlnode.get("name") |
398 | have_found = False |
399 | |
400 | - possibles = [tree_choice for tree_choice in datatree.choices() if tree_choice.name == xmlnode.tag] |
401 | + possibles = [tree_choice for tree_choice in datatree.get_choices() if tree_choice.name == xmlnode.tag] |
402 | # first loop over the fixed-value names |
403 | for tree_choice in possibles: |
404 | if "name" not in tree_choice.attrs: |
405 | @@ -698,7 +693,7 @@ |
406 | |
407 | for schemachild in priority_queue: |
408 | if schemachild.cardinality in ['', '?']: |
409 | - for curtree in schemachild.choices(): |
410 | + for curtree in schemachild.get_choices(): |
411 | name = curtree.name |
412 | |
413 | have_fixed_name = False |
414 | @@ -725,7 +720,7 @@ |
415 | xmls[schemachild.schemaname] = copy.deepcopy([]) |
416 | elif schemachild.cardinality in ['*', '+']: |
417 | xmls[schemachild.schemaname] = copy.deepcopy([]) |
418 | - for curtree in schemachild.choices(): |
419 | + for curtree in schemachild.get_choices(): |
420 | name = curtree.name |
421 | |
422 | have_fixed_name = False |
423 | @@ -803,7 +798,7 @@ |
424 | bins[schemachild.schemaname].append(child) |
425 | |
426 | # search for neglected choices |
427 | - if schemachild.__class__ is choice.Choice and schemachild.cardinality in ['', '?']: |
428 | + if isinstance(schemachild, choice.Choice) and schemachild.cardinality in ['', '?']: |
429 | for child in bins[schemachild.schemaname]: |
430 | |
431 | # Does the child have a valid XML node attached? |
432 | @@ -811,7 +806,7 @@ |
433 | if child.xmlnode is None: continue |
434 | |
435 | current_choice = child.get_current_tree() |
436 | - for tree_choice in child.l: |
437 | + for tree_choice in child.get_choices(): |
438 | if tree_choice is current_choice: continue |
439 | |
440 | return bins |
441 | |
442 | === modified file 'diamond/diamond/tree.py' |
443 | --- diamond/diamond/tree.py 2011-07-26 14:04:07 +0000 |
444 | +++ diamond/diamond/tree.py 2011-07-28 14:01:27 +0000 |
445 | @@ -266,7 +266,7 @@ |
446 | |
447 | sub_tree=etree.Element(self.name) |
448 | |
449 | - for key in self.attrs.keys(): |
450 | + for key in self.attrs: |
451 | val = self.attrs[key] |
452 | output_val = val[1] |
453 | if output_val is not None: |
454 | @@ -275,17 +275,9 @@ |
455 | for child in self.children: |
456 | if child.active is True: |
457 | child.write_core(sub_tree) |
458 | -# else: |
459 | -# if child.cardinality == '?': |
460 | -# root=etree.Element(self.name) |
461 | -# child.write_core(root) |
462 | -# comment_buffer = StringIO.StringIO(etree.tostring(root)) |
463 | -# comment_text = ("DIAMOND MAGIC COMMENT (inactive optional subtree %s):\n" % child.schemaname) |
464 | -# comment_text = comment_text + base64.b64encode(bz2.compress(comment_buffer.getvalue())) |
465 | -# sub_tree.append(etree.Comment(unicode(comment_text))) |
466 | |
467 | if self.data is not None: |
468 | - sub_tree.text=(unicode(self.data)) |
469 | + sub_tree.text = unicode(self.data) |
470 | |
471 | if parent is not None: |
472 | parent.append(sub_tree) |
473 | @@ -541,6 +533,9 @@ |
474 | |
475 | def __str__(self): |
476 | return self.get_display_name() |
477 | - |
478 | + |
479 | + def __repr__(self): |
480 | + return self.get_name_path() |
481 | + |
482 | gobject.type_register(Tree) |
483 |
With that branch I'm still getting the same error:
File "/usr/lib/ python2. 7/dist- packages/ diamond/ interface. py", line 695, in on_paste python2. 7/dist- packages/ diamond/ schema. py", line 532, in read node(root) python2. 7/dist- packages/ diamond/ schema. py", line 167, in valid_node parent. children. remove( eidtree)
newnode = self.s.read(ios, node)
File "/usr/lib/
datatree = self.valid_
File "/usr/lib/
eidtree.
ValueError: list.remove(x): x not in list
and behaviour as reported in bug #811200 (i.e. saving the file immediately afterwards saves a file that's different from the one you're seeing and you also don't get a copied branch of the tree).
Can anyone else reproduce this or have I mangled my paths somewhere? (I packaged the branch and installed it so shouldn't be mixing versions of diamond.)