[vreg] vregistry._select_best was needlessly instanciating NoSelectableObject (closes #1626708)
in large selections, this incurred a non negligible cost (add_relations with
2000 inlined relations runs 7% faster with this patch)
--- a/cwvreg.py Thu Apr 28 15:30:16 2011 +0200
+++ b/cwvreg.py Wed Apr 27 16:38:01 2011 +0200
@@ -402,10 +402,8 @@
if not isinstance(view, class_deprecated)]
try:
view = self._select_best(views, req, rset=rset, **kwargs)
- if view.linkable():
+ if view is not None and view.linkable():
yield view
- except NoSelectableObject:
- continue
except Exception:
self.exception('error while trying to select %s view for %s',
vid, rset)
--- a/devtools/testlib.py Thu Apr 28 15:30:16 2011 +0200
+++ b/devtools/testlib.py Wed Apr 27 16:38:01 2011 +0200
@@ -562,6 +562,8 @@
if views:
try:
view = viewsvreg._select_best(views, req, rset=rset)
+ if view is None:
+ raise NoSelectableObject((req,), {'rset':rset}, views)
if view.linkable():
yield view
else:
--- a/vregistry.py Thu Apr 28 15:30:16 2011 +0200
+++ b/vregistry.py Wed Apr 27 16:38:01 2011 +0200
@@ -184,7 +184,10 @@
raise :exc:`NoSelectableObject` if not object apply
"""
- return self._select_best(self[__oid], *args, **kwargs)
+ obj = self._select_best(self[__oid], *args, **kwargs)
+ if obj is None:
+ raise NoSelectableObject(args, kwargs, self[__oid] )
+ return obj
def select_or_none(self, __oid, *args, **kwargs):
"""return the most specific object among those with the given oid
@@ -202,16 +205,18 @@
context
"""
for appobjects in self.itervalues():
- try:
- yield self._select_best(appobjects, *args, **kwargs)
- except NoSelectableObject:
+ obj = self._select_best(appobjects, *args, **kwargs)
+ if obj is None:
continue
+ yield obj
def _select_best(self, appobjects, *args, **kwargs):
"""return an instance of the most specific object according
to parameters
- raise `NoSelectableObject` if not object apply
+ return None if not object apply (don't raise `NoSelectableObject` since
+ it's costly when searching appobjects using `possible_objects`
+ (e.g. searching for hooks).
"""
if len(args) > 1:
warn('[3.5] only the request param can not be named when calling select*',
@@ -224,7 +229,7 @@
elif appobjectscore > 0 and appobjectscore == score:
winners.append(appobject)
if winners is None:
- raise NoSelectableObject(args, kwargs, appobjects)
+ return None
if len(winners) > 1:
# log in production environement / test, error while debugging
msg = 'select ambiguity: %s\n(args: %s, kwargs: %s)'
--- a/web/views/urlpublishing.py Thu Apr 28 15:30:16 2011 +0200
+++ b/web/views/urlpublishing.py Wed Apr 27 16:38:01 2011 +0200
@@ -260,9 +260,8 @@
else:
try:
action = actionsreg._select_best(actions, req, rset=rset)
+ if action is not None:
+ raise Redirect(action.url())
except RegistryException:
- continue
- else:
- # XXX avoid redirect
- raise Redirect(action.url())
+ pass # continue searching
raise PathDontMatch()