402 def __call__(cls, *args, **kwargs): |
402 def __call__(cls, *args, **kwargs): |
403 msg = getattr(cls, "__deprecation_warning__", |
403 msg = getattr(cls, "__deprecation_warning__", |
404 "%(cls)s is deprecated") % {'cls': cls.__name__} |
404 "%(cls)s is deprecated") % {'cls': cls.__name__} |
405 warn(msg, DeprecationWarning, stacklevel=2) |
405 warn(msg, DeprecationWarning, stacklevel=2) |
406 return type.__call__(cls, *args, **kwargs) |
406 return type.__call__(cls, *args, **kwargs) |
407 |
|
408 |
|
409 class IProgressAdapter(view.EntityAdapter): |
|
410 """something that has a cost, a state and a progression. |
|
411 |
|
412 You should at least override progress_info an in_progress methods on |
|
413 concrete implementations. |
|
414 """ |
|
415 __metaclass__ = adapter_deprecated |
|
416 __deprecation_warning__ = '[3.14] IProgressAdapter has been moved to iprogress cube' |
|
417 __needs_bw_compat__ = True |
|
418 __regid__ = 'IProgress' |
|
419 __select__ = implements(IProgress, warn=False) # XXX for bw compat, should be abstract |
|
420 |
|
421 @property |
|
422 @view.implements_adapter_compat('IProgress') |
|
423 def cost(self): |
|
424 """the total cost""" |
|
425 return self.progress_info()['estimated'] |
|
426 |
|
427 @property |
|
428 @view.implements_adapter_compat('IProgress') |
|
429 def revised_cost(self): |
|
430 return self.progress_info().get('estimatedcorrected', self.cost) |
|
431 |
|
432 @property |
|
433 @view.implements_adapter_compat('IProgress') |
|
434 def done(self): |
|
435 """what is already done""" |
|
436 return self.progress_info()['done'] |
|
437 |
|
438 @property |
|
439 @view.implements_adapter_compat('IProgress') |
|
440 def todo(self): |
|
441 """what remains to be done""" |
|
442 return self.progress_info()['todo'] |
|
443 |
|
444 @view.implements_adapter_compat('IProgress') |
|
445 def progress_info(self): |
|
446 """returns a dictionary describing progress/estimated cost of the |
|
447 version. |
|
448 |
|
449 - mandatory keys are (''estimated', 'done', 'todo') |
|
450 |
|
451 - optional keys are ('notestimated', 'notestimatedcorrected', |
|
452 'estimatedcorrected') |
|
453 |
|
454 'noestimated' and 'notestimatedcorrected' should default to 0 |
|
455 'estimatedcorrected' should default to 'estimated' |
|
456 """ |
|
457 raise NotImplementedError |
|
458 |
|
459 @view.implements_adapter_compat('IProgress') |
|
460 def finished(self): |
|
461 """returns True if status is finished""" |
|
462 return not self.in_progress() |
|
463 |
|
464 @view.implements_adapter_compat('IProgress') |
|
465 def in_progress(self): |
|
466 """returns True if status is not finished""" |
|
467 raise NotImplementedError |
|
468 |
|
469 @view.implements_adapter_compat('IProgress') |
|
470 def progress(self): |
|
471 """returns the % progress of the task item""" |
|
472 try: |
|
473 return 100. * self.done / self.revised_cost |
|
474 except ZeroDivisionError: |
|
475 # total cost is 0 : if everything was estimated, task is completed |
|
476 if self.progress_info().get('notestimated'): |
|
477 return 0. |
|
478 return 100 |
|
479 |
|
480 @view.implements_adapter_compat('IProgress') |
|
481 def progress_class(self): |
|
482 return '' |
|
483 |
|
484 |
|
485 class IMileStoneAdapter(IProgressAdapter): |
|
486 __metaclass__ = adapter_deprecated |
|
487 __deprecation_warning__ = '[3.14] IMileStoneAdapter has been moved to iprogress cube' |
|
488 __needs_bw_compat__ = True |
|
489 __regid__ = 'IMileStone' |
|
490 __select__ = implements(IMileStone, warn=False) # XXX for bw compat, should be abstract |
|
491 |
|
492 parent_type = None # specify main task's type |
|
493 |
|
494 @view.implements_adapter_compat('IMileStone') |
|
495 def get_main_task(self): |
|
496 """returns the main ITask entity""" |
|
497 raise NotImplementedError |
|
498 |
|
499 @view.implements_adapter_compat('IMileStone') |
|
500 def initial_prevision_date(self): |
|
501 """returns the initial expected end of the milestone""" |
|
502 raise NotImplementedError |
|
503 |
|
504 @view.implements_adapter_compat('IMileStone') |
|
505 def eta_date(self): |
|
506 """returns expected date of completion based on what remains |
|
507 to be done |
|
508 """ |
|
509 raise NotImplementedError |
|
510 |
|
511 @view.implements_adapter_compat('IMileStone') |
|
512 def completion_date(self): |
|
513 """returns date on which the subtask has been completed""" |
|
514 raise NotImplementedError |
|
515 |
|
516 @view.implements_adapter_compat('IMileStone') |
|
517 def contractors(self): |
|
518 """returns the list of persons supposed to work on this task""" |
|
519 raise NotImplementedError |
|
520 |
|