I'm guessing the button is generated via form.add_button(), which uses TAG['button'], which generates a __tag_div__ object, which is pickled with the custom TAG_pickler function:
def TAG_pickler(data): d = DIV() d.__dict__ = data.__dict__ marshal_dump = pickle.dumps(d, pickle.HIGHEST_PROTOCOL) return (TAG_unpickler, (marshal_dump,)) When a web2py HTML DOM element is nested inside another element, its __dict__ has a reference to the parent element, resulting in a recursive object. This is generally not a problem for pickle, but I guess the the fact that TAG_pickler creates a new DIV object and copies the __dict__ of the original __tag_div__ object to the new DIV object must somehow break down pickle's tracking of the recursive references, resulting in infinite recursion during the pickle process. I'm not sure we actually need the TAG_pickler anyway -- I tried removing it, and pickling seemed to work fine, at least in a simple test case. Maybe we can get away without it. For now, though, a workaround would be to render the HTML right in the controller so cache.action will cache the raw HTML output instead of caching a Python dictionary holding a web2py DOM object. This will also speed things up, as web2py will not need to keep re-executing the view on each request. For example: return response.render(dict(form=form)) If you don't mind, please open a Github issue about this and link back to this post. Anthony On Sunday, July 29, 2018 at 2:59:40 PM UTC-4, Joe Barnhart wrote: > > I'm using cache.action with cache_model=cache.disk to play with > optimization of my site. To be sure, this page has a lot going on -- > complicated menus using "button" objects among the issues. But I don't > have any circular references, at least as far as I can tell. Still, I get > the error: > > Traceback (most recent call last): > File "/Users/jbarnhart/Work/w2p_env/ss/gluon/restricted.py", line 219, > in restricted > exec(ccode, environment) > File > "/Users/jbarnhart/Work/w2p_env/ss/applications/swim_smarter/controllers/results.py", > > line 29, in <module> > File "/Users/jbarnhart/Work/w2p_env/ss/gluon/globals.py", line 419, in > <lambda> > self._caller = lambda f: f() > File "/Users/jbarnhart/Work/w2p_env/ss/gluon/cache.py", line 632, in > wrapped_f > rtn = cache_model(cache_key, lambda: func(), time_expire=time_expire) > File "/Users/jbarnhart/Work/w2p_env/ss/gluon/cache.py", line 467, in > __call__ > self.storage[key] = (now, value) > File "/Users/jbarnhart/Work/w2p_env/ss/gluon/cache.py", line 339, in > __setitem__ > pickle.dump(value, val_file, pickle.HIGHEST_PROTOCOL) > File "/Users/jbarnhart/Work/w2p_env/ss/gluon/html.py", line 1256, in > TAG_pickler > marshal_dump = pickle.dumps(d, pickle.HIGHEST_PROTOCOL) > File "/Users/jbarnhart/Work/w2p_env/ss/gluon/html.py", line 1256, in > TAG_pickler > marshal_dump = pickle.dumps(d, pickle.HIGHEST_PROTOCOL) > > ... some duplication omitted ... > > File "/Users/jbarnhart/Work/w2p_env/ss/gluon/html.py", line 1256, in > TAG_pickler > marshal_dump = pickle.dumps(d, pickle.HIGHEST_PROTOCOL) > File "/Users/jbarnhart/Work/w2p_env/ss/gluon/html.py", line 1256, in > TAG_pickler > marshal_dump = pickle.dumps(d, pickle.HIGHEST_PROTOCOL) > File > "/Applications/WingIDE.app/Contents/Resources/patches/6.0.12/04-fix-logging-exc/bin/dbg/src/debug/tserver/dbgutils.py", > > line 3409, in wrapper > File > "/Applications/WingIDE.app/Contents/Resources/patches/6.0.12/04-fix-logging-exc/bin/dbg/src/debug/tserver/dbgutils.py", > > line 2955, in Log > RuntimeError: maximum recursion depth exceeded > > The particular code being pickled, if it matters, looks like this: > > <button class="btn btn-primary dropdown-toggle button" > data-toggle="dropdown"> > Male > <span class="caret"></span></button> > > Followed by: > > <button class="btn btn-primary dropdown-toggle button" > data-toggle="dropdown"> > 100M Back <span class="caret"> > </span></button> > > Over and over. > > The full HTML sequence is this. Note the pair of problem buttons are not > adjacent. But I've never studied the pickler and don't know how it works, > so maybe it's not an issue. > > <div class="widget-box" id="meettimes"> > <div class="widget-header"> > <h3 class="widget-title smaller ">2018 Phoenix Summer Invitation</h3> > <div class="widget-toolbar no-border" id="meettimes-tb" style="padding:0 > 0 0 5px;"> > <div class="widget-menu"> > <button class="btn btn-primary dropdown-toggle button" > data-toggle="dropdown"> > Male <span class="caret"</span> > </button> > <ul class="dropdown-menu dropdown-caret dropdown-close"> > <li><a class="" > href="/swim_smarter/results/meettimes?eid=266&mid=14&stage=F">Female</a></li> > <li><a class="" href="#">Male</a></li> > <li><a class="disabled" > href="/swim_smarter/results/meettimes?eid=848&mid=14&stage=F">Mixed</a></li> > </ul> > </div> > <div class="widget-menu"> > <button class="btn btn-primary dropdown-toggle button" > data-toggle="dropdown"> > 100M Back <span class="caret"></span> > </button> > <ul class="dropdown-menu dropdown-caret dropdown-close"> > <li><a class="" > href="/swim_smarter/results/meettimes?eid=106&mid=14&stage=F">50M > Free</a></li> > <li><a class="" > href="/swim_smarter/results/meettimes?eid=107&mid=14&stage=F">100M > Free</a></li> > <li><a class="" > href="/swim_smarter/results/meettimes?eid=102&mid=14&stage=F">200M > Free</a></li> > <li><a class="" > href="/swim_smarter/results/meettimes?eid=299&mid=14&stage=F">400M > Free</a></li> > <li><a class="disabled" > href="/swim_smarter/results/meettimes?eid=331&mid=14&stage=F">800M > Free</a></li> > <li><a class="" > href="/swim_smarter/results/meettimes?eid=808&mid=14&stage=F">1500M > Free</a></li> > <li><a class="" > href="/swim_smarter/results/meettimes?eid=188&mid=14&stage=F">50M > Back</a></li> > <li><a class="" href="#">100M Back</a></li> > <li><a class="disabled" > href="/swim_smarter/results/meettimes?eid=833&mid=14&stage=F">200M > Back</a></li> > <li><a class="" > href="/swim_smarter/results/meettimes?eid=108&mid=14&stage=F">50M > Breast</a></li> > <li><a class="" > href="/swim_smarter/results/meettimes?eid=105&mid=14&stage=F">100M > Breast</a></li> > <li><a class="disabled" > href="/swim_smarter/results/meettimes?eid=832&mid=14&stage=F">200M > Breast</a></li> > <li><a class="" > href="/swim_smarter/results/meettimes?eid=103&mid=14&stage=F">50M > Fly</a></li> > <li><a class="" > href="/swim_smarter/results/meettimes?eid=104&mid=14&stage=F">100M > Fly</a></li> > <li><a class="disabled" > href="/swim_smarter/results/meettimes?eid=866&mid=14&stage=F">200M > Fly</a></li> > <li><a class="" > href="/swim_smarter/results/meettimes?eid=110&mid=14&stage=F">200M > Medley</a></li> > <li><a class="disabled" > href="/swim_smarter/results/meettimes?eid=287&mid=14&stage=F">400M > Medley</a></li> > </ul> > </div> > <div class="widget-menu"> > <button class="btn btn-primary dropdown-toggle button" > data-toggle="dropdown"> > 11-12 <span class="caret"></span> > </button> > <ul class="dropdown-menu dropdown-caret dropdown-close"> > <li><a class="disabled" > href="/swim_smarter/results/meettimes?eid=800&mid=14&stage=F">10-Un</a></li> > <li><a class="" href="#">11-12</a></li> > <li><a class="" > href="/swim_smarter/results/meettimes?eid=151&mid=14&stage=F">13-14</a></li> > <li><a class="" > href="/swim_smarter/results/meettimes?eid=823&mid=14&stage=F">15-Ov</a></li> > <li><a class="disabled" > href="/swim_smarter/results/meettimes?eid=856&mid=14&stage=F">13-Ov</a></li> > <li><a class="disabled" > href="/swim_smarter/results/meettimes?eid=848&mid=14&stage=F">Open</a></li> > </ul> > </div> > <div class="widget-menu"> > <button class="btn btn-primary dropdown-toggle button" > data-toggle="dropdown"> > Finals <span class="caret"></span> > </button> > <ul class="dropdown-menu dropdown-caret dropdown-close"> > <li><a class="" href="#">Finals</a></li> > <li><a class="" > href="/swim_smarter/results/meettimes?eid=258&mid=14&stage=P">Prelims</a></li> > <li><a class="" > href="/swim_smarter/results/meettimes?eid=258&mid=14&stage=S">Swim-offs</a></li> > </ul> > </div> > </div> > </div> > <div class="widget-body"> > <div class="widget-main no-padding"> > <table class="table table-striped table-bordered table-hover" > data-api="mttabapi" data-var="mttabdv" id="mttab" style="width:100%;"> > </table> > </div> > </div> > </div> > -- 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/d/optout.