def search_cursor_timeout_decorator(cursor, skip, limit): r""" INPUT: - pymongo cursor - skip value to pass to cursor (after cursor.count()) - limit value to pass to cursor (after cursor.count()) OUTPUT: If the query doesn't time out returns the tuple (skip, cursor.count(), cursor.skip(skip).limit(limit)) If the query times out, it raises a ValueError """ # 25 seconds, timeout, hopefully enough to avoid google's and gunicorn's timeout of 30s cursor = cursor.max_time_ms(25000) try: ncursor = cursor.count() # adjusts skip if necessary if(skip >= ncursor): skip -= (1 + (skip - ncursor) / limit) * limit if(skip < 0): skip = 0 cursor = cursor.skip(skip).limit(limit) except ExecutionTimeout as err: ctx = ctx_proc_userdata() flash_error('The search query took longer than expected! Please help us improve by reporting this error <a href="%s" target=_blank>here</a>.' % ctx['feedbackpage']); raise ValueError(err) return skip, ncursor, cursor
def __call__(self, info): info = to_dict(info) # I'm not sure why this is required... for key, func in self.shortcuts.items(): if info.get(key,'').strip(): return func(info) query = {} template_kwds = {} for key in self.kwds: template_kwds[key] = info.get(key, self.kwds[key]()) try: errpage = self.f(info, query) except ValueError as err: # Errors raised in parsing info['err'] = str(err) err_title = query.pop('__err_title__', self.err_title) return render_template(self.template, info=info, title=err_title, **template_kwds) if errpage is not None: return errpage if 'result_count' in info: nres = self.table.count(query) return jsonify({"nres":str(nres)}) sort = query.pop('__sort__', None) table = query.pop('__table__', self.table) proj = query.pop('__projection__', self.projection) # We want to pop __title__ even if overridden by info. title = query.pop('__title__', self.title) title = info.get('title', title) template = query.pop('__template__', self.template) count = parse_count(info, self.per_page) start = parse_start(info) try: res = table.search(query, proj, limit=count, offset=start, sort=sort, info=info) except QueryCanceledError as err: ctx = ctx_proc_userdata() flash_error('The search query took longer than expected! Please help us improve by reporting this error <a href="%s" target=_blank>here</a>.' % ctx['feedbackpage']) info['err'] = str(err) info['query'] = dict(query) return render_template(self.template, info=info, title=self.err_title, **template_kwds) else: if self.cleaners: for v in res: for name, func in self.cleaners.items(): v[name] = func(v) if self.postprocess is not None: res = self.postprocess(res, info, query) for key, func in self.longcuts.items(): if info.get(key,'').strip(): return func(res, info, query) info['results'] = res return render_template(template, info=info, title=title, **template_kwds)
def __call__(self, info, random=False): # If random is True, returns a random label info = to_dict(info, exclude =['bread']) # I'm not sure why this is required... for key, func in self.shortcuts.items(): if info.get(key,'').strip(): return func(info) query = {} template_kwds = {} for key in self.kwds: template_kwds[key] = info.get(key, self.kwds[key]()) try: errpage = self.f(info, query) except ValueError as err: # Errors raised in parsing info['err'] = str(err) err_title = query.pop('__err_title__', self.err_title) return render_template(self.template, info=info, title=err_title, **template_kwds) else: err_title = query.pop('__err_title__', self.err_title) if errpage is not None: return errpage if 'result_count' in info: nres = self.table.count(query) return jsonify({"nres":str(nres)}) sort = query.pop('__sort__', None) table = query.pop('__table__', self.table) # We want to pop __title__ even if overridden by info. title = query.pop('__title__', self.title) title = info.get('title', title) template = query.pop('__template__', self.template) if random: query.pop('__projection__', None) proj = query.pop('__projection__', self.projection) count = parse_count(info, self.per_page) start = parse_start(info) try: if random: # Ignore __projection__: it's intended for searches label = table.random(query, projection=0) if label is None: res = [] # ugh; we have to set these manually info['query'] = dict(query) info['number'] = 0 info['count'] = count info['start'] = start info['exact_count'] = True else: return redirect(self.url_for_label(label), 307) else: res = table.search(query, proj, limit=count, offset=start, sort=sort, info=info) except QueryCanceledError as err: ctx = ctx_proc_userdata() flash_error('The search query took longer than expected! Please help us improve by reporting this error <a href="%s" target=_blank>here</a>.' % ctx['feedbackpage']) info['err'] = str(err) info['query'] = dict(query) return render_template(self.template, info=info, title=self.err_title, **template_kwds) else: try: if self.cleaners: for v in res: for name, func in self.cleaners.items(): v[name] = func(v) if self.postprocess is not None: res = self.postprocess(res, info, query) except ValueError as err: # Errors raised in postprocessing flash_error(str(err)) info['err'] = str(err) return render_template(self.template, info=info, title=err_title, **template_kwds) for key, func in self.longcuts.items(): if info.get(key,'').strip(): return func(res, info, query) info['results'] = res return render_template(template, info=info, title=title, **template_kwds)
def __call__(self, info): info = to_dict(info) # I'm not sure why this is required... for key, func in self.shortcuts.items(): if info.get(key, '').strip(): return func(info) query = {} template_kwds = {} for key in self.kwds: template_kwds[key] = info.get(key, self.kwds[key]()) try: errpage = self.f(info, query) except ValueError as err: # Errors raised in parsing info['err'] = str(err) err_title = query.pop('__err_title__', self.err_title) return render_template(self.template, info=info, title=err_title, **template_kwds) if errpage is not None: return errpage if 'result_count' in info: nres = self.table.count(query) return jsonify({"nres": str(nres)}) sort = query.pop('__sort__', None) table = query.pop('__table__', self.table) proj = query.pop('__projection__', self.projection) # We want to pop __title__ even if overridden by info. title = query.pop('__title__', self.title) title = info.get('title', title) template = query.pop('__template__', self.template) count = parse_count(info, self.per_page) start = parse_start(info) try: res = table.search(query, proj, limit=count, offset=start, sort=sort, info=info) except QueryCanceledError as err: ctx = ctx_proc_userdata() flash_error( 'The search query took longer than expected! Please help us improve by reporting this error <a href="%s" target=_blank>here</a>.' % ctx['feedbackpage']) info['err'] = str(err) info['query'] = dict(query) return render_template(self.template, info=info, title=self.err_title, **template_kwds) else: if self.cleaners: for v in res: for name, func in self.cleaners.items(): v[name] = func(v) if self.postprocess is not None: res = self.postprocess(res, info, query) for key, func in self.longcuts.items(): if info.get(key, '').strip(): return func(res, info, query) info['results'] = res return render_template(template, info=info, title=title, **template_kwds)
def search(**args): """ query processing for Sato-Tate groups -- returns rendered results page """ info = to_dict(args) if 'jump' in info: return redirect(url_for('.by_label', label=info['jump']), 301) if 'label' in info: return redirect(url_for('.by_label', label=info['label']), 301) template_kwds = { 'bread': [('Sato-Tate Groups', url_for('.index')), ('Search Results', '.')], 'credit': credit_string, 'learnmore': learnmore_list() } title = 'Sato-Tate Group Search Results' err_title = 'Sato-Tate Groups Search Input Error' count = parse_count(info, 25) start = parse_start(info) # if user clicked refine search always restart at 0 if 'refine' in info: start = 0 ratonly = True if info.get('rational_only', 'no').strip().lower() == 'yes' else False query = {'rational': True} if ratonly else {} try: parse_ints(info, query, 'weight', 'weight') if 'weight' in query: weight_list = parse_ints_to_list_flash(info.get('weight'), 'weight') parse_ints(info, query, 'degree', 'degree') if 'degree' in query: degree_list = parse_ints_to_list_flash(info.get('degree'), 'degree') if info.get('identity_component'): query['identity_component'] = info['identity_component'] parse_ints(info, query, 'components', 'components') if 'components' in query: components_list = parse_ints_to_list_flash(info.get('components'), 'components') parse_rational(info, query, 'trace_zero_density', 'trace zero density') except ValueError as err: info['err'] = str(err) return render_template('st_results.html', info=info, title=err_title, **template_kwds) # Check mu(n) groups first (these are not stored in the database) results = [] if (not 'weight' in query or 0 in weight_list) and \ (not 'degree' in query or 1 in degree_list) and \ (not 'identity_component' in query or query['identity_component'] == 'SO(1)') and \ (not 'trace_zero_density' in query or query['trace_zero_density'] == '0'): if not 'components' in query: components_list = xrange(1, 3 if ratonly else start + count + 1) elif ratonly: components_list = [n for n in range(1, 3) if n in components_list] nres = len( components_list) if 'components' in query or ratonly else INFINITY for n in itertools.islice(components_list, start, start + count): results.append(mu_info(n)) else: nres = 0 if 'result_count' in info: nres += db.gps_sato_tate.count(query) return jsonify({"nres": str(nres)}) # Now lookup other (rational) ST groups in database if nres != INFINITY: start2 = start - nres if start > nres else 0 proj = [ 'label', 'weight', 'degree', 'real_dimension', 'identity_component', 'name', 'pretty', 'components', 'component_group', 'trace_zero_density', 'moments' ] try: res = db.gps_sato_tate.search(query, proj, limit=max(count - len(results), 0), offset=start2, info=info) except QueryCanceledError as err: ctx = ctx_proc_userdata() flash_error( 'The search query took longer than expected! Please help us improve by reporting this error <a href="%s" target=_blank>here</a>.' % ctx['feedbackpage']) info['err'] = str(err) return render_template('st_results.html', info=info, title=err_title, **template_kwds) info['number'] += nres if start < info['number'] and len(results) < count: for v in res: v['identity_component'] = st0_pretty(v['identity_component']) v['component_group'] = sg_pretty(v['component_group']) v['trace_moments'] = trace_moments(v['moments']) results.append(v) else: info['number'] = 'infinity' info['start'] = start info['count'] = count info['st0_list'] = st0_list info['st0_dict'] = st0_dict info['results'] = results info['stgroup_url'] = lambda dbc: url_for('.by_label', label=dbc['label']) return render_template('st_results.html', info=info, title=title, **template_kwds)
def search(**args): """ query processing for Sato-Tate groups -- returns rendered results page """ info = to_dict(args) if 'jump' in info: return redirect(url_for('.by_label', label=info['jump']), 301) if 'label' in info: return redirect(url_for('.by_label', label=info['label']), 301) template_kwds = {'bread':[('Sato-Tate Groups', url_for('.index')),('Search Results', '.')], 'credit':credit_string, 'learnmore':learnmore_list()} title = 'Sato-Tate Group Search Results' err_title = 'Sato-Tate Groups Search Input Error' count = parse_count(info, 25) start = parse_start(info) # if user clicked refine search always restart at 0 if 'refine' in info: start = 0 ratonly = True if info.get('rational_only','no').strip().lower() == 'yes' else False query = {'rational':True} if ratonly else {} try: parse_ints(info,query,'weight','weight') if 'weight' in query: weight_list = parse_ints_to_list_flash(info.get('weight'),'weight') parse_ints(info,query,'degree','degree') if 'degree' in query: degree_list = parse_ints_to_list_flash(info.get('degree'),'degree') if info.get('identity_component'): query['identity_component'] = info['identity_component'] parse_ints(info,query,'components','components') if 'components' in query: components_list = parse_ints_to_list_flash(info.get('components'), 'components') parse_rational(info,query,'trace_zero_density','trace zero density') except ValueError as err: info['err'] = str(err) return render_template('st_results.html', info=info, title=err_title, **template_kwds) # Check mu(n) groups first (these are not stored in the database) results = [] if (not 'weight' in query or 0 in weight_list) and \ (not 'degree' in query or 1 in degree_list) and \ (not 'identity_component' in query or query['identity_component'] == 'SO(1)') and \ (not 'trace_zero_density' in query or query['trace_zero_density'] == '0'): if not 'components' in query: components_list = xrange(1,3 if ratonly else start+count+1) elif ratonly: components_list = [n for n in range(1,3) if n in components_list] nres = len(components_list) if 'components' in query or ratonly else INFINITY for n in itertools.islice(components_list,start,start+count): results.append(mu_info(n)) else: nres = 0 if 'result_count' in info: nres += db.gps_sato_tate.count(query) return jsonify({"nres":str(nres)}) # Now lookup other (rational) ST groups in database if nres != INFINITY: start2 = start - nres if start > nres else 0 proj = ['label','weight','degree','real_dimension','identity_component','name','pretty','components','component_group','trace_zero_density','moments'] try: res = db.gps_sato_tate.search(query, proj, limit=max(count - len(results), 0), offset=start2, info=info) except QueryCanceledError as err: ctx = ctx_proc_userdata() flash_error('The search query took longer than expected! Please help us improve by reporting this error <a href="%s" target=_blank>here</a>.' % ctx['feedbackpage']) info['err'] = str(err) return render_template('st_results.html', info=info, title=err_title, **template_kwds) info['number'] += nres if start < info['number'] and len(results) < count: for v in res: v['identity_component'] = st0_pretty(v['identity_component']) v['component_group'] = sg_pretty(v['component_group']) v['trace_moments'] = trace_moments(v['moments']) results.append(v) else: info['number'] = 'infinity' info['start'] = start info['count'] = count info['st0_list'] = st0_list info['st0_dict'] = st0_dict info['results'] = results info['stgroup_url'] = lambda dbc: url_for('.by_label', label=dbc['label']) return render_template('st_results.html', info=info, title=title, **template_kwds)
def __call__(self, info, random=False): # If random is True, returns a random label info = to_dict(info, exclude=['bread' ]) # I'm not sure why this is required... for key, func in self.shortcuts.items(): if info.get(key, '').strip(): return func(info) query = {} template_kwds = {} for key in self.kwds: template_kwds[key] = info.get(key, self.kwds[key]()) try: errpage = self.f(info, query) except ValueError as err: # Errors raised in parsing info['err'] = str(err) err_title = query.pop('__err_title__', self.err_title) return render_template(self.template, info=info, title=err_title, **template_kwds) else: err_title = query.pop('__err_title__', self.err_title) if errpage is not None: return errpage if 'result_count' in info: nres = self.table.count(query) return jsonify({"nres": str(nres)}) sort = query.pop('__sort__', None) table = query.pop('__table__', self.table) # We want to pop __title__ even if overridden by info. title = query.pop('__title__', self.title) title = info.get('title', title) template = query.pop('__template__', self.template) if random: query.pop('__projection__', None) proj = query.pop('__projection__', self.projection) count = parse_count(info, self.per_page) start = parse_start(info) try: if random: # Ignore __projection__: it's intended for searches label = table.random(query, projection=0) if label is None: res = [] # ugh; we have to set these manually info['query'] = dict(query) info['number'] = 0 info['count'] = count info['start'] = start info['exact_count'] = True else: return redirect(self.url_for_label(label), 307) else: res = table.search(query, proj, limit=count, offset=start, sort=sort, info=info) except QueryCanceledError as err: ctx = ctx_proc_userdata() flash_error( 'The search query took longer than expected! Please help us improve by reporting this error <a href="%s" target=_blank>here</a>.' % ctx['feedbackpage']) info['err'] = str(err) info['query'] = dict(query) return render_template(self.template, info=info, title=self.err_title, **template_kwds) else: try: if self.cleaners: for v in res: for name, func in self.cleaners.items(): v[name] = func(v) if self.postprocess is not None: res = self.postprocess(res, info, query) except ValueError as err: # Errors raised in postprocessing flash_error(str(err)) info['err'] = str(err) return render_template(self.template, info=info, title=err_title, **template_kwds) for key, func in self.longcuts.items(): if info.get(key, '').strip(): return func(res, info, query) info['results'] = res return render_template(template, info=info, title=title, **template_kwds)