It's actually a little deeper problem.  I see that Rows.sort() has the 
effect of stripping the table key from the resulting Row objects.

If I try the obvious fix, to use the built-in "sorted" on self.records 
instead of self, then the next problem surfaces -- the supplied sort key 
must include the table and the field key, and they must both be supplied to 
the sort.  Which would break all manner of existing programs.

I love the concept of "compact" vs non-compact, but the implementation of 
stripping the table keys from the Row objects has left quite a mess!

-- Joe

On Tuesday, January 7, 2014 8:03:56 AM UTC-8, Anthony wrote:
>
> The Rows.find() method does the following:
>
>         for row in self:
>             if f(row):
>                 if a<=k: records.append(row)
>                 k += 1
>                 if k==b: break
>
> In a Rows object, there is self.records, which is a list of Row objects. 
> Each Row object has at least one top-level key with the table name, and the 
> record is stored in the value associated with that key:
>
> <Row {'person': {'first_name': 'Bob', 'last_name': 'Smith'}}>
>
> When .find() is called on a Rows object with compact=True, the __iter__ 
> method (called by the "for row in self" loop) returns a transformed version 
> of each Row object, removing the top-level table key:
>
> <Row {'first_name': 'Bob', 'last_name': 'Smith'}>
>
> I believe this is an unnecessary transformation, and it is what is 
> subsequently causing the .render() method to fail (the .render() method 
> expects the top-level table key to be there, whether or not compact=True). 
> I propose the following change to .find():
>
>         for i, row in enumerate(self):
>             if f(row):
>                 if a<=k: records.append(self.records[i])
>                 k += 1
>                 if k==b: break
>
> The above code appends self.records[i] instead of row, which preserves the 
> original Row objects instead of including transformed objects. Anyone see 
> any problems with that change?
>
> Also, is there any reason all of the Rows methods (i.e., find, exclude, 
> __and__, __or__) should not be preserving the "compact" attribute of the 
> original Rows object? Perhaps we should change them all to do so. (Note, 
> this is a separate issue unrelated to the above problem with .find() and 
> .render().)
>
> Anthony
>
> On Tuesday, January 7, 2014 10:47:28 AM UTC-5, Anthony wrote:
>>
>> .render() works fine on Rows objects with compact=True, and it also works 
>> fine on the results of .sort(), .exclude(), &, and | operations. The only 
>> problem is with the results of .find() operations when the original Rows 
>> object has compact=True. The problem is that the .find() method modifies 
>> the Row objects in self.records when compact=True, which it probably should 
>> not due.
>>
>> Aside from this issue, perhaps the various Rows methods should preserve 
>> the "compact" attribute -- not sure why they don't.
>>
>> Forwarding to the developers list for discussion.
>>
>> Anthony
>>
>> On Tuesday, January 7, 2014 3:10:00 AM UTC-5, Joe Barnhart wrote:
>>>
>>> I've been experimenting with the render method of the Rows class, and I 
>>> am very impressed.  But one drawback I found is that the Rows object must 
>>> have its value set to "compact=False" to work properly with render().  It 
>>> isn't a problem if the Rows object is used directly without any operators, 
>>> but I discovered that many, if not most, Rows methods do not preserve the 
>>> "compact" setting.
>>>
>>> For example. if you "sort" the Rows, it leaves compact=True.  Ditto, if 
>>> you use "extract" or "find" on the Rows object.  The "&" and "|" operators 
>>> also set the compact variable to "True".  The upshot is that you can't use 
>>> any of these operators on the Rows object and then use "render" on the 
>>> resulting object.
>>>
>>> It is a simple change to add the preservation of the "compact" flag 
>>> during any of these steps, but I'm unsure if this will break existing code. 
>>>  Other than coming up with a completely parallel set of methods, which 
>>> leave compact set the way it came in, I can't think of another approach 
>>> will be provably backwards-compatible.
>>>
>>> Here is an example:
>>>
>>>
>>>     def __and__(self,other):
>>>         if self.colnames!=other.colnames:
>>>             raise Exception('Cannot & incompatible Rows objects')
>>>         records = self.records+other.records
>>>         return Rows(self.db,records,self.colnames)
>>>
>>>
>>> Becomes:
>>>
>>>
>>>     def __and__(self,other):
>>>         if self.colnames!=other.colnames:
>>>             raise Exception('Cannot & incompatible Rows objects')
>>>         records = self.records+other.records
>>>         return Rows(self.db,records,self.colnames,compact=(self.compact 
>>> or other.compact))
>>>
>>>
>>> In the case above, the flag compact will be set True if either of the 
>>> participating Rows object is also "compact".  My logic is, if you've lost 
>>> the "table" values on either Rows object, you may as well lose them on the 
>>> combined set.
>>>
>>> What do you think?
>>>
>>> -- Joe B.
>>>
>>>
>>>

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to