Пример #1
0
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
Пример #2
0
    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)
Пример #3
0
 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)
Пример #4
0
    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)
Пример #5
0
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)
Пример #6
0
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)
Пример #7
0
 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)