Merge lp:~facundo/magicicada-gui/stop-rezero into lp:magicicada-gui

Proposed by Facundo Batista
Status: Merged
Approved by: Natalia Bidart
Approved revision: 139
Merged at revision: 137
Proposed branch: lp:~facundo/magicicada-gui/stop-rezero
Merge into: lp:magicicada-gui
Diff against target: 556 lines (+59/-335)
7 files modified
magicicada/gui/gtk/operations.py (+25/-6)
magicicada/gui/gtk/tests/test_operations.py (+17/-8)
magicicada/queue_content.py (+1/-1)
magicicada/syncdaemon.py (+15/-12)
magicicada/tests/test_syncdaemon.py (+1/-1)
pylintrc (+0/-306)
test (+0/-1)
To merge this branch: bzr merge lp:~facundo/magicicada-gui/stop-rezero
Reviewer Review Type Date Requested Status
Natalia Bidart Approve
Review via email: mp+196786@code.launchpad.net

Commit message

Reuse current Operations TreeStore instead of clearing and filling from scratch.

Description of the change

Reuse current Operations TreeStore instead of clearing and filling from scratch.

This has two important effects:

1) Much much more efficient when handling changes in big trees.

2) Stop resetting to zero the transfers when changes go in.

Tests adjusted and created.

To post a comment you must log in.
139. By Facundo Batista

Small fixes.

Revision history for this message
Natalia Bidart (nataliabidart) wrote :

Looks great!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'magicicada/gui/gtk/operations.py'
2--- magicicada/gui/gtk/operations.py 2012-09-19 23:28:39 +0000
3+++ magicicada/gui/gtk/operations.py 2013-11-27 18:36:06 +0000
4@@ -122,6 +122,15 @@
5 row_key = None
6 transfer_ops = []
7 show_transfer = False
8+ current_children = []
9+
10+ if parent_iter is None:
11+ # parent being None complicates how the children are get
12+ nch = self.ops_store.iter_n_children(None)
13+ current_children = [self.ops_store[i] for i in range(nch)]
14+ else:
15+ # get the items at this level (chidren from parent)
16+ current_children = list(self.ops_store[parent_iter].iterchildren())
17
18 if row_info is not None:
19 transfer_ops = filter(lambda op: op[1] in TRANSFER_OPS,
20@@ -132,8 +141,17 @@
21 all_done = all(op[2][queue_content.DONE] for op in transfer_ops)
22 show_transfer = not all_done
23
24- row = row + (0, show_transfer, '')
25- tree_iter = self.ops_store.append(parent_iter, row)
26+ for child in current_children:
27+ if row[0] == child[0].decode("utf8"):
28+ # row in current children, let's just modify it
29+ child[1] = row[1]
30+ child[6] = show_transfer
31+ tree_iter = child.iter
32+ break
33+ else:
34+ # not there in current children, let's add it
35+ row = row + (0, show_transfer, '')
36+ tree_iter = self.ops_store.append(parent_iter, row)
37
38 if row_key is not None:
39 self._store_idx[row_key] = tree_iter
40@@ -173,20 +191,21 @@
41 else:
42 self._append_file_row(child_name, child_info, parent)
43
44- def on_node_ops_changed(self, items, *args, **kwargs):
45+ def on_node_ops_changed(self, items, clear=False):
46 """Callback'ed when syncadaemon's node ops info changed."""
47 if not items:
48 items = []
49
50 self.ops_view.set_model(None)
51- self.ops_store.clear()
52+ if clear:
53+ self.ops_store.clear()
54 self._can_clear = False
55
56 for root_kind, root_info in items:
57 icon_name = (HOME_ICON_NAME
58 if root_kind == queue_content.ROOT_HOME
59 else REMOTE_ICON_NAME)
60- row = ('', '', None, icon_name, Gtk.IconSize.LARGE_TOOLBAR)
61+ row = (root_kind, '', None, icon_name, Gtk.IconSize.LARGE_TOOLBAR)
62 parent = self._append_row(None, row)
63 self._append_root_row(root_info, parent)
64
65@@ -201,7 +220,7 @@
66 def on_clear_button_clicked(self, button):
67 """The clear button was clicked, remove all complete operations."""
68 self.sd.queue_content.clear()
69- self.load()
70+ self.on_node_ops_changed(self.sd.queue_content.node_ops, clear=True)
71
72 def load(self):
73 """Update UI based on SD current state."""
74
75=== modified file 'magicicada/gui/gtk/tests/test_operations.py'
76--- magicicada/gui/gtk/tests/test_operations.py 2012-09-19 23:28:39 +0000
77+++ magicicada/gui/gtk/tests/test_operations.py 2013-11-27 18:36:06 +0000
78@@ -100,9 +100,9 @@
79
80 root = [u'', u'', None, operations.HOME_ICON_NAME,
81 Gtk.IconSize.LARGE_TOOLBAR]
82- yada = [u'', u'', None, operations.REMOTE_ICON_NAME,
83+ yada = [u'Yadda', u'', None, operations.REMOTE_ICON_NAME,
84 Gtk.IconSize.LARGE_TOOLBAR]
85- yoda = [u'', u'', None, operations.REMOTE_ICON_NAME,
86+ yoda = [u'Yodda', u'', None, operations.REMOTE_ICON_NAME,
87 Gtk.IconSize.LARGE_TOOLBAR]
88
89 self.assert_store_correct([(root, []), (yada, []), (yoda, [])])
90@@ -116,7 +116,7 @@
91 sd_items = [(u'Yadda', {node.name: node})]
92 self.sd.on_node_ops_changed_callback(sd_items)
93
94- yada = [u'', u'', None, operations.REMOTE_ICON_NAME,
95+ yada = [u'Yadda', u'', None, operations.REMOTE_ICON_NAME,
96 Gtk.IconSize.LARGE_TOOLBAR]
97 node_row = [node.name, u'', None,
98 operations.FOLDER_ICON_NAME, Gtk.IconSize.SMALL_TOOLBAR]
99@@ -143,7 +143,7 @@
100 sd_items = [(u'Yadda', {node.name: node})]
101 self.sd.on_node_ops_changed_callback(sd_items)
102
103- yada = [u'', u'', None, operations.REMOTE_ICON_NAME,
104+ yada = [u'Yadda', u'', None, operations.REMOTE_ICON_NAME,
105 Gtk.IconSize.LARGE_TOOLBAR]
106 node_row = [node.name, u'', None,
107 operations.FOLDER_ICON_NAME, Gtk.IconSize.SMALL_TOOLBAR]
108@@ -171,7 +171,7 @@
109 sd_items = [(u'Yadda', {file_node.name: file_node})]
110 self.sd.on_node_ops_changed_callback(sd_items)
111
112- yada = [u'', u'', None, operations.REMOTE_ICON_NAME,
113+ yada = [u'Yadda', u'', None, operations.REMOTE_ICON_NAME,
114 Gtk.IconSize.LARGE_TOOLBAR]
115 op_name = u'foo, bar, ' + long_op_name
116 op_name = op_name[:operations.MAX_OP_LEN - len(operations.ELLIPSIS)]
117@@ -202,9 +202,18 @@
118 (u'Yadda', {}), (u'Yodda', {})]
119 self.sd.on_node_ops_changed_callback(sd_items)
120
121- self.sd.on_node_ops_changed_callback([])
122+ self.sd.on_node_ops_changed_callback([], clear=True)
123 self.assertEqual(len(self.ui.ops_store), 0)
124
125+ def test_model_is_not_cleared_before_updating(self):
126+ """The model is not cleared before upadting with a new set of data."""
127+ sd_items = [(operations.queue_content.ROOT_HOME, {}),
128+ (u'Yadda', {}), (u'Yodda', {})]
129+ self.sd.on_node_ops_changed_callback(sd_items)
130+
131+ self.sd.on_node_ops_changed_callback([])
132+ self.assertEqual(len(self.ui.ops_store), 3)
133+
134 def test_load(self):
135 """Calling load will query the backend."""
136 expected = object()
137@@ -217,7 +226,7 @@
138
139 def test_clear_button_clicked(self):
140 """When the clear button was clicked, the store is cleared."""
141- self.patch(self.ui, 'load', self._set_called)
142+ self.patch(self.ui, 'on_node_ops_changed', self._set_called)
143 sd_items = [(operations.queue_content.ROOT_HOME, {}),
144 (u'Yadda', {}), (u'Yodda', {})]
145 self.sd.on_node_ops_changed_callback(sd_items)
146@@ -225,7 +234,7 @@
147 self.ui.clear_button.clicked()
148
149 self.assertEqual(len(self.ui.sd.queue_content), 0)
150- self.assertEqual(self._called, ((), {}))
151+ self.assertEqual(self._called, (([],), {'clear': True}))
152
153 def test_on_transfers_bad_data(self):
154 """Something informed that's not there."""
155
156=== modified file 'magicicada/queue_content.py'
157--- magicicada/queue_content.py 2012-09-05 16:09:39 +0000
158+++ magicicada/queue_content.py 2013-11-27 18:36:06 +0000
159@@ -27,7 +27,7 @@
160 KIND_UNKNOWN, KIND_FILE, KIND_DIR = "Unknown File Dir".split()
161
162 # type of roots (so far, only home)
163-ROOT_HOME = "Root"
164+ROOT_HOME = "" # this string will appear next to the home icon in the GUI
165
166 # action that happened with the operation
167 ACTION_ADDED, ACTION_REMOVED = "Added Removed".split()
168
169=== modified file 'magicicada/syncdaemon.py'
170--- magicicada/syncdaemon.py 2012-09-19 23:28:39 +0000
171+++ magicicada/syncdaemon.py 2013-11-27 18:36:06 +0000
172@@ -40,17 +40,17 @@
173 TRANSFER_POLL_INTERVAL = 5
174
175 # status of the node
176-CHANGED_LOCAL = u"uploading"
177-CHANGED_NONE = u"synchronized"
178-CHANGED_SERVER = u"downloading"
179+CHANGED_LOCAL = u"UPLOADING"
180+CHANGED_NONE = u"SYNCHRONIZED"
181+CHANGED_SERVER = u"DOWNLOADING"
182
183 # state of SD
184-STATE_CONNECTING = u"connecting"
185-STATE_DISCONNECTED = u"disconnected"
186-STATE_IDLE = u"idle"
187-STATE_STARTING = u"starting"
188-STATE_STOPPED = u"stopped"
189-STATE_WORKING = u"working"
190+STATE_CONNECTING = u"CONNECTING"
191+STATE_DISCONNECTED = u"DISCONNECTED"
192+STATE_IDLE = u"IDLE"
193+STATE_STARTING = u"STARTING"
194+STATE_STOPPED = u"STOPPED"
195+STATE_WORKING = u"WORKING"
196
197
198 def mandatory_callback(function_name):
199@@ -66,8 +66,10 @@
200 class State(object):
201 """Hold the state of SD."""
202
203- _attrs = ['name', 'description', 'is_error', 'is_connected',
204- 'is_online', 'queues', 'connection', 'is_started', 'state']
205+ _attrs = {'name', 'description', 'is_error', 'is_connected',
206+ 'is_online', 'queues', 'connection', 'is_started', 'state'}
207+ _toshow = ['name', 'is_error', 'is_connected',
208+ 'is_online', 'queues', 'connection', 'is_started', 'state']
209
210 def __init__(self):
211 # starting defaults
212@@ -100,7 +102,8 @@
213 result = []
214 for attr in self._attrs:
215 result.append("%s=%s" % (attr, getattr(self, attr)))
216- return "<%s>" % ", ".join(result)
217+ return "<State %s>" % ", ".join(result)
218+ __repr__ = __str__
219
220
221 class Poller(object):
222
223=== modified file 'magicicada/tests/test_syncdaemon.py'
224--- magicicada/tests/test_syncdaemon.py 2012-09-19 23:28:39 +0000
225+++ magicicada/tests/test_syncdaemon.py 2013-11-27 18:36:06 +0000
226@@ -605,7 +605,7 @@
227 "is_online=False",
228 "queues='IDLE'",
229 "connection='connection'",
230- "state=u'idle'",
231+ "state=u'IDLE'",
232 )
233 self.assertTrue(self.hdlr.check_debug(*should))
234
235
236=== removed file 'pylintrc'
237--- pylintrc 2011-06-19 15:08:44 +0000
238+++ pylintrc 1970-01-01 00:00:00 +0000
239@@ -1,306 +0,0 @@
240-# lint Python modules using external checkers.
241-#
242-# This is the main checker controlling the other ones and the reports
243-# generation. It is itself both a raw checker and an astng checker in order
244-# to:
245-# * handle message activation / deactivation at the module level
246-# * handle some basic but necessary stats'data (number of classes, methods...)
247-#
248-[MASTER]
249-
250-# Specify a configuration file.
251-#rcfile=
252-
253-# Python code to execute, usually for sys.path manipulation such as
254-# pygtk.require().
255-#init-hook=
256-
257-# Profiled execution.
258-profile=no
259-
260-# Add <file or directory> to the black list. It should be a base name, not a
261-# path. You may set this option multiple times.
262-#ignore=<somedir>
263-
264-# Pickle collected data for later comparisons.
265-persistent=no
266-
267-# List of plugins (as comma separated values of python modules names) to load,
268-# usually to register additional checkers.
269-load-plugins=
270-
271-
272-[MESSAGES CONTROL]
273-
274-# Enable only checker(s) with the given id(s). This option conflicts with the
275-# disable-checker option
276-#enable-checker=
277-
278-# Enable all checker(s) except those with the given id(s). This option
279-# conflicts with the enable-checker option
280-#disable-checker=
281-
282-# Enable the message(s) with the given id(s).
283-#enable=
284-
285-# Disable the message(s) with the given id(s).
286-# W0142: Used * or ** magic
287-# W0613: Unused argument 'yyy'
288-# E1103: Generator 'accept_share' has no 'addCallbacks' member (but some
289-# types could not be inferred). Disabled because it always complains
290-# when using the deferred returned by an inlineCallbacks
291-# E1101: Disable 'member' control, it always complains about reactor.callLater
292-disable=R,I,W0142,W0613,E1103,E1101
293-
294-
295-[REPORTS]
296-
297-# Set the output format. Available formats are text, parseable, colorized, msvs
298-# (visual studio) and html
299-output-format=colorized
300-
301-# Include message's id in output
302-include-ids=yes
303-
304-# Put messages in a separate file for each module / package specified on the
305-# command line instead of printing them on stdout. Reports (if any) will be
306-# written in a file name "pylint_global.[txt|html]".
307-files-output=no
308-
309-# Tells whether to display a full report or only the messages
310-reports=no
311-
312-# Python expression which should return a note less than 10 (10 is the highest
313-# note). You have access to the variables errors warning, statement which
314-# respectively contain the number of errors / warnings messages and the total
315-# number of statements analyzed. This is used by the global evaluation report
316-# (R0004).
317-evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
318-
319-# Add a comment according to your evaluation note. This is used by the global
320-# evaluation report (R0004).
321-comment=no
322-
323-# Enable the report(s) with the given id(s).
324-#enable-report=
325-
326-# Disable the report(s) with the given id(s).
327-#disable-report=
328-
329-
330-# try to find bugs in the code using type inference
331-#
332-[TYPECHECK]
333-
334-# Tells whether missing members accessed in mixin class should be ignored. A
335-# mixin class is detected if its name ends with "mixin" (case insensitive).
336-ignore-mixin-members=yes
337-
338-# List of classes names for which member attributes should not be checked
339-# (useful for classes with attributes dynamically set).
340-ignored-classes=
341-
342-# When zope mode is activated, add a predefined set of Zope acquired attributes
343-# to generated-members.
344-zope=no
345-
346-# List of members which are set dynamically and missed by pylint inference
347-# system, and so shouldn't trigger E0201 when accessed.
348-generated-members=REQUEST,acl_users,aq_parent
349-
350-
351-# checks for
352-# * unused variables / imports
353-# * undefined variables
354-# * redefinition of variable from builtins or from an outer scope
355-# * use of variable before assignment
356-#
357-[VARIABLES]
358-
359-# Tells whether we should check for unused import in __init__ files.
360-init-import=yes
361-
362-# A regular expression matching names used for dummy variables (i.e. not used).
363-dummy-variables-rgx=_|dummy
364-
365-# List of additional names supposed to be defined in builtins. Remember that
366-# you should avoid to define new builtins when possible.
367-additional-builtins=
368-
369-
370-# checks for :
371-# * doc strings
372-# * modules / classes / functions / methods / arguments / variables name
373-# * number of arguments, local variables, branches, returns and statements in
374-# functions, methods
375-# * required module attributes
376-# * dangerous default values as arguments
377-# * redefinition of function / method / class
378-# * uses of the global statement
379-#
380-[BASIC]
381-
382-# Required attributes for module, separated by a comma
383-required-attributes=
384-
385-# Regular expression which should only match functions or classes name which do
386-# not require a docstring
387-no-docstring-rgx=(__.*__|setUp|tearDown)
388-
389-# Regular expression which should only match correct module names
390-module-rgx=([a-z_][a-z0-9_]*)$
391-
392-# Regular expression which should only match correct module level names
393-const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
394-
395-# Regular expression which should only match correct class names
396-class-rgx=[A-Z_][a-zA-Z0-9]+$
397-
398-# Regular expression which should only match correct function names
399-function-rgx=[a-z_][a-z0-9_]{2,79}$
400-
401-# Regular expression which should only match correct method names
402-method-rgx=([a-z_][a-z0-9_]{2,79}$|setUp|tearDown)
403-
404-# Regular expression which should only match correct instance attribute names
405-attr-rgx=[a-z_][a-z0-9_]{1,50}$
406-
407-# Regular expression which should only match correct argument names
408-argument-rgx=[a-z_][a-z0-9_]{1,30}$
409-
410-# Regular expression which should only match correct variable names
411-variable-rgx=[a-z_][a-z0-9_]{0,30}$
412-
413-# Regular expression which should only match correct list comprehension /
414-# generator expression variable names
415-inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
416-
417-# Good variable names which should always be accepted, separated by a comma
418-good-names=f,logger,_
419-
420-# Bad variable names which should always be refused, separated by a comma
421-bad-names=foo,bar,baz,toto,tutu,tata
422-
423-# List of builtins function names that should not be used, separated by a comma
424-bad-functions=apply,input
425-
426-
427-# checks for sign of poor/misdesign:
428-# * number of methods, attributes, local variables...
429-# * size, complexity of functions, methods
430-#
431-[DESIGN]
432-
433-# Maximum number of arguments for function / method
434-max-args=5
435-
436-# Maximum number of locals for function / method body
437-max-locals=15
438-
439-# Maximum number of return / yield for function / method body
440-max-returns=6
441-
442-# Maximum number of branch for function / method body
443-max-branchs=12
444-
445-# Maximum number of statements in function / method body
446-max-statements=50
447-
448-# Maximum number of parents for a class (see R0901).
449-max-parents=7
450-
451-# Maximum number of attributes for a class (see R0902).
452-max-attributes=7
453-
454-# Minimum number of public methods for a class (see R0903).
455-min-public-methods=2
456-
457-# Maximum number of public methods for a class (see R0904).
458-max-public-methods=20
459-
460-
461-# checks for :
462-# * methods without self as first argument
463-# * overridden methods signature
464-# * access only to existent members via self
465-# * attributes not defined in the __init__ method
466-# * supported interfaces implementation
467-# * unreachable code
468-#
469-[CLASSES]
470-
471-# List of interface methods to ignore, separated by a comma. This is used for
472-# instance to not check methods defines in Zopes Interface base class.
473-#ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by,providedBy
474-
475-# List of method names used to declare (i.e. assign) instance attributes.
476-defining-attr-methods=__init__,__new__,setUp
477-
478-
479-# checks for
480-# * external modules dependencies
481-# * relative / wildcard imports
482-# * cyclic imports
483-# * uses of deprecated modules
484-#
485-[IMPORTS]
486-
487-# Deprecated modules which should not be used, separated by a comma
488-deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
489-
490-# Create a graph of every (i.e. internal and external) dependencies in the
491-# given file (report RP0402 must not be disabled)
492-import-graph=
493-
494-# Create a graph of external dependencies in the given file (report RP0402 must
495-# not be disabled)
496-ext-import-graph=
497-
498-# Create a graph of internal dependencies in the given file (report RP0402 must
499-# not be disabled)
500-int-import-graph=
501-
502-
503-# checks for :
504-# * unauthorized constructions
505-# * strict indentation
506-# * line length
507-# * use of <> instead of !=
508-#
509-[FORMAT]
510-
511-# Maximum number of characters on a single line.
512-max-line-length=79
513-
514-# Maximum number of lines in a module
515-max-module-lines=2000
516-
517-# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
518-# tab).
519-indent-string=' '
520-
521-
522-# checks for similarities and duplicated code. This computation may be
523-# memory / CPU intensive, so you should disable it if you experiments some
524-# problems.
525-#
526-[SIMILARITIES]
527-
528-# Minimum lines number of a similarity.
529-min-similarity-lines=4
530-
531-# Ignore comments when computing similarities.
532-ignore-comments=yes
533-
534-# Ignore docstrings when computing similarities.
535-ignore-docstrings=yes
536-
537-
538-# checks for:
539-# * warning notes in the code like FIXME, XXX
540-# * PEP 263: source code with non ascii character but no encoding declaration
541-#
542-[MISCELLANEOUS]
543-
544-# List of note tags to take in consideration, separated by a comma.
545-notes=FIXME,XXX,TODO,fixme,xxx,todo
546
547=== modified file 'test'
548--- test 2012-09-06 19:36:44 +0000
549+++ test 2013-11-27 18:36:06 +0000
550@@ -26,6 +26,5 @@
551
552 echo "Running test suite for ""$MODULE"
553 `which xvfb-run` trial -r gi "$MODULE"
554-pylint magicicada
555 rm -rf _trial_temp
556 rm -rf _logs_temp

Subscribers

People subscribed via source and target branches