--- a/entities/adapters.py Fri Oct 28 11:33:25 2011 +0200
+++ b/entities/adapters.py Fri Oct 28 11:33:26 2011 +0200
@@ -26,15 +26,15 @@
from logilab.mtconverter import TransformError
from logilab.common.decorators import cached
+from logilab.common.deprecation import class_deprecated
-from cubicweb import ValidationError
-from cubicweb.view import EntityAdapter, implements_adapter_compat
+from cubicweb import ValidationError, view
from cubicweb.selectors import (implements, is_instance, relation_possible,
match_exception)
from cubicweb.interfaces import IDownloadable, ITree, IProgress, IMileStone
-class IEmailableAdapter(EntityAdapter):
+class IEmailableAdapter(view.EntityAdapter):
__regid__ = 'IEmailable'
__select__ = relation_possible('primary_email') | relation_possible('use_email')
@@ -67,12 +67,12 @@
for attr in self.allowed_massmail_keys() )
-class INotifiableAdapter(EntityAdapter):
+class INotifiableAdapter(view.EntityAdapter):
__needs_bw_compat__ = True
__regid__ = 'INotifiable'
__select__ = is_instance('Any')
- @implements_adapter_compat('INotifiableAdapter')
+ @view.implements_adapter_compat('INotifiableAdapter')
def notification_references(self, view):
"""used to control References field of email send on notification
for this entity. `view` is the notification view.
@@ -86,7 +86,7 @@
return ()
-class IFTIndexableAdapter(EntityAdapter):
+class IFTIndexableAdapter(view.EntityAdapter):
__regid__ = 'IFTIndexable'
__select__ = is_instance('Any')
@@ -156,35 +156,35 @@
for weight, words in newdict.iteritems():
maindict.setdefault(weight, []).extend(words)
-class IDownloadableAdapter(EntityAdapter):
+class IDownloadableAdapter(view.EntityAdapter):
"""interface for downloadable entities"""
__needs_bw_compat__ = True
__regid__ = 'IDownloadable'
__select__ = implements(IDownloadable, warn=False) # XXX for bw compat, else should be abstract
- @implements_adapter_compat('IDownloadable')
+ @view.implements_adapter_compat('IDownloadable')
def download_url(self, **kwargs): # XXX not really part of this interface
"""return an url to download entity's content"""
raise NotImplementedError
- @implements_adapter_compat('IDownloadable')
+ @view.implements_adapter_compat('IDownloadable')
def download_content_type(self):
"""return MIME type of the downloadable content"""
raise NotImplementedError
- @implements_adapter_compat('IDownloadable')
+ @view.implements_adapter_compat('IDownloadable')
def download_encoding(self):
"""return encoding of the downloadable content"""
raise NotImplementedError
- @implements_adapter_compat('IDownloadable')
+ @view.implements_adapter_compat('IDownloadable')
def download_file_name(self):
"""return file name of the downloadable content"""
raise NotImplementedError
- @implements_adapter_compat('IDownloadable')
+ @view.implements_adapter_compat('IDownloadable')
def download_data(self):
"""return actual data of the downloadable content"""
raise NotImplementedError
# XXX should propose to use two different relations for children/parent
-class ITreeAdapter(EntityAdapter):
+class ITreeAdapter(view.EntityAdapter):
"""This adapter has to be overriden to be configured using the
tree_relation, child_role and parent_role class attributes to benefit from
this default implementation.
@@ -225,12 +225,12 @@
return self.entity.tree_attribute
# XXX should be removed from the public interface
- @implements_adapter_compat('ITree')
+ @view.implements_adapter_compat('ITree')
def children_rql(self):
"""Returns RQL to get the children of the entity."""
return self.entity.cw_related_rql(self.tree_relation, self.parent_role)
- @implements_adapter_compat('ITree')
+ @view.implements_adapter_compat('ITree')
def different_type_children(self, entities=True):
"""Return children entities of different type as this entity.
@@ -244,7 +244,7 @@
return [e for e in res if e.e_schema != eschema]
return res.filtered_rset(lambda x: x.e_schema != eschema, self.entity.cw_col)
- @implements_adapter_compat('ITree')
+ @view.implements_adapter_compat('ITree')
def same_type_children(self, entities=True):
"""Return children entities of the same type as this entity.
@@ -258,23 +258,23 @@
return [e for e in res if e.e_schema == eschema]
return res.filtered_rset(lambda x: x.e_schema is eschema, self.entity.cw_col)
- @implements_adapter_compat('ITree')
+ @view.implements_adapter_compat('ITree')
def is_leaf(self):
"""Returns True if the entity does not have any children."""
return len(self.children()) == 0
- @implements_adapter_compat('ITree')
+ @view.implements_adapter_compat('ITree')
def is_root(self):
"""Returns true if the entity is root of the tree (e.g. has no parent).
"""
return self.parent() is None
- @implements_adapter_compat('ITree')
+ @view.implements_adapter_compat('ITree')
def root(self):
"""Return the root entity of the tree."""
return self._cw.entity_from_eid(self.path()[0])
- @implements_adapter_compat('ITree')
+ @view.implements_adapter_compat('ITree')
def parent(self):
"""Returns the parent entity if any, else None (e.g. if we are on the
root).
@@ -285,7 +285,7 @@
except (KeyError, IndexError):
return None
- @implements_adapter_compat('ITree')
+ @view.implements_adapter_compat('ITree')
def children(self, entities=True, sametype=False):
"""Return children entities.
@@ -298,7 +298,7 @@
return self.entity.related(self.tree_relation, self.parent_role,
entities=entities)
- @implements_adapter_compat('ITree')
+ @view.implements_adapter_compat('ITree')
def iterparents(self, strict=True):
"""Return an iterator on the parents of the entity."""
def _uptoroot(self):
@@ -313,7 +313,7 @@
return chain([self.entity], _uptoroot(self))
return _uptoroot(self)
- @implements_adapter_compat('ITree')
+ @view.implements_adapter_compat('ITree')
def iterchildren(self, _done=None):
"""Return an iterator over the item's children."""
if _done is None:
@@ -325,7 +325,7 @@
yield child
_done.add(child.eid)
- @implements_adapter_compat('ITree')
+ @view.implements_adapter_compat('ITree')
def prefixiter(self, _done=None):
"""Return an iterator over the item's descendants in a prefixed order."""
if _done is None:
@@ -338,7 +338,7 @@
for entity in child.cw_adapt_to('ITree').prefixiter(_done):
yield entity
- @implements_adapter_compat('ITree')
+ @view.implements_adapter_compat('ITree')
@cached
def path(self):
"""Returns the list of eids from the root object to this object."""
@@ -363,40 +363,75 @@
return path
-class IProgressAdapter(EntityAdapter):
+# error handling adapters ######################################################
+
+from cubicweb import UniqueTogetherError
+
+class IUserFriendlyError(view.EntityAdapter):
+ __regid__ = 'IUserFriendlyError'
+ __abstract__ = True
+ def __init__(self, *args, **kwargs):
+ self.exc = kwargs.pop('exc')
+ super(IUserFriendlyError, self).__init__(*args, **kwargs)
+
+
+class IUserFriendlyUniqueTogether(IUserFriendlyError):
+ __select__ = match_exception(UniqueTogetherError)
+ def raise_user_exception(self):
+ etype, rtypes = self.exc.args
+ msg = self._cw._('violates unique_together constraints (%s)') % (
+ ', '.join([self._cw._(rtype) for rtype in rtypes]))
+ raise ValidationError(self.entity.eid, dict((col, msg) for col in rtypes))
+
+# deprecated ###################################################################
+
+
+class adapter_deprecated(view.auto_unwrap_bw_compat):
+ """metaclass to print a warning on instantiation of a deprecated class"""
+
+ def __call__(cls, *args, **kwargs):
+ msg = getattr(cls, "__deprecation_warning__",
+ "%(cls)s is deprecated") % {'cls': cls.__name__}
+ warn(msg, DeprecationWarning, stacklevel=2)
+ return type.__call__(cls, *args, **kwargs)
+
+
+class IProgressAdapter(view.EntityAdapter):
"""something that has a cost, a state and a progression.
You should at least override progress_info an in_progress methods on
concrete implementations.
"""
+ __metaclass__ = adapter_deprecated
+ __deprecation_warning__ = '[3.14] IProgressAdapter has been moved to iprogress cube'
__needs_bw_compat__ = True
__regid__ = 'IProgress'
__select__ = implements(IProgress, warn=False) # XXX for bw compat, should be abstract
@property
- @implements_adapter_compat('IProgress')
+ @view.implements_adapter_compat('IProgress')
def cost(self):
"""the total cost"""
return self.progress_info()['estimated']
@property
- @implements_adapter_compat('IProgress')
+ @view.implements_adapter_compat('IProgress')
def revised_cost(self):
return self.progress_info().get('estimatedcorrected', self.cost)
@property
- @implements_adapter_compat('IProgress')
+ @view.implements_adapter_compat('IProgress')
def done(self):
"""what is already done"""
return self.progress_info()['done']
@property
- @implements_adapter_compat('IProgress')
+ @view.implements_adapter_compat('IProgress')
def todo(self):
"""what remains to be done"""
return self.progress_info()['todo']
- @implements_adapter_compat('IProgress')
+ @view.implements_adapter_compat('IProgress')
def progress_info(self):
"""returns a dictionary describing progress/estimated cost of the
version.
@@ -411,17 +446,17 @@
"""
raise NotImplementedError
- @implements_adapter_compat('IProgress')
+ @view.implements_adapter_compat('IProgress')
def finished(self):
"""returns True if status is finished"""
return not self.in_progress()
- @implements_adapter_compat('IProgress')
+ @view.implements_adapter_compat('IProgress')
def in_progress(self):
"""returns True if status is not finished"""
raise NotImplementedError
- @implements_adapter_compat('IProgress')
+ @view.implements_adapter_compat('IProgress')
def progress(self):
"""returns the % progress of the task item"""
try:
@@ -432,62 +467,44 @@
return 0.
return 100
- @implements_adapter_compat('IProgress')
+ @view.implements_adapter_compat('IProgress')
def progress_class(self):
return ''
class IMileStoneAdapter(IProgressAdapter):
+ __metaclass__ = adapter_deprecated
+ __deprecation_warning__ = '[3.14] IMileStoneAdapter has been moved to iprogress cube'
__needs_bw_compat__ = True
__regid__ = 'IMileStone'
__select__ = implements(IMileStone, warn=False) # XXX for bw compat, should be abstract
parent_type = None # specify main task's type
- @implements_adapter_compat('IMileStone')
+ @view.implements_adapter_compat('IMileStone')
def get_main_task(self):
"""returns the main ITask entity"""
raise NotImplementedError
- @implements_adapter_compat('IMileStone')
+ @view.implements_adapter_compat('IMileStone')
def initial_prevision_date(self):
"""returns the initial expected end of the milestone"""
raise NotImplementedError
- @implements_adapter_compat('IMileStone')
+ @view.implements_adapter_compat('IMileStone')
def eta_date(self):
"""returns expected date of completion based on what remains
to be done
"""
raise NotImplementedError
- @implements_adapter_compat('IMileStone')
+ @view.implements_adapter_compat('IMileStone')
def completion_date(self):
"""returns date on which the subtask has been completed"""
raise NotImplementedError
- @implements_adapter_compat('IMileStone')
+ @view.implements_adapter_compat('IMileStone')
def contractors(self):
"""returns the list of persons supposed to work on this task"""
raise NotImplementedError
-
-# error handling adapters ######################################################
-
-from cubicweb import UniqueTogetherError
-
-class IUserFriendlyError(EntityAdapter):
- __regid__ = 'IUserFriendlyError'
- __abstract__ = True
- def __init__(self, *args, **kwargs):
- self.exc = kwargs.pop('exc')
- super(IUserFriendlyError, self).__init__(*args, **kwargs)
-
-
-class IUserFriendlyUniqueTogether(IUserFriendlyError):
- __select__ = match_exception(UniqueTogetherError)
- def raise_user_exception(self):
- etype, rtypes = self.exc.args
- msg = self._cw._('violates unique_together constraints (%s)') % (
- ', '.join([self._cw._(rtype) for rtype in rtypes]))
- raise ValidationError(self.entity.eid, dict((col, msg) for col in rtypes))
--- a/web/views/iprogress.py Fri Oct 28 11:33:25 2011 +0200
+++ b/web/views/iprogress.py Fri Oct 28 11:33:26 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
@@ -22,6 +22,7 @@
from math import floor
+from logilab.common.deprecation import class_deprecated
from logilab.mtconverter import xml_escape
from cubicweb.utils import make_uid
@@ -47,6 +48,8 @@
header_for_COLNAME methods allow to customize header's label
"""
+ __metaclass__ = class_deprecated
+ __deprecation_warning__ = '[3.14] %(cls)s is deprecated'
__regid__ = 'progress_table_view'
__select__ = adaptable('IMileStone')
@@ -59,6 +62,7 @@
_('cost'), _('progress'), _('todo_by'))
def cell_call(self, row, col):
+ x
_ = self._cw._
entity = self.cw_rset.get_entity(row, col)
infos = {}
@@ -150,9 +154,12 @@
"""this views redirects to ``progress_table_view`` but removes
the ``project`` column
"""
+ __metaclass__ = class_deprecated
+ __deprecation_warning__ = '[3.14] %(cls)s is deprecated'
__regid__ = 'ic_progress_table_view'
def call(self, columns=None):
+ x
view = self._cw.vreg['views'].select('progress_table_view', self._cw,
rset=self.cw_rset)
columns = list(columns or view.columns)
@@ -165,6 +172,8 @@
class ProgressBarView(EntityView):
"""displays a progress bar"""
+ __metaclass__ = class_deprecated
+ __deprecation_warning__ = '[3.14] %(cls)s is deprecated'
__regid__ = 'progressbar'
__select__ = adaptable('IProgress')
@@ -196,6 +205,7 @@
return cls.overrun(iprogress) * 100. / budget
def cell_call(self, row, col):
+ x
self._cw.add_css('cubicweb.iprogress.css')
self._cw.add_js('cubicweb.iprogress.js')
entity = self.cw_rset.get_entity(row, col)