← Back to team overview

launchpad-dev team mailing list archive

Re: odd test failure for an IHasBugs attribute of an IPerson object

 

Hi Abel,

On Tue, 2010-03-09 at 11:47 +0100, Abel Deuring wrote:
> Hi all,
> 
> I get a test failure for the branch
> lp:~adeuring/launchpad/bug-528788-no-searchbox-without-hot-bugs in
> lib/lp/registry/tests/../doc/person.txt that I do not understand:
> 
[...]
> If I add the line
> 
>     >>> foobar.has_bugtasks
> 
> to the doc test, I get a slightly more specific error:
> 
> File "lib/lp/registry/tests/../doc/person.txt", line 25, in person.txt
> Failed example:
>     foobar.has_bugtasks
> Exception raised:
>     Traceback (most recent call last):
>       File
> "/home/abel/canonical/lp-branches/trunk/eggs/zope.testing-3.8.1-py2.5.egg/zope/testing/doctest.py",
> line 1361, in __run
>         compileflags, 1) in test.globs
>       File "<doctest person.txt[line 25, example 8]>", line 1, in <module>
>         foobar.has_bugtasks
>       File
> "/home/abel/canonical/lp-branches/bug-528788-no-searchbox-without-hot-bugs/lib/lp/bugs/model/bugtarget.py",
> line 254, in has_bugtasks
>         all_tasks = all_tasks.limit(1)
>     ForbiddenAttribute: ('limit', <storm.sqlobject.SQLObjectResultSet
> object at 0xef90690>)

I think this is because ISQLObjectResultSet doesn't have the limit()
method (storm/zope/interfaces.py). Since SQLObjectResultSet does define
that method, it should be in ISORS.  Care to file a bug against storm?

> 
> HasBugsBase.has_bugtasks is quite simple:
> 
>     def has_bugtasks(self):
>         """See `IHasBugs`."""
>         # Basically, the return value is self.all_bugtasks.count() > 0.
>         # But finding, sorting and counting all bug tasks can take
>         # a longer time (long enough that the HTML data for "number of
>         # open, critical etc bugs" on a bug page is retrieved in a
>         # separate request). all_bugtasks returns a
>         # storm.SQLObjectResultSet instance, and this class does not
>         # provide methods like is_empty(), so limit the query
>         # manually and simply check if at least one bug task exists.
>         all_tasks = self.all_bugtasks
>         all_tasks = all_tasks.limit(1)
>         return all_tasks.count() > 0
> 
> So, we can't call foobar.all_bugtasks.limit(1) -- while calls like
> product.all_bugtasks.limit(1) do not cause any problem.
> 
> Can somebody enlighten me how to fix this properly? An obvious
> workaround would be to use removeSecurityProxy(self.all_bugtasks) -- but
> I'd like to understand what is so special about class Person that things
> like

There's nothing special about Person -- the problem is that .limit() is
not allowed on an SQLObjectResultSet instance.

In the meantime, since has_bugtasks() seems to expect that all_bugtasks
return an SQLObjectResultSet, you can do bool(all_tasks), which ends up
calling is_empty() on the ResultSet object that is wrapped by
SQLObjectResultSet. That should be as efficient as what you currently
have.

> 
>     >>> for task on foobar.all_bugtasks:
>     ...     print task
> 
> work, while foobar.all_bugtasks.limit(1) fails...


-- 
Guilherme Salgado <salgado@xxxxxxxxxxxxx>

Attachment: signature.asc
Description: This is a digitally signed message part


References