OK, good point. In that case, I'll just send a patch for .find and .sort so 
they return the original self.records items so .render will work properly.

Anthony

On Wednesday, January 8, 2014 11:47:24 AM UTC-5, Massimo Di Pierro wrote:
>
> The problem is speed. I believe the getitem should be as fast as possible. 
> This was changed before so that the trasformation of the rows occurred only 
> once and not every time a row column is accessed.
>
> On Jan 8, 2014, at 8:41 AM, Anthony wrote:
>
> Let's discuss on the developers 
> list<https://groups.google.com/forum/?fromgroups=#!topic/web2py-developers/k2D6MVfBEYo>
> .
>
> On Tuesday, January 7, 2014 9:52:16 PM UTC-5, Joe Barnhart wrote:
>>
>> Maybe the best answer is to change Row so that it always holds the full 
>> set of keys (table:field) and change the __getitem__ method to look up the 
>> key recursively if only one part is provided.  Here is a sample method 
>> which implements this strategy of testing keys for dicts within dicts.  Our 
>> case is a little simpler since we never "recurse" more than one level deep.
>>
>> def _finditem(obj, key):
>>     if key in obj: return obj[key]
>>     for k, v in obj.items():
>>         if isinstance(v,dict):
>>             item = _finditem(v, key)
>>             if item is not None:
>>                 return item
>>
>>
>> This has the advantage of working with existing code and preserving as 
>> much information as possible in the Row object.  I have a feeling this 
>> could make the internals of web2py a good deal more consistent.  Less 
>> testing for special cases is always good!
>>
>> -- Joe B.
>>
>> On Tuesday, January 7, 2014 3:48:39 PM UTC-8, Anthony wrote:
>>>
>>> Note, same problem with .sort (it modifies the Row objects in 
>>> self.records), so we should probably fix that as well (will be a bit more 
>>> complicated).
>>>
>>> Anthony
>>>
>>> On Tuesday, January 7, 2014 11:03:56 AM UTC-5, 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.
>>>>>>
>>>>>>
>>>>>>
> -- 
> -- mail from:GoogleGroups "web2py-developers" mailing list
> make speech: web2py-d...@googlegroups.com <javascript:>
> unsubscribe: web2py-develop...@googlegroups.com <javascript:>
> details : http://groups.google.com/group/web2py-developers
> the project: http://code.google.com/p/web2py/
> official : http://www.web2py.com/
> --- 
> You received this message because you are subscribed to the Google Groups 
> "web2py-developers" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to web2py-develop...@googlegroups.com <javascript:>.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
>

-- 
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