update to cw 3.14 / tracker 1.10 api: iprogress/tables. Closes #2072168

* * *
pylint fixes

authorSylvain Th?nault <sylvain.thenault@logilab.fr>
changeset7bac9fce84b8
branchdefault
phasepublic
hiddenno
parent revision#0d50bdd4023e backport stable
child revision#3360fb713c5c i18nupdate
files modified by this revision
__pkginfo__.py
debian/control
entities.py
hooks.py
test/unittest_forge.py
views/boxes.py
views/forms.py
views/project.py
views/ticket.py
views/version.py
# HG changeset patch
# User Sylvain Thénault <sylvain.thenault@logilab.fr>
# Date 1320423440 -3600
# Fri Nov 04 17:17:20 2011 +0100
# Node ID 7bac9fce84b8da208c0d92c0e3acc25553926e72
# Parent 0d50bdd4023e55a5d9feb77b46d5b7779c9b3c7f
update to cw 3.14 / tracker 1.10 api: iprogress/tables. Closes #2072168
* * *
pylint fixes

diff --git a/__pkginfo__.py b/__pkginfo__.py
@@ -26,11 +26,11 @@
1                 'cubicweb-file': '>= 1.2.0',
2                 'cubicweb-folder': '>= 1.1.0',
3                 'cubicweb-mailinglist': '>= 1.1.0',
4                 'cubicweb-tag': '>= 1.2.0',
5                 'cubicweb-testcard': None,
6 -               'cubicweb-tracker': '>= 1.7.0',
7 +               'cubicweb-tracker': '>= 1.10.0',
8                 'cubicweb-nosylist': None,
9                 }
10 
11 
12  # packaging ###
diff --git a/debian/control b/debian/control
@@ -11,11 +11,11 @@
13  Architecture: all
14  Depends: cubicweb-common (>= 3.14.0),
15           cubicweb-comment (>= 1.2.0), cubicweb-email (>= 1.2.1),
16           cubicweb-file (>= 1.2.0), cubicweb-folder (>= 1.1.0),
17           cubicweb-mailinglist (>= 1.1.0), cubicweb-nosylist,
18 -         cubicweb-tag (>= 1.2.0), cubicweb-tracker (>= 1.7.0),
19 +         cubicweb-tag (>= 1.2.0), cubicweb-tracker (>= 1.10.0),
20           cubicweb-testcard, cubicweb-card
21  Description: forge component for the CubicWeb framework
22   This CubicWeb component provides a Forge application
23   that supports the process of collaborative developing software.
24   .
diff --git a/entities.py b/entities.py
@@ -1,9 +1,9 @@
25  """forge specific entities class for imported entities
26 
27  :organization: Logilab
28 -:copyright: 2006-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
29 +:copyright: 2006-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
30  :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
31  """
32  __docformat__ = "restructuredtext en"
33 
34  from datetime import datetime, date, timedelta
@@ -17,48 +17,31 @@
35  from cubes.card.entities import Card as BaseCard
36  from cubes.file.entities import File as BaseFile
37  from cubes.comment.entities import Comment as BaseComment
38  from cubes.email.entities import Email as BaseEmail
39  from cubes.tracker.entities import project, version, ticket
40 -from cubes.tracker.entities import ProjectItemMixIn, fixed_orderby_rql
41 +from cubes.tracker.entities import ProjectItemMixIn
42 
43 
44  # project / extproject #########################################################
45 
46 
47  class ExtProject(AnyEntity):
48      __regid__ = 'ExtProject'
49      __permissions__ = ('developer', 'client')
50 
51 -    fetch_attrs, fetch_order = fetch_config(['name', 'description', 'description_format'])
52 +    fetch_attrs, cw_fetch_order = fetch_config(['name', 'description', 'description_format'])
53 
54      def dc_title(self, format='text/plain'):
55          return self.name
56 
57 
58  class Project(project.Project):
59 
60      __permissions__ = ('developer', 'client')
61      fetch_attrs = project.Project.fetch_attrs + ('homepage', 'summary')
62 
63 -    TICKET_DEFAULT_STATE_RESTR = 'S name IN ("open","done","waiting feedback","in-progress","validation pending")'
64 -
65 -    # number of columns to display
66 -    tickets_rql_nb_displayed_cols = 10
67 -    sort_defs = (('in_state', 'S'), ('num', 'VN'), ('type', 'TT'),
68 -                 ('priority', 'PR'))
69 -    def tickets_rql(self, limit=None):
70 -        return ('Any B,TT,NOW - CD, NOW - BMD, U,PR,S,C,V,group_concat(TN),BDF,BD,BC,VN,P,BT,CD,BMD,UL '
71 -                'GROUPBY B,TT,CD,PR,S,C,V,U,VN,BDF,BD,BC,P,BT,BMD,UL %s %s WHERE '
72 -                'B type TT, B priority PR, B in_state S, B creation_date CD, '
73 -                'B description_format BDF, B description BD, B load_left BC, '
74 -                'B title BT, B modification_date BMD, '
75 -                'B load C, T? tags B, T name TN, B done_in V?, V num VN, '
76 -                'B created_by U?, U login UL, B concerns P, P eid %%(x)s'
77 -                % (fixed_orderby_rql(self.sort_defs),
78 -                   limit and ' LIMIT %s' % limit or ''),
79 -                {'x': self.eid})
80 
81 
82  class ProjectIFTIndexableAdapter(IFTIndexableAdapter):
83      __select__ = is_instance('Project')
84      entity_weight = 20.0
@@ -119,35 +102,10 @@
85          progress_done = max(0, progress_target - progress_todo)
86          self.set_attributes(progress_target=progress_target,
87                              progress_todo=progress_todo,
88                              progress_done=progress_done)
89 
90 -    # ui utilities ############################################################
91 -
92 -    # number of columns to display
93 -    tickets_rql_nb_displayed_cols = 8
94 -    sort_defs = (('in_state', 'S'), ('type', 'TT'), ('priority', 'PR'))
95 -    def tickets_rql(self):
96 -        """rql for tickets done / todo in this version"""
97 -        return ('Any B,TT,PR,S,C,AC,U,group_concat(TN), TI,D,DF,V '
98 -                'GROUPBY B,TT,PR,S,C,AC,U,TI,D,DF,V %s '
99 -                'WHERE B type TT, B priority PR, B load_left AC, B load C, '
100 -                'B in_state S, T? tags B, T name TN, B created_by U?,'
101 -                'B done_in V, V eid %%(x)s, '
102 -                'B title TI, B description D, B description_format DF'
103 -                % fixed_orderby_rql(self.sort_defs), {'x': self.eid})
104 -
105 -    defects_rql_nb_displayed_cols = 5
106 -    def defects_rql(self):
107 -        """rql for defects appeared in this version"""
108 -        return ('Any B,S,V,U,group_concat(TN), BT,BD,BDF '
109 -                'GROUPBY B,S,V,U,BT,BD,BDF ORDERBY S '
110 -                'WHERE B in_state S, T? tags B, T name TN, B created_by U?,'
111 -                'B done_in V?, B appeared_in X, X eid %(x)s, '
112 -                'B title BT, B description BD, B description_format BDF',
113 -                {'x': self.eid})
114 -
115 
116  class VersionIMileStoneAdapter(version.VersionIMileStoneAdapter):
117 
118      def progress_info(self):
119          """returns a dictionary describing load and progress of the version"""
@@ -234,11 +192,11 @@
120              return self.cw_adapt_to('ITree').root().project
121          except AttributeError:
122              return None
123 
124 
125 -class File(ProjectItemMixIn, BaseFile):
126 +class File(BaseFile):
127 
128      @property
129      def project(self):
130          """project item interface"""
131          if self.reverse_documented_by:
diff --git a/hooks.py b/hooks.py
@@ -1,17 +1,16 @@
132  """Forge cube hooks
133 
134  :organization: Logilab
135 -:copyright: 2006-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
136 +:copyright: 2006-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
137  :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
138  """
139  __docformat__ = "restructuredtext en"
140 
141  from datetime import datetime
142 
143 -from cubicweb import ValidationError
144 -from cubicweb.server.hook import Hook, Operation
145 +from cubicweb.server.hook import Hook
146  from cubicweb.selectors import is_instance
147  from cubicweb.server import hook
148 
149  from cubes.tracker import hooks as tracker
150  from cubes.nosylist import hooks as nosylist
diff --git a/test/unittest_forge.py b/test/unittest_forge.py
@@ -35,14 +35,10 @@
151              iworkflowable.fire_transition(tr)
152              self.commit()
153              ticket.cw_clear_all_caches()
154              self.assertEqual(iworkflowable.state, state)
155 
156 -    def test_tickets_rql(self):
157 -        self.execute(self.cubicweb.active_tickets_rql()) # just check rql validity
158 -        self.execute(*self.cubicweb.tickets_rql()) # just check rql validity
159 -
160      def test_download_box(self):
161          req = self.request()
162          rset = req.execute('Any X WHERE X is Project, X name "cubicweb"')
163          self.assertRaises(NoSelectableObject,
164                            self.vreg['ctxcomponents'].select, 'download_box', req, rset=rset)
diff --git a/views/boxes.py b/views/boxes.py
@@ -6,11 +6,10 @@
165  """
166  __docformat__ = "restructuredtext en"
167 
168  from logilab.mtconverter import xml_escape
169 
170 -from cubicweb.schema import display_name
171  from cubicweb.selectors import is_instance, score_entity, has_related_entities
172  from cubicweb.view import EntityAdapter
173  from cubicweb.web import component
174  from cubicweb.web.views import boxes
175  from cubicweb.utils import transitive_closure_of
diff --git a/views/forms.py b/views/forms.py
@@ -1,11 +1,11 @@
176  from copy import copy
177 
178  from cubicweb.web import stdmsgs, formwidgets, eid_param
179  from cubicweb.web.formfields import RelationField
180  from cubicweb.web.views.workflow import ChangeStateFormView
181 -from cubicweb.selectors import is_instance, rql_condition, is_in_state, match_transition
182 +from cubicweb.selectors import is_instance, is_in_state, match_transition
183 
184  class NotValidatedChangeView(ChangeStateFormView):
185 
186      __select__ = (ChangeStateFormView.__select__ &
187                    is_instance('Ticket') &
@@ -44,12 +44,12 @@
188                                               **kwargs)
189 
190          followup_form = self._cw.vreg['forms'].select('edition', self._cw,
191                                                         entity=followup_tk,
192                                                         mainform=False)
193 -        followup_form.add_hidden(eid_param('__cloned_eid',followup_tk.eid),
194 -                                  entity.eid)
195 +        followup_form.add_hidden(eid_param('__cloned_eid', followup_tk.eid),
196 +                                 entity.eid)
197          followup_relation_field = RelationField(name='follow_up',
198                                                   label=self._cw._('follow-up ticket'),
199                                                   role='subject',
200                                                   eidparam=True,
201                                                   choices=[(entity.dc_title(), entity.eid)])
diff --git a/views/project.py b/views/project.py
@@ -1,30 +1,55 @@
202  """views for Project entities
203 
204  :organization: Logilab
205 -:copyright: 2006-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL.
206 +:copyright: 2006-2011 LOGILAB S.A. (Paris, FRANCE), license is LGPL.
207  :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
208  """
209  __docformat__ = "restructuredtext en"
210  _ = unicode
211 
212 +from logilab.common.decorators import monkeypatch
213  from logilab.mtconverter import xml_escape
214 
215  from cubicweb.selectors import one_line_rset, score_entity, is_instance
216  from cubicweb.view import EntityView
217 -from cubicweb import tags, uilib
218 +from cubicweb import tags
219  from cubicweb.web import uicfg, action
220 -from cubicweb.web.views import primary, tabs, baseviews
221 -
222 -from cubes.tracker.views import project as tracker
223 +from cubicweb.web.views import primary, tabs, baseviews, tableview
224 
225  from cubes.testcard import views as testcard
226 +from cubes.tracker.views import fixed_orderby_rql, project as tracker
227 +
228 
229  tracker.ProjectStatsView.default_rql = (
230      'Any P, PN WHERE P is Project, P name PN, '
231      'P in_state S, S name "active development"')
232 
233 +idx = tracker.ProjectTicketsTable.columns.index('in_state')
234 +tracker.ProjectTicketsTable.columns.insert(idx+1, 'load')
235 +tracker.ProjectTicketsTable.columns.append('tags')
236 +tracker.ProjectTicketsTable.column_renderers['tags'] = \
237 +    tableview.RelationColRenderer(role='object')
238 +
239 +tracker.ProjectTicketsTab.TICKET_DEFAULT_STATE_RESTR \
240 +    = 'S name IN ("open","done","waiting feedback","in-progress","validation pending")'
241 +
242 +@monkeypatch(tracker.ProjectTicketsTab)
243 +def tickets_rql(self):
244 +    # prefetch everything we can for optimization
245 +    return ('Any T,TTI,TT,TP,TD,TDF,TCD,TMD,TL,S,SN,V,VN,U,UL %s WHERE '
246 +            'T title TTI, T type TT, T priority TP, '
247 +            'T description TD, T description_format TDF, '
248 +            'T creation_date TCD, T modification_date TMD, '
249 +            'T load TL,'
250 +            'T in_state S, S name SN, '
251 +            'T done_in V?, V num VN, '
252 +            'T created_by U?, U login UL, '
253 +            'T concerns P, P eid %%(x)s'
254 +            % fixed_orderby_rql(self.SORT_DEFS))
255 +
256 +
257  # primary view and tabs ########################################################
258 
259  class ExtProjectPrimaryView(primary.PrimaryView):
260      __select__ = is_instance('ExtProject')
261      show_attr_label = False
@@ -125,10 +150,11 @@
262          # no summary on ext project
263          if getattr(entity, 'summary', None):
264              self.w(u'&nbsp;')
265              self.w(xml_escape(entity.summary))
266 
267 +
268  # Project actions #############################################################
269 
270  class ProjectAddRelatedAction(action.LinkToEntityAction):
271      __select__ = (action.LinkToEntityAction.__select__ & is_instance('Project')
272                    & score_entity(lambda x: x.cw_adapt_to('IWorkflowable').state != 'moved'))
diff --git a/views/ticket.py b/views/ticket.py
@@ -5,14 +5,13 @@
273  :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
274  """
275  __docformat__ = "restructuredtext en"
276  _ = unicode
277 
278 -from logilab.mtconverter import xml_escape
279 -from cubicweb.web import component, box
280 -from cubicweb.web.views import tabs, primary
281 -from cubicweb.selectors import one_line_rset, is_instance, has_related_entities
282 +from cubicweb.web import component
283 +from cubicweb.web.views import tabs
284 +from cubicweb.selectors import one_line_rset, is_instance
285 
286  class TicketTestCardCtxComponent(component.RelatedObjectsCtxComponent):
287      """display project's test cards"""
288      __regid__ = 'tickettests'
289      __select__ = component.RelatedObjectsCtxComponent.__select__ & is_instance('Ticket')
diff --git a/views/version.py b/views/version.py
@@ -1,27 +1,56 @@
290  """views for Project entities
291 
292  :organization: Logilab
293 -:copyright: 2006-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL.
294 +:copyright: 2006-2011 LOGILAB S.A. (Paris, FRANCE), license is LGPL.
295  :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
296  """
297  __docformat__ = "restructuredtext en"
298  _ = unicode
299 
300 +from copy import deepcopy
301 +
302 +from logilab.common.decorators import monkeypatch
303 +
304  from cubicweb.selectors import is_instance
305  from cubicweb.view import EntityView
306 -from cubicweb.web import uicfg, component
307 -from cubicweb.web.views import baseviews
308 +from cubicweb.web import uicfg
309 +from cubicweb.web.views import baseviews, tableview
310 
311 -from cubes.tracker.views import version as tracker
312 +from cubes.tracker.views import fixed_orderby_rql, version as tracker
313 +
314 
315  _pvs = uicfg.primaryview_section
316  for attr in ('progress_target', 'progress_done', 'progress_todo'):
317      _pvs.tag_attribute(('Version', attr), 'hidden')
318 
319  tracker.VersionPrimaryView.tabs.append(_('forge.version.burndown_tab'))
320 
321 +idx = tracker.VersionTicketsTable.columns.index('in_state')
322 +tracker.VersionTicketsTable.columns.insert(idx+1, 'load')
323 +tracker.VersionTicketsTable.columns.insert(idx+2, 'load_left')
324 +tracker.VersionTicketsTable.columns.append('tags')
325 +tracker.VersionTicketsTable.column_renderers['tags'] = tableview.RelationColRenderer(role='object')
326 +
327 +@monkeypatch(tracker.VersionPrimaryTab)
328 +def tickets_rql(self):
329 +    # prefetch everything we can for optimization
330 +    return ('Any T,TTI,TT,TP,TD,TDF,TCD,TMD,TL,TLL,S,SN %s WHERE '
331 +            'T title TTI, T type TT, T priority TP, '
332 +            'T description TD, T description_format TDF, '
333 +            'T creation_date TCD, T modification_date TMD, '
334 +            'T load TL, T load_left TLL, '
335 +            'T in_state S, S name SN, '
336 +            'T %s V, V eid %%(x)s'
337 +            % (fixed_orderby_rql(self.SORT_DEFS), self.TICKETS_RELATION))
338 +
339 +
340 +class VersionProgressTableView(tracker.VersionProgressTableView):
341 +    column_renderers = deepcopy(tracker.VersionProgressTableView.column_renderers)
342 +    column_renderers['cost'].header = _('load')
343 +
344 +
345  # we don't want IDownloadable oneline view for version
346  class VersionOneLineView(baseviews.OneLineView):
347      __select__ = is_instance('Version')
348 
349 
@@ -51,20 +80,9 @@
350          tickets_rset = self._cw.execute(self.rql, {'x': self.cw_rset[row][col]})
351          if tickets_rset:
352              self.wview('burndown_chart', tickets_rset, width=800, height=500)
353 
354 
355 -class VersionProgressTableView(tracker.VersionProgressTableView):
356 -    columns = (_('project'), _('milestone'), _('state'), _('planned_start'),
357 -               _('planned_delivery'),
358 -               _('cost'), _('progress'),
359 -               _('depends_on'), _('todo_by'))
360 -
361 -    def header_for_cost(self, ecls):
362 -        """``cost`` column cell renderer"""
363 -        return self._cw._('load')
364 -
365 -
366  def registration_callback(vreg):
367      vreg.register_all(globals().values(), __name__, (VersionProgressTableView,))
368      vreg.register_and_replace(VersionProgressTableView,
369                                tracker.VersionProgressTableView)