Drop iprogress code (closes #2777628)

authorR?mi Cardona <remi.cardona@logilab.fr>
changeset86c1a5afbe4e
branchdefault
phasepublic
hiddenno
parent revision#8ca1a0da5a29 [web/views] extract cube sioc (closes #1916018)
child revision#1a4ac6667f13 [whatsnew] notify drop of deprecated code, #bf3f129bbbdb [web/views] extract cube embed (closes #1916015), #d92919c995cc [skeleton] Update debian packaging to support only python 2.6 and up
files modified by this revision
doc/3.17.rst
doc/tools/pyjsrest.py
entities/adapters.py
test/unittest_vregistry.py
web/data/cubicweb.iprogress.css
web/data/cubicweb.iprogress.js
web/views/iprogress.py
# HG changeset patch
# User RĂ©mi Cardona <remi.cardona@logilab.fr>
# Date 1364399893 -3600
# Wed Mar 27 16:58:13 2013 +0100
# Node ID 86c1a5afbe4e273de8ee5a659c6aa4e1081b5d2c
# Parent 8ca1a0da5a29cc3050f7c024b681b0a2e49989a3
Drop iprogress code (closes #2777628)

diff --git a/doc/3.17.rst b/doc/3.17.rst
@@ -4,5 +4,13 @@
1  API changes
2  -----------
3 
4  * The SIOC views and adapters have been removed from CubicWeb and moved to the
5    `sioc` cube.
6 +
7 +
8 +Deprecated Code Drops
9 +----------------------
10 +
11 +* The progress views and adapters have been removed from CubicWeb. These
12 +  classes were deprecated since 3.14.0. They are still available in the
13 +  `iprogress` cube.
diff --git a/doc/tools/pyjsrest.py b/doc/tools/pyjsrest.py
@@ -134,11 +134,10 @@
14      'cubicweb.flot',
15      'cubicweb.calendar',
16      'cubicweb.preferences',
17      'cubicweb.edition',
18      'cubicweb.reledit',
19 -    'cubicweb.iprogress',
20      'cubicweb.rhythm',
21      'cubicweb.gmap',
22      'cubicweb.timeline-ext',
23  ]
24 
diff --git a/entities/adapters.py b/entities/adapters.py
@@ -402,119 +402,5 @@
25      def __call__(cls, *args, **kwargs):
26          msg = getattr(cls, "__deprecation_warning__",
27                        "%(cls)s is deprecated") % {'cls': cls.__name__}
28          warn(msg, DeprecationWarning, stacklevel=2)
29          return type.__call__(cls, *args, **kwargs)
30 -
31 -
32 -class IProgressAdapter(view.EntityAdapter):
33 -    """something that has a cost, a state and a progression.
34 -
35 -    You should at least override progress_info an in_progress methods on
36 -    concrete implementations.
37 -    """
38 -    __metaclass__ = adapter_deprecated
39 -    __deprecation_warning__ = '[3.14] IProgressAdapter has been moved to iprogress cube'
40 -    __needs_bw_compat__ = True
41 -    __regid__ = 'IProgress'
42 -    __select__ = implements(IProgress, warn=False) # XXX for bw compat, should be abstract
43 -
44 -    @property
45 -    @view.implements_adapter_compat('IProgress')
46 -    def cost(self):
47 -        """the total cost"""
48 -        return self.progress_info()['estimated']
49 -
50 -    @property
51 -    @view.implements_adapter_compat('IProgress')
52 -    def revised_cost(self):
53 -        return self.progress_info().get('estimatedcorrected', self.cost)
54 -
55 -    @property
56 -    @view.implements_adapter_compat('IProgress')
57 -    def done(self):
58 -        """what is already done"""
59 -        return self.progress_info()['done']
60 -
61 -    @property
62 -    @view.implements_adapter_compat('IProgress')
63 -    def todo(self):
64 -        """what remains to be done"""
65 -        return self.progress_info()['todo']
66 -
67 -    @view.implements_adapter_compat('IProgress')
68 -    def progress_info(self):
69 -        """returns a dictionary describing progress/estimated cost of the
70 -        version.
71 -
72 -        - mandatory keys are (''estimated', 'done', 'todo')
73 -
74 -        - optional keys are ('notestimated', 'notestimatedcorrected',
75 -          'estimatedcorrected')
76 -
77 -        'noestimated' and 'notestimatedcorrected' should default to 0
78 -        'estimatedcorrected' should default to 'estimated'
79 -        """
80 -        raise NotImplementedError
81 -
82 -    @view.implements_adapter_compat('IProgress')
83 -    def finished(self):
84 -        """returns True if status is finished"""
85 -        return not self.in_progress()
86 -
87 -    @view.implements_adapter_compat('IProgress')
88 -    def in_progress(self):
89 -        """returns True if status is not finished"""
90 -        raise NotImplementedError
91 -
92 -    @view.implements_adapter_compat('IProgress')
93 -    def progress(self):
94 -        """returns the % progress of the task item"""
95 -        try:
96 -            return 100. * self.done / self.revised_cost
97 -        except ZeroDivisionError:
98 -            # total cost is 0 : if everything was estimated, task is completed
99 -            if self.progress_info().get('notestimated'):
100 -                return 0.
101 -            return 100
102 -
103 -    @view.implements_adapter_compat('IProgress')
104 -    def progress_class(self):
105 -        return ''
106 -
107 -
108 -class IMileStoneAdapter(IProgressAdapter):
109 -    __metaclass__ = adapter_deprecated
110 -    __deprecation_warning__ = '[3.14] IMileStoneAdapter has been moved to iprogress cube'
111 -    __needs_bw_compat__ = True
112 -    __regid__ = 'IMileStone'
113 -    __select__ = implements(IMileStone, warn=False) # XXX for bw compat, should be abstract
114 -
115 -    parent_type = None # specify main task's type
116 -
117 -    @view.implements_adapter_compat('IMileStone')
118 -    def get_main_task(self):
119 -        """returns the main ITask entity"""
120 -        raise NotImplementedError
121 -
122 -    @view.implements_adapter_compat('IMileStone')
123 -    def initial_prevision_date(self):
124 -        """returns the initial expected end of the milestone"""
125 -        raise NotImplementedError
126 -
127 -    @view.implements_adapter_compat('IMileStone')
128 -    def eta_date(self):
129 -        """returns expected date of completion based on what remains
130 -        to be done
131 -        """
132 -        raise NotImplementedError
133 -
134 -    @view.implements_adapter_compat('IMileStone')
135 -    def completion_date(self):
136 -        """returns date on which the subtask has been completed"""
137 -        raise NotImplementedError
138 -
139 -    @view.implements_adapter_compat('IMileStone')
140 -    def contractors(self):
141 -        """returns the list of persons supposed to work on this task"""
142 -        raise NotImplementedError
143 -
diff --git a/test/unittest_vregistry.py b/test/unittest_vregistry.py
@@ -52,27 +52,27 @@
144          self.vreg.initialization_completed()
145          self.assertEqual(len(self.vreg['views']['primary']), 1)
146 
147 
148      def test_load_subinterface_based_appobjects(self):
149 -        self.vreg.register_objects([join(BASE, 'web', 'views', 'iprogress.py')])
150 -        # check progressbar was kicked
151 -        self.assertFalse(self.vreg['views'].get('progressbar'))
152 +        self.vreg.register_objects([join(BASE, 'web', 'views', 'idownloadable.py')])
153 +        # check downloadlink was kicked
154 +        self.assertFalse(self.vreg['views'].get('downloadlink'))
155          # we've to emulate register_objects to add custom MyCard objects
156          path = [join(BASE, 'entities', '__init__.py'),
157                  join(BASE, 'entities', 'adapters.py'),
158 -                join(BASE, 'web', 'views', 'iprogress.py')]
159 +                join(BASE, 'web', 'views', 'idownloadable.py')]
160          filemods = self.vreg.init_registration(path, None)
161          for filepath, modname in filemods:
162              self.vreg.load_file(filepath, modname)
163 -        class CardIProgressAdapter(EntityAdapter):
164 -            __regid__ = 'IProgress'
165 +        class CardIDownloadableAdapter(EntityAdapter):
166 +            __regid__ = 'IDownloadable'
167          self.vreg._loadedmods[__name__] = {}
168 -        self.vreg.register(CardIProgressAdapter)
169 +        self.vreg.register(CardIDownloadableAdapter)
170          self.vreg.initialization_completed()
171          # check progressbar isn't kicked
172 -        self.assertEqual(len(self.vreg['views']['progressbar']), 1)
173 +        self.assertEqual(len(self.vreg['views']['downloadlink']), 1)
174 
175      def test_properties(self):
176          self.vreg.reset()
177          self.assertFalse('system.version.cubicweb' in self.vreg['propertydefs'])
178          self.assertTrue(self.vreg.property_info('system.version.cubicweb'))
diff --git a/web/data/cubicweb.iprogress.css b/web/data/cubicweb.iprogress.css
@@ -1,78 +0,0 @@
179 -/*
180 - *  :organization: Logilab
181 - *  :copyright: 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
182 - *  :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
183 - */
184 -
185 -/******************************************************************************/
186 -/* progressbar                                                                */
187 -/******************************************************************************/
188 -
189 -.done { background:red }
190 -
191 -.inprogress { background:green }
192 -
193 -.overpassed { background: yellow}
194 -
195 -
196 -canvas.progressbar {
197 -  border:1px solid black;
198 -}
199 -
200 -.progressbarback {
201 -  border: 1px solid #000000;
202 -  background: transparent;
203 -  height: 10px;
204 -  width: 100px;
205 -}
206 -
207 -/******************************************************************************/
208 -/* progress table                                                             */
209 -/******************************************************************************/
210 -
211 -table.progress {
212 - /* The default table view */
213 -  margin: 10px 0px 1em;
214 -  width: 100%;
215 -  font-size: 0.9167em;
216 -}
217 -
218 -table.progress th {
219 -  white-space: nowrap;
220 -  font-weight: bold;
221 -  background: %(listingHeaderBgColor)s;
222 -  padding: 2px 4px;
223 -  font-size:8pt;
224 -}
225 -
226 -table.progress th,
227 -table.progress td {
228 -  border: 1px solid %(listingBorderColor)s;
229 -}
230 -
231 -table.progress td {
232 -  text-align: right;
233 -  padding: 2px 3px;
234 -}
235 -
236 -table.progress th.tdleft,
237 -table.progress td.tdleft {
238 -  text-align: left;
239 -  padding: 2px 3px 2px 5px;
240 -}
241 -
242 -table.progress tr.highlighted {
243 -  background-color: %(listingHighlightedBgColor)s;
244 -}
245 -
246 -table.progress tr.highlighted .progressbarback {
247 -  border: 1px solid %(listingHighlightedBgColor)s;
248 -}
249 -
250 -table.progress .progressbarback {
251 -  border: 1px solid #777;
252 -}
253 -
254 -.progress_data {
255 -  padding-right: 3px;
256 -}
257 \ No newline at end of file
diff --git a/web/data/cubicweb.iprogress.js b/web/data/cubicweb.iprogress.js
@@ -1,63 +0,0 @@
258 -function ProgressBar() {
259 -    this.budget = 100;
260 -    this.todo = 100;
261 -    this.done = 100;
262 -    this.color_done = "green";
263 -    this.color_budget = "blue";
264 -    this.color_todo = "#cccccc"; //  grey
265 -    this.height = 16;
266 -    this.middle = this.height / 2;
267 -    this.radius = 4;
268 -}
269 -
270 -ProgressBar.prototype.draw_one_rect = function(ctx, pos, color, fill) {
271 -    ctx.beginPath();
272 -    ctx.lineWidth = 1;
273 -    ctx.strokeStyle = color;
274 -    if (fill) {
275 -        ctx.fillStyle = color;
276 -        ctx.fillRect(0, 0, pos, this.middle * 2);
277 -    } else {
278 -        ctx.lineWidth = 2;
279 -        ctx.strokeStyle = "black";
280 -        ctx.moveTo(pos, 0);
281 -        ctx.lineTo(pos, this.middle * 2);
282 -        ctx.stroke();
283 -    }
284 -};
285 -
286 -ProgressBar.prototype.draw_one_circ = function(ctx, pos, color) {
287 -    ctx.beginPath();
288 -    ctx.lineWidth = 2;
289 -    ctx.strokeStyle = color;
290 -    ctx.moveTo(0, this.middle);
291 -    ctx.lineTo(pos, this.middle);
292 -    ctx.arc(pos, this.middle, this.radius, 0, Math.PI * 2, true);
293 -    ctx.stroke();
294 -};
295 -
296 -ProgressBar.prototype.draw_circ = function(ctx) {
297 -    this.draw_one_circ(ctx, this.budget, this.color_budget);
298 -    this.draw_one_circ(ctx, this.todo, this.color_todo);
299 -    this.draw_one_circ(ctx, this.done, this.color_done);
300 -};
301 -
302 -ProgressBar.prototype.draw_rect = function(ctx) {
303 -    this.draw_one_rect(ctx, this.todo, this.color_todo, true);
304 -    this.draw_one_rect(ctx, this.done, this.color_done, true);
305 -    this.draw_one_rect(ctx, this.budget, this.color_budget, false);
306 -};
307 -
308 -function draw_progressbar(cid, done, todo, budget, color) {
309 -    var canvas = document.getElementById(cid);
310 -    if (canvas.getContext) {
311 -        var ctx = canvas.getContext("2d");
312 -        var bar = new ProgressBar();
313 -        bar.budget = budget;
314 -        bar.todo = todo;
315 -        bar.done = done;
316 -        bar.color_done = color;
317 -        bar.draw_rect(ctx);
318 -    }
319 -}
320 -
diff --git a/web/views/iprogress.py b/web/views/iprogress.py
@@ -1,260 +0,0 @@
321 -# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
322 -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
323 -#
324 -# This file is part of CubicWeb.
325 -#
326 -# CubicWeb is free software: you can redistribute it and/or modify it under the
327 -# terms of the GNU Lesser General Public License as published by the Free
328 -# Software Foundation, either version 2.1 of the License, or (at your option)
329 -# any later version.
330 -#
331 -# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
332 -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
333 -# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
334 -# details.
335 -#
336 -# You should have received a copy of the GNU Lesser General Public License along
337 -# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
338 -"""Specific views for entities implementing IProgress/IMileStone"""
339 -
340 -__docformat__ = "restructuredtext en"
341 -_ = unicode
342 -
343 -from math import floor
344 -
345 -from logilab.common.deprecation import class_deprecated
346 -from logilab.mtconverter import xml_escape
347 -
348 -from cubicweb.utils import make_uid
349 -from cubicweb.predicates import adaptable
350 -from cubicweb.schema import display_name
351 -from cubicweb.view import EntityView
352 -from cubicweb.web.views.tableview import EntityAttributesTableView
353 -
354 -
355 -class ProgressTableView(EntityAttributesTableView):
356 -    """The progress table view is able to display progress information
357 -    of any object implement IMileStone.
358 -
359 -    The default layout is composoed of 7 columns : parent task,
360 -    milestone, state, estimated date, cost, progressbar, and todo_by
361 -
362 -    The view accepts an optional ``columns`` paramater that lets you
363 -    remove or reorder some of those columns.
364 -
365 -    To add new columns, you should extend this class, define a new
366 -    ``columns`` class attribute and implement corresponding
367 -    build_COLNAME_cell methods
368 -
369 -    header_for_COLNAME methods allow to customize header's label
370 -    """
371 -    __metaclass__ = class_deprecated
372 -    __deprecation_warning__ = '[3.14] %(cls)s is deprecated'
373 -
374 -    __regid__ = 'progress_table_view'
375 -    __select__ = adaptable('IMileStone')
376 -    title = _('task progression')
377 -    table_css = "progress"
378 -    css_files = ('cubicweb.iprogress.css',)
379 -
380 -    # default columns of the table
381 -    columns = (_('project'), _('milestone'), _('state'), _('eta_date'),
382 -               _('cost'), _('progress'), _('todo_by'))
383 -
384 -    def cell_call(self, row, col):
385 -        _ = self._cw._
386 -        entity = self.cw_rset.get_entity(row, col)
387 -        infos = {}
388 -        for col in self.columns:
389 -            meth = getattr(self, 'build_%s_cell' % col, None)
390 -            # find the build method or try to find matching attribute
391 -            if meth:
392 -                content = meth(entity)
393 -            else:
394 -                content = entity.printable_value(col)
395 -            infos[col] = content
396 -        cssclass = entity.cw_adapt_to('IMileStone').progress_class()
397 -        self.w(u"""<tr class="%s" onmouseover="$(this).addClass('highlighted');"
398 -            onmouseout="$(this).removeClass('highlighted')">""" % cssclass)
399 -        line = u''.join(u'<td>%%(%s)s</td>' % col for col in self.columns)
400 -        self.w(line % infos)
401 -        self.w(u'</tr>\n')
402 -
403 -    ## header management ######################################################
404 -
405 -    def header_for_project(self, sample):
406 -        """use entity's parent type as label"""
407 -        return display_name(self._cw, sample.cw_adapt_to('IMileStone').parent_type)
408 -
409 -    def header_for_milestone(self, sample):
410 -        """use entity's type as label"""
411 -        return display_name(self._cw, sample.__regid__)
412 -
413 -    ## cell management ########################################################
414 -    def build_project_cell(self, entity):
415 -        """``project`` column cell renderer"""
416 -        project = entity.cw_adapt_to('IMileStone').get_main_task()
417 -        if project:
418 -            return project.view('incontext')
419 -        return self._cw._('no related project')
420 -
421 -    def build_milestone_cell(self, entity):
422 -        """``milestone`` column cell renderer"""
423 -        return entity.view('incontext')
424 -
425 -    def build_state_cell(self, entity):
426 -        """``state`` column cell renderer"""
427 -        return xml_escape(entity.cw_adapt_to('IWorkflowable').printable_state)
428 -
429 -    def build_eta_date_cell(self, entity):
430 -        """``eta_date`` column cell renderer"""
431 -        imilestone = entity.cw_adapt_to('IMileStone')
432 -        if imilestone.finished():
433 -            return self._cw.format_date(imilestone.completion_date())
434 -        formated_date = self._cw.format_date(imilestone.initial_prevision_date())
435 -        if imilestone.in_progress():
436 -            eta_date = self._cw.format_date(imilestone.eta_date())
437 -            _ = self._cw._
438 -            if formated_date:
439 -                formated_date += u' (%s %s)' % (_('expected:'), eta_date)
440 -            else:
441 -                formated_date = u'%s %s' % (_('expected:'), eta_date)
442 -        return formated_date
443 -
444 -    def build_todo_by_cell(self, entity):
445 -        """``todo_by`` column cell renderer"""
446 -        imilestone = entity.cw_adapt_to('IMileStone')
447 -        return u', '.join(p.view('outofcontext') for p in imilestone.contractors())
448 -
449 -    def build_cost_cell(self, entity):
450 -        """``cost`` column cell renderer"""
451 -        _ = self._cw._
452 -        imilestone = entity.cw_adapt_to('IMileStone')
453 -        pinfo = imilestone.progress_info()
454 -        totalcost = pinfo.get('estimatedcorrected', pinfo['estimated'])
455 -        missing = pinfo.get('notestimatedcorrected', pinfo.get('notestimated', 0))
456 -        costdescr = []
457 -        if missing:
458 -            # XXX: link to unestimated entities
459 -            costdescr.append(_('%s not estimated') % missing)
460 -        estimated = pinfo['estimated']
461 -        if estimated and estimated != totalcost:
462 -            costdescr.append(_('initial estimation %s') % estimated)
463 -        if costdescr:
464 -            return u'%s (%s)' % (totalcost, ', '.join(costdescr))
465 -        return unicode(totalcost)
466 -
467 -    def build_progress_cell(self, entity):
468 -        """``progress`` column cell renderer"""
469 -        return entity.view('progressbar')
470 -
471 -
472 -class InContextProgressTableView(ProgressTableView):
473 -    """this views redirects to ``progress_table_view`` but removes
474 -    the ``project`` column
475 -    """
476 -    __metaclass__ = class_deprecated
477 -    __deprecation_warning__ = '[3.14] %(cls)s is deprecated'
478 -    __regid__ = 'ic_progress_table_view'
479 -
480 -    def call(self, columns=None):
481 -        view = self._cw.vreg['views'].select('progress_table_view', self._cw,
482 -                                         rset=self.cw_rset)
483 -        columns = list(columns or view.columns)
484 -        try:
485 -            columns.remove('project')
486 -        except ValueError:
487 -            self.info('[ic_progress_table_view] could not remove project from columns')
488 -        view.render(w=self.w, columns=columns)
489 -
490 -
491 -class ProgressBarView(EntityView):
492 -    """displays a progress bar"""
493 -    __metaclass__ = class_deprecated
494 -    __deprecation_warning__ = '[3.14] %(cls)s is deprecated'
495 -    __regid__ = 'progressbar'
496 -    __select__ = adaptable('IProgress')
497 -
498 -    title = _('progress bar')
499 -
500 -    precision = 0.1
501 -    red_threshold = 1.1
502 -    orange_threshold = 1.05
503 -    yellow_threshold = 1
504 -
505 -    @classmethod
506 -    def overrun(cls, iprogress):
507 -        done = iprogress.done or 0
508 -        todo = iprogress.todo or 0
509 -        budget = iprogress.revised_cost or 0
510 -        if done + todo > budget:
511 -            overrun = done + todo - budget
512 -        else:
513 -            overrun = 0
514 -        if overrun < cls.precision:
515 -            overrun = 0
516 -        return overrun
517 -
518 -    @classmethod
519 -    def overrun_percentage(cls, iprogress):
520 -        budget = iprogress.revised_cost or 0
521 -        if budget == 0:
522 -            return 0
523 -        return cls.overrun(iprogress) * 100. / budget
524 -
525 -    def cell_call(self, row, col):
526 -        self._cw.add_css('cubicweb.iprogress.css')
527 -        self._cw.add_js('cubicweb.iprogress.js')
528 -        entity = self.cw_rset.get_entity(row, col)
529 -        iprogress = entity.cw_adapt_to('IProgress')
530 -        done = iprogress.done or 0
531 -        todo = iprogress.todo or 0
532 -        budget = iprogress.revised_cost or 0
533 -        if budget == 0:
534 -            pourcent = 100
535 -        else:
536 -            pourcent = done*100./budget
537 -        if pourcent > 100.1:
538 -            color = 'red'
539 -        elif todo+done > self.red_threshold*budget:
540 -            color = 'red'
541 -        elif todo+done > self.orange_threshold*budget:
542 -            color = 'orange'
543 -        elif todo+done > self.yellow_threshold*budget:
544 -            color = 'yellow'
545 -        else:
546 -            color = 'green'
547 -        if pourcent < 0:
548 -            pourcent = 0
549 -
550 -        if floor(done) == done or done>100:
551 -            done_str = '%i' % done
552 -        else:
553 -            done_str = '%.1f' % done
554 -        if floor(budget) == budget or budget>100:
555 -            budget_str = '%i' % budget
556 -        else:
557 -            budget_str = '%.1f' % budget
558 -
559 -        title = u'%s/%s = %i%%' % (done_str, budget_str, pourcent)
560 -        short_title = title
561 -        overrunpercent = self.overrun_percentage(iprogress)
562 -        if overrunpercent:
563 -            overrun = self.overrun(iprogress)
564 -            title += u' overrun +%sj (+%i%%)' % (overrun, overrunpercent)
565 -            if floor(overrun) == overrun or overrun > 100:
566 -                short_title += u' +%i' % overrun
567 -            else:
568 -                short_title += u' +%.1f' % overrun
569 -        # write bars
570 -        maxi = max(done+todo, budget)
571 -        if maxi == 0:
572 -            maxi = 1
573 -        cid = make_uid('progress_bar')
574 -        self._cw.html_headers.add_onload(
575 -            'draw_progressbar("canvas%s", %i, %i, %i, "%s");' %
576 -            (cid, int(100.*done/maxi), int(100.*(done+todo)/maxi),
577 -             int(100.*budget/maxi), color))
578 -        self.w(u'%s<br/>'
579 -               u'<canvas class="progressbar" id="canvas%s" width="100" height="10"></canvas>'
580 -               % (xml_escape(short_title), cid))