<commit_before>from django.forms import Form, ModelForm, CharField, IntegerField, HiddenInput, \
        ModelMultipleChoiceField
from search.models import Comment, Question, Information, GoodPractice, \
    Person, Project, Event, Glossary, Community, Item
from search.widgets import TagInput, NonAdminFilteredSelectMultiple
from bootstrap3_datetime.widgets import DateTimePicker

class CommentForm(ModelForm):
    item_type = CharField(widget=HiddenInput())
    item_id = IntegerField(widget=HiddenInput())

    class Meta:
        model = Comment
        fields = ['text', 'tags']

    def __init__(self, *args, **kwargs):
        super(CommentForm, self).__init__(*args, **kwargs)
        self.fields['tags'].widget = TagInput()
        self.fields['tags'].help_text = None

class QuestionForm(ModelForm):
    item_type = CharField(widget=HiddenInput())
    item_id = IntegerField(widget=HiddenInput())

    class Meta:
        model = Question
        fields = ['title', 'text', 'tags']

    def __init__(self, *args, **kwargs):
        super(QuestionForm, self).__init__(*args, **kwargs)
        self.fields['tags'].widget = TagInput()
        self.fields['tags'].help_text = None

class DashboardForm(ModelForm):
    def __init__(self, *args, **kwargs):
        if "communities" in kwargs:
            communities = kwargs["communities"]
            del kwargs["communities"]
        else:
            communities = Community.objects
        super(DashboardForm, self).__init__(*args, **kwargs)
        self.fields['tags'].widget = TagInput()
        self.fields['tags'].help_text = None
        if 'links' in self.fields:
            self.fields['links'] = ModelMultipleChoiceField(Item.objects.all(),
                widget=NonAdminFilteredSelectMultiple("Links", False),
                required=False)
        if 'communities' in self.fields:
            self.fields['communities'] = ModelMultipleChoiceField(communities,
                widget=NonAdminFilteredSelectMultiple("Communities", False))
        if 'date' in self.fields:
            self.fields['date'].widget = \
                DateTimePicker(options={"format": "YYYY-MM-DD HH:mm",
                                        "pickSeconds": False})
        print self.fields

    class Media:
        js = ['/admin/jsi18n/']
        css = {'all': ['admin/css/widgets.css', 'css/m2m_form_widget.css'], }

class EditInformationForm(DashboardForm):
    class Meta:
        model = Information
        fields = ['title', 'text', 'links', 'author', 'communities', 'tags']

class EditCommentForm(DashboardForm):
    class Meta:
        model = Information
        fields = ['title', 'text', 'tags']

class EditGoodPracticeForm(DashboardForm):
    class Meta:
        model = GoodPractice
        fields = ['title', 'text', 'links', 'author', 'communities', 'tags']

class EditQuestionForm(DashboardForm):
    class Meta:
        model = Question
        fields = ['title', 'text', 'links', 'author', 'communities', 'tags']

class EditPersonForm(DashboardForm):
    class Meta:
        model = Person
        fields = ['title', 'name', 'headline', 'about', 'photo', 'website',
                  'email', 'communities']

class EditProjectForm(DashboardForm):
    class Meta:
        model = Project
        fields = ['title', 'text', 'contact', 'author', 'communities', 'links',
                  'tags']

class EditEventForm(DashboardForm):
    class Meta:
        model = Event
        fields = ['title', 'text', 'contact', 'author', 'communities', 'links',
                  'tags', 'date']

class EditGlossaryForm(DashboardForm):
    class Meta:
        model = Glossary
        fields = ['title', 'text', 'tags', 'author', 'links', 'communities']
<commit_msg>Dashboard links now ordered on type, although not in alphabetical order #132<commit_after>from django.forms import Form, ModelForm, CharField, IntegerField, HiddenInput, \
        ModelMultipleChoiceField
from search.models import Comment, Question, Information, GoodPractice, \
    Person, Project, Event, Glossary, Community, Item
from search.widgets import TagInput, NonAdminFilteredSelectMultiple
from bootstrap3_datetime.widgets import DateTimePicker

class CommentForm(ModelForm):
    item_type = CharField(widget=HiddenInput())
    item_id = IntegerField(widget=HiddenInput())

    class Meta:
        model = Comment
        fields = ['text', 'tags']

    def __init__(self, *args, **kwargs):
        super(CommentForm, self).__init__(*args, **kwargs)
        self.fields['tags'].widget = TagInput()
        self.fields['tags'].help_text = None

class QuestionForm(ModelForm):
    item_type = CharField(widget=HiddenInput())
    item_id = IntegerField(widget=HiddenInput())

    class Meta:
        model = Question
        fields = ['title', 'text', 'tags']

    def __init__(self, *args, **kwargs):
        super(QuestionForm, self).__init__(*args, **kwargs)
        self.fields['tags'].widget = TagInput()
        self.fields['tags'].help_text = None

class DashboardForm(ModelForm):
    def __init__(self, *args, **kwargs):
        if "communities" in kwargs:
            communities = kwargs["communities"]
            del kwargs["communities"]
        else:
            communities = Community.objects
        super(DashboardForm, self).__init__(*args, **kwargs)
        self.fields['tags'].widget = TagInput()
        self.fields['tags'].help_text = None
        if 'links' in self.fields:
            self.fields['links'] = ModelMultipleChoiceField(
                Item.objects.order_by('type'),
                widget=NonAdminFilteredSelectMultiple("Links", False),
                required=False)
        if 'communities' in self.fields:
            self.fields['communities'] = ModelMultipleChoiceField(
                communities,
                widget=NonAdminFilteredSelectMultiple("Communities", False))
        if 'date' in self.fields:
            self.fields['date'].widget = \
                DateTimePicker(options={"format": "YYYY-MM-DD HH:mm",
                                        "pickSeconds": False})
        print self.fields

    class Media:
        js = ['/admin/jsi18n/']
        css = {'all': ['admin/css/widgets.css', 'css/m2m_form_widget.css'], }

class EditInformationForm(DashboardForm):
    class Meta:
        model = Information
        fields = ['title', 'text', 'links', 'author', 'communities', 'tags']

class EditCommentForm(DashboardForm):
    class Meta:
        model = Information
        fields = ['title', 'text', 'tags']

class EditGoodPracticeForm(DashboardForm):
    class Meta:
        model = GoodPractice
        fields = ['title', 'text', 'links', 'author', 'communities', 'tags']

class EditQuestionForm(DashboardForm):
    class Meta:
        model = Question
        fields = ['title', 'text', 'links', 'author', 'communities', 'tags']

class EditPersonForm(DashboardForm):
    class Meta:
        model = Person
        fields = ['title', 'name', 'headline', 'about', 'photo', 'website',
                  'email', 'communities']

class EditProjectForm(DashboardForm):
    class Meta:
        model = Project
        fields = ['title', 'text', 'contact', 'author', 'communities', 'links',
                  'tags']

class EditEventForm(DashboardForm):
    class Meta:
        model = Event
        fields = ['title', 'text', 'contact', 'author', 'communities', 'links',
                  'tags', 'date']

class EditGlossaryForm(DashboardForm):
    class Meta:
        model = Glossary
        fields = ['title', 'text', 'tags', 'author', 'links', 'communities']
<|endoftext|>


<commit_before>'''
A Python port of KUKA Varproxy client (OpenShowVar).

Authors:
    - Message format analysis: Liang Tao
    - Programming: Huang Jie
'''

import struct
import random
import socket

class openshowvar(object):
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port
        self.msg_id = random.randint(1, 100)
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            self.sock.connect((self.ip, self.port))
        except socket.error:
            pass

    def test_connection(self):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            ret = sock.connect_ex((self.ip, self.port))
            return ret == 0
        except socket.error:
            print 'socket error'
            return False

    can_connect = property(test_connection)

    def read(self, var, debug=True):
        if not isinstance(var, str):
            raise Exception('Var name is a string')
        else:
            self.varname = var
        return self._read_var(debug)

    def write(self, var, value, debug=True):
        if not (isinstance(var, str) and isinstance(value, str)):
            raise Exception('Var name and its value should be string')
        self.varname = var
        self.value = value
        return self._write_var(debug)

    def _read_var(self, debug):
        req = self._pack_read_req()
        self._send_req(req)
        _value = self._read_rsp(debug)
        print 'read value -->', _value
        return _value

    def _write_var(self, debug):
        req = self._pack_write_req()
        self._send_req(req)
        _value = self._read_rsp(debug)
        print 'write value -->', _value
        return _value

    def _send_req(self, req):
        self.rsp = None
        self.sock.sendall(req)
        self.rsp = self.sock.recv(256)

    def _pack_read_req(self):
        var_name_len = len(self.varname)
        flag = 0
        req_len = var_name_len + 3

        return struct.pack(
            '!HHBH'+str(var_name_len)+'s',
            self.msg_id,
            req_len,
            flag,
            var_name_len,
            self.varname
            )

    def _pack_write_req(self):
        var_name_len = len(self.varname)
        flag = 1
        value_len = len(self.value)
        req_len = var_name_len + 3 + 2 + value_len

        return struct.pack(
            '!HHBH'+str(var_name_len)+'s'+'H'+str(value_len)+'s',
            self.msg_id,
            req_len,
            flag,
            var_name_len,
            self.varname,
            value_len,
            self.value
            )

    def _read_rsp(self, debug=False):
        if self.rsp is None: return None
        var_value_len = len(self.rsp) - struct.calcsize('!HHBH') - 3
        result = struct.unpack('!HHBH'+str(var_value_len)+'s'+'3s', self.rsp)
        _msg_id, body_len, flag, var_value_len, var_value, isok = result
        if debug:
            print '[DEBUG]', result
        if result[-1].endswith('\x01') and _msg_id == self.msg_id:   # todo
            self.msg_id += 1
            return var_value

def test():
    foo = openshowvar('192.168.19.246', 7000)
    if not foo.can_connect:
        print 'connection error'
        import sys
        sys.exit(-1)
    foo.write('$OV_PRO', str(random.randint(30, 50)))
    print 'start: $OV_PRO minus one, until zero'

    ov = int(current_ov)
    for i in range(ov, 0, -1):
        foo.write('$OV_PRO', str(i))

def test2():
    foo = openshowvar('192.168.19.133', 7001)
    if not foo.can_connect:
        print 'connection error'
        import sys
        sys.exit(-1)
    while True:
        data = raw_input('\nInput var_name [, var_value]\n(`q` for quit): ')
        if data.lower() == 'q': break
        else:
            parts = data.split(',')
            if len(parts) == 1:
                foo.read(data.strip(), True)
            else:
                foo.write(parts[0], parts[1], True)

if __name__ == '__main__':
    test2()

<commit_msg>remove useless test routines<commit_after>'''
A Python port of KUKA VarProxy client (OpenShowVar).
'''

import struct
import random
import socket

class openshowvar(object):
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port
        self.msg_id = random.randint(1, 100)
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            self.sock.connect((self.ip, self.port))
        except socket.error:
            pass

    def test_connection(self):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            ret = sock.connect_ex((self.ip, self.port))
            return ret == 0
        except socket.error:
            print 'socket error'
            return False

    can_connect = property(test_connection)

    def read(self, var, debug=True):
        if not isinstance(var, str):
            raise Exception('Var name is a string')
        else:
            self.varname = var
        return self._read_var(debug)

    def write(self, var, value, debug=True):
        if not (isinstance(var, str) and isinstance(value, str)):
            raise Exception('Var name and its value should be string')
        self.varname = var
        self.value = value
        return self._write_var(debug)

    def _read_var(self, debug):
        req = self._pack_read_req()
        self._send_req(req)
        _value = self._read_rsp(debug)
        print 'read value -->', _value
        return _value

    def _write_var(self, debug):
        req = self._pack_write_req()
        self._send_req(req)
        _value = self._read_rsp(debug)
        print 'write value -->', _value
        return _value

    def _send_req(self, req):
        self.rsp = None
        self.sock.sendall(req)
        self.rsp = self.sock.recv(256)

    def _pack_read_req(self):
        var_name_len = len(self.varname)
        flag = 0
        req_len = var_name_len + 3

        return struct.pack(
            '!HHBH'+str(var_name_len)+'s',
            self.msg_id,
            req_len,
            flag,
            var_name_len,
            self.varname
            )

    def _pack_write_req(self):
        var_name_len = len(self.varname)
        flag = 1
        value_len = len(self.value)
        req_len = var_name_len + 3 + 2 + value_len

        return struct.pack(
            '!HHBH'+str(var_name_len)+'s'+'H'+str(value_len)+'s',
            self.msg_id,
            req_len,
            flag,
            var_name_len,
            self.varname,
            value_len,
            self.value
            )

    def _read_rsp(self, debug=False):
        if self.rsp is None: return None
        var_value_len = len(self.rsp) - struct.calcsize('!HHBH') - 3
        result = struct.unpack('!HHBH'+str(var_value_len)+'s'+'3s', self.rsp)
        _msg_id, body_len, flag, var_value_len, var_value, isok = result
        if debug:
            print '[DEBUG]', result
        if result[-1].endswith('\x01') and _msg_id == self.msg_id:   # todo
            self.msg_id += 1
            return var_value

    def close(self):
        self.sock.close()

IP = '192.168.50.28'

def minus_ov_pro():
    foo = openshowvar(IP, 7000)
    if not foo.can_connect:
        print 'connection error'
        import sys
        sys.exit(-1)
    foo.write('$OV_PRO', str(random.randint(30, 50)))
    print 'start: $OV_PRO minus one, until zero'

    ov = int(current_ov)
    for i in range(ov, 0, -1):
        foo.write('$OV_PRO', str(i))

def run_shell(ip):
    foo = openshowvar(ip, 7001)
    if not foo.can_connect:
        print 'connection error'
        import sys
        sys.exit(-1)
    while True:
        data = raw_input('\nInput var_name [, var_value]\n(`q` for quit): ')
        if data.lower() == 'q':
            foo.close()
            break
        else:
            parts = data.split(',')
            if len(parts) == 1:
                foo.read(data.strip(), True)
            else:
                foo.write(parts[0], parts[1], True)

if __name__ == '__main__':
    run_shell(IP)

<|endoftext|>


<commit_before>"""
Celery tasks for search
"""
import logging

from django.conf import settings
# The imports which are prefixed with _ are mocked to be ignored in MockedESTestCase

from dashboard.models import ProgramEnrollment
from discussions.api import sync_user_to_channels as _sync_user_to_channels
from mail.api import send_automatic_emails as _send_automatic_emails
from micromasters.celery import app
from search.indexing_api import (
    get_default_alias,
    index_program_enrolled_users as _index_program_enrolled_users,
    remove_program_enrolled_user as _remove_program_enrolled_user,
    index_users as _index_users,
    index_percolate_queries as _index_percolate_queries,
    delete_percolate_query as _delete_percolate_query,
    refresh_index as _refresh_index,
)
from search.models import PercolateQuery

log = logging.getLogger(__name__)

def post_indexing_handler(program_enrollment_ids):
    """
    Do the work which happens after a profile is reindexed

    Args:
        program_enrollment_ids (list of int): A list of ProgramEnrollment ids
    """
    feature_sync_user = settings.FEATURES.get('OPEN_DISCUSSIONS_USER_SYNC', False)

    if not feature_sync_user:
        log.error('OPEN_DISCUSSIONS_USER_SYNC is set to False (so disabled) in the settings')

    _refresh_index(get_default_alias())
    for program_enrollment in ProgramEnrollment.objects.filter(id__in=program_enrollment_ids):
        _send_automatic_emails(program_enrollment)

        if feature_sync_user:
            _sync_user_to_channels(program_enrollment.user.id)

@app.task
def remove_program_enrolled_user(program_enrollment_id):
    """
    Remove program-enrolled user from index

    Args:
        program_enrollment_id (int): A ProgramEnrollment to remove from the index
    """
    _remove_program_enrolled_user(program_enrollment_id)

@app.task
def index_program_enrolled_users(program_enrollment_ids):
    """
    Index program enrollments

    Args:
        program_enrollment_ids (list of int): A list of program enrollment ids
    """
    program_enrollments = ProgramEnrollment.objects.filter(id__in=program_enrollment_ids)
    _index_program_enrolled_users(program_enrollments)

    # Send email for profiles that newly fit the search query for an automatic email
    post_indexing_handler(program_enrollment_ids)

@app.task
def index_users(user_ids):
    """
    Index users' ProgramEnrollment documents

    Args:
        user_ids (list of int): Ids of users to update in the Elasticsearch index
    """
    _index_users(user_ids)

    # Send email for profiles that newly fit the search query for an automatic email
    enrollment_ids = list(ProgramEnrollment.objects.filter(user__in=user_ids).values_list("id", flat=True))
    post_indexing_handler(enrollment_ids)

@app.task
def index_percolate_queries(percolate_query_ids):
    """
    Index percolate queries

    Args:
        percolate_query_ids (iterable of int):
            Database ids for PercolateQuery instances to index
    """
    _index_percolate_queries(PercolateQuery.objects.filter(id__in=percolate_query_ids))

@app.task
def delete_percolate_query(percolate_query_id):
    """
    Delete a percolate query in Elasticsearch

    Args:
        percolate_query_id (int): A PercolateQuery id
    """
    _delete_percolate_query(percolate_query_id)
<commit_msg>Changed noisy log.error to log.debug<commit_after>"""
Celery tasks for search
"""
import logging

from django.conf import settings
# The imports which are prefixed with _ are mocked to be ignored in MockedESTestCase

from dashboard.models import ProgramEnrollment
from discussions.api import sync_user_to_channels as _sync_user_to_channels
from mail.api import send_automatic_emails as _send_automatic_emails
from micromasters.celery import app
from search.indexing_api import (
    get_default_alias,
    index_program_enrolled_users as _index_program_enrolled_users,
    remove_program_enrolled_user as _remove_program_enrolled_user,
    index_users as _index_users,
    index_percolate_queries as _index_percolate_queries,
    delete_percolate_query as _delete_percolate_query,
    refresh_index as _refresh_index,
)
from search.models import PercolateQuery

log = logging.getLogger(__name__)

def post_indexing_handler(program_enrollment_ids):
    """
    Do the work which happens after a profile is reindexed

    Args:
        program_enrollment_ids (list of int): A list of ProgramEnrollment ids
    """
    feature_sync_user = settings.FEATURES.get('OPEN_DISCUSSIONS_USER_SYNC', False)

    if not feature_sync_user:
        log.debug('OPEN_DISCUSSIONS_USER_SYNC is set to False (so disabled) in the settings')

    _refresh_index(get_default_alias())
    for program_enrollment in ProgramEnrollment.objects.filter(id__in=program_enrollment_ids):
        _send_automatic_emails(program_enrollment)

        if feature_sync_user:
            _sync_user_to_channels(program_enrollment.user.id)

@app.task
def remove_program_enrolled_user(program_enrollment_id):
    """
    Remove program-enrolled user from index

    Args:
        program_enrollment_id (int): A ProgramEnrollment to remove from the index
    """
    _remove_program_enrolled_user(program_enrollment_id)

@app.task
def index_program_enrolled_users(program_enrollment_ids):
    """
    Index program enrollments

    Args:
        program_enrollment_ids (list of int): A list of program enrollment ids
    """
    program_enrollments = ProgramEnrollment.objects.filter(id__in=program_enrollment_ids)
    _index_program_enrolled_users(program_enrollments)

    # Send email for profiles that newly fit the search query for an automatic email
    post_indexing_handler(program_enrollment_ids)

@app.task
def index_users(user_ids):
    """
    Index users' ProgramEnrollment documents

    Args:
        user_ids (list of int): Ids of users to update in the Elasticsearch index
    """
    _index_users(user_ids)

    # Send email for profiles that newly fit the search query for an automatic email
    enrollment_ids = list(ProgramEnrollment.objects.filter(user__in=user_ids).values_list("id", flat=True))
    post_indexing_handler(enrollment_ids)

@app.task
def index_percolate_queries(percolate_query_ids):
    """
    Index percolate queries

    Args:
        percolate_query_ids (iterable of int):
            Database ids for PercolateQuery instances to index
    """
    _index_percolate_queries(PercolateQuery.objects.filter(id__in=percolate_query_ids))

@app.task
def delete_percolate_query(percolate_query_id):
    """
    Delete a percolate query in Elasticsearch

    Args:
        percolate_query_id (int): A PercolateQuery id
    """
    _delete_percolate_query(percolate_query_id)
<|endoftext|>


<commit_before>"""PyAMG: Algebraic Multigrid Solvers in Python"""
from __future__ import absolute_import

__doc__ += """

Utility tools
-------------

  test        --- Run pyamg unittests (requires nose unittest framework)
  bench       --- Run pyamg benchmarks (requires nose unittest framework)
  __version__ --- pyamg version string

"""

# Warn on old numpy or scipy
import numpy as np
npreq = '1.6'
npmin = [int(j) for j in npreq.split('.')]
npver = [int(j) for j in np.__version__.split('.')]
if npver[0] < npmin[0] or (npver[0] >= npmin[0] and npver[1] < npmin[1]):
    import warnings
    warnings.warn("Numpy %s or above is recommended for this version of"
                  "PyAMG (detected version %s)" % (npmin, npver),
                  UserWarning)

import scipy as sp
spreq = '0.11'
spmin = [int(j) for j in spreq.split('.')]
spver = [int(j) for j in sp.__version__.split('.')]
if spver[0] < spmin[0] or (spver[0] >= spmin[0] and spver[1] < spmin[1]):
    print('hi')
    import warnings
    warnings.warn("SciPy %s or above is recommended for this version of"
                  "PyAMG (detected version %s)" % (spmin, spver),
                  UserWarning)

from .version import git_revision as __git_revision__
from .version import version as __version__

from .multilevel import *
from .classical import ruge_stuben_solver
from .aggregation import smoothed_aggregation_solver, rootnode_solver
from .gallery import demo
from .blackbox import solve, solver, solver_configuration

__all__ = [s for s in dir() if not s.startswith('_')]
__all__ += ['test', '__version__']

from numpy.testing import Tester
test = Tester().test
bench = Tester().bench
<commit_msg>remove random print stmt<commit_after>"""PyAMG: Algebraic Multigrid Solvers in Python"""
from __future__ import absolute_import

__doc__ += """

Utility tools
-------------

  test        --- Run pyamg unittests (requires nose unittest framework)
  bench       --- Run pyamg benchmarks (requires nose unittest framework)
  __version__ --- pyamg version string

"""

# Warn on old numpy or scipy
import numpy as np
npreq = '1.6'
npmin = [int(j) for j in npreq.split('.')]
npver = [int(j) for j in np.__version__.split('.')]
if npver[0] < npmin[0] or (npver[0] >= npmin[0] and npver[1] < npmin[1]):
    import warnings
    warnings.warn("Numpy %s or above is recommended for this version of"
                  "PyAMG (detected version %s)" % (npmin, npver),
                  UserWarning)

import scipy as sp
spreq = '0.11'
spmin = [int(j) for j in spreq.split('.')]
spver = [int(j) for j in sp.__version__.split('.')]
if spver[0] < spmin[0] or (spver[0] >= spmin[0] and spver[1] < spmin[1]):
    import warnings
    warnings.warn("SciPy %s or above is recommended for this version of"
                  "PyAMG (detected version %s)" % (spmin, spver),
                  UserWarning)

from .version import git_revision as __git_revision__
from .version import version as __version__

from .multilevel import *
from .classical import ruge_stuben_solver
from .aggregation import smoothed_aggregation_solver, rootnode_solver
from .gallery import demo
from .blackbox import solve, solver, solver_configuration

__all__ = [s for s in dir() if not s.startswith('_')]
__all__ += ['test', '__version__']

from numpy.testing import Tester
test = Tester().test
bench = Tester().bench
<|endoftext|>


<commit_before>from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied
from django.shortcuts import (
    render,
    redirect,
)
from django.http import HttpResponseBadRequest
from elasticsearch import TransportError

from .index import (
    create_or_update_index,
    delete_all_indices,
    delete_single_index,
    get_elasticsearch,
    get_mappings,
    put_questionnaire_data,
)
from .search import simple_search
from .utils import get_alias
from configuration.cache import get_configuration
from configuration.models import Configuration
from questionnaire.models import Questionnaire
from questionnaire.utils import get_list_values

es = get_elasticsearch()

@login_required
def admin(request, log=''):
    """
    The search admin overview. Allow superusers to update the indices
    and execute other administrative tasks.

    Args:
        ``request`` (django.http.HttpRequest): The request object.

    Returns:
        ``HttpResponse``. A rendered Http Response.
    """
    if request.user.is_superuser is not True:
        raise PermissionDenied()

    configurations = []
    for active_configuration in Configuration.objects.filter(active=True):
        db_count = Questionnaire.objects.filter(
            configurations__code=active_configuration.code).count()
        try:
            index_count = es.count(
                index=get_alias([active_configuration.code])).get('count')
        except TransportError:
            index_count = None
        config_entry = {
            'object': active_configuration,
            'db_count': db_count,
            'index_count': index_count,
        }
        configurations.append(config_entry)

    return render(request, 'search/admin.html', {
        'configurations': configurations,
    })

@login_required
def index(request, configuration):
    """
    Create or update the mapping of an index.

    Args:
        ``request`` (django.http.HttpRequest): The request object.

        ``configuration`` (str): The code of the Questionnaire
        configuration.

    Returns:
        ``HttpResponse``. A rendered Http Response (redirected to the
        search admin home page).
    """
    if request.user.is_superuser is not True:
        raise PermissionDenied()

    questionnaire_configuration = get_configuration(configuration)
    if questionnaire_configuration.get_configuration_errors() is not None:
        return HttpResponseBadRequest(
            questionnaire_configuration.configuration_error)

    mappings = get_mappings(questionnaire_configuration)

    success, logs, error_msg = create_or_update_index(configuration, mappings)
    if success is not True:
        messages.error(request, 'The following error(s) occured: {}'.format(
            error_msg))
    else:
        messages.success(
            request, 'Index "{}" was created or updated.'.format(
                configuration))

    return redirect('search:admin')

@login_required
def update(request, configuration):
    """
    Add the questionnaires of a configuration to the index.

    Args:
        ``request`` (django.http.HttpRequest): The request object.

        ``configuration`` (str): The code of the Questionnaire
        configuration.

    Returns:
        ``HttpResponse``. A rendered Http Response (redirected to the
        search admin home page).
    """
    if request.user.is_superuser is not True:
        raise PermissionDenied()

    questionnaire_configuration = get_configuration(configuration)
    if questionnaire_configuration.get_configuration_errors() is not None:
        return HttpResponseBadRequest(
            questionnaire_configuration.configuration_error)

    processed, errors = put_questionnaire_data(
        configuration,
        Questionnaire.objects.filter(configurations__code=configuration))

    if len(errors) > 0:
        messages.error(request, 'The following error(s) occured: {}'.format(
            ', '.join(errors)))
    else:
        messages.success(
            request, '{} Questionnaires of configuration "{}" successfully '
            'indexed.'.format(processed, configuration))

    return redirect('search:admin')

@login_required
def delete_all(request):
    """
    Delete all the indices.

    Args:
        ``request`` (django.http.HttpRequest): The request object.

    Returns:
        ``HttpResponse``. A rendered Http Response (redirected to the
        search admin home page).
    """
    if request.user.is_superuser is not True:
        raise PermissionDenied()

    success, error_msg = delete_all_indices()
    if success is not True:
        messages.error(request, 'The following error(s) occured: {}'.format(
            error_msg))
    else:
        messages.success(request, 'All indices successfully deleted.')

    return redirect('search:admin')

@login_required
def delete_one(request, configuration):
    """
    Delete a single index.

    Args:
        ``request`` (django.http.HttpRequest): The request object.

        ``configuration`` (str): The code of the Questionnaire
        configuration.

    Returns:
        ``HttpResponse``. A rendered Http Response (redirected to the
        search admin home page).
    """
    if request.user.is_superuser is not True:
        raise PermissionDenied()

    success, error_msg = delete_single_index(configuration)
    if success is not True:
        messages.error(request, 'The following error(s) occured: {}'.format(
            error_msg))
    else:
        messages.success(request, 'Index "{}" successfully deleted.'.format(
            configuration))

    return redirect('search:admin')

def search(request):
    """
    Do a full text search.

    Args:
        ``request`` (django.http.HttpRequest): The request object.
    """
    search = simple_search(request.GET.get('q', ''))
    hits = search.get('hits', {}).get('hits', [])

    list_values = get_list_values(configuration_code=None, es_hits=hits)

    return render(request, 'sample/questionnaire/list.html', {
        'list_values': list_values,
    })
<commit_msg>Update ES adds only public Questionnaires<commit_after>from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied
from django.shortcuts import (
    render,
    redirect,
)
from django.http import HttpResponseBadRequest
from elasticsearch import TransportError

from .index import (
    create_or_update_index,
    delete_all_indices,
    delete_single_index,
    get_elasticsearch,
    get_mappings,
    put_questionnaire_data,
)
from .search import simple_search
from .utils import get_alias
from configuration.cache import get_configuration
from configuration.models import Configuration
from questionnaire.models import Questionnaire
from questionnaire.utils import get_list_values

es = get_elasticsearch()

@login_required
def admin(request, log=''):
    """
    The search admin overview. Allow superusers to update the indices
    and execute other administrative tasks.

    Args:
        ``request`` (django.http.HttpRequest): The request object.

    Returns:
        ``HttpResponse``. A rendered Http Response.
    """
    if request.user.is_superuser is not True:
        raise PermissionDenied()

    configurations = []
    for active_configuration in Configuration.objects.filter(active=True):
        db_count = Questionnaire.objects.filter(
            configurations__code=active_configuration.code, status=3).count()
        try:
            index_count = es.count(
                index=get_alias([active_configuration.code])).get('count')
        except TransportError:
            index_count = None
        config_entry = {
            'object': active_configuration,
            'db_count': db_count,
            'index_count': index_count,
        }
        configurations.append(config_entry)

    return render(request, 'search/admin.html', {
        'configurations': configurations,
    })

@login_required
def index(request, configuration):
    """
    Create or update the mapping of an index.

    Args:
        ``request`` (django.http.HttpRequest): The request object.

        ``configuration`` (str): The code of the Questionnaire
        configuration.

    Returns:
        ``HttpResponse``. A rendered Http Response (redirected to the
        search admin home page).
    """
    if request.user.is_superuser is not True:
        raise PermissionDenied()

    questionnaire_configuration = get_configuration(configuration)
    if questionnaire_configuration.get_configuration_errors() is not None:
        return HttpResponseBadRequest(
            questionnaire_configuration.configuration_error)

    mappings = get_mappings(questionnaire_configuration)

    success, logs, error_msg = create_or_update_index(configuration, mappings)
    if success is not True:
        messages.error(request, 'The following error(s) occured: {}'.format(
            error_msg))
    else:
        messages.success(
            request, 'Index "{}" was created or updated.'.format(
                configuration))

    return redirect('search:admin')

@login_required
def update(request, configuration):
    """
    Add the questionnaires of a configuration to the index.

    Args:
        ``request`` (django.http.HttpRequest): The request object.

        ``configuration`` (str): The code of the Questionnaire
        configuration.

    Returns:
        ``HttpResponse``. A rendered Http Response (redirected to the
        search admin home page).
    """
    if request.user.is_superuser is not True:
        raise PermissionDenied()

    questionnaire_configuration = get_configuration(configuration)
    if questionnaire_configuration.get_configuration_errors() is not None:
        return HttpResponseBadRequest(
            questionnaire_configuration.configuration_error)

    processed, errors = put_questionnaire_data(
        configuration,
        Questionnaire.objects.filter(
            configurations__code=configuration, status=3))

    if len(errors) > 0:
        messages.error(request, 'The following error(s) occured: {}'.format(
            ', '.join(errors)))
    else:
        messages.success(
            request, '{} Questionnaires of configuration "{}" successfully '
            'indexed.'.format(processed, configuration))

    return redirect('search:admin')

@login_required
def delete_all(request):
    """
    Delete all the indices.

    Args:
        ``request`` (django.http.HttpRequest): The request object.

    Returns:
        ``HttpResponse``. A rendered Http Response (redirected to the
        search admin home page).
    """
    if request.user.is_superuser is not True:
        raise PermissionDenied()

    success, error_msg = delete_all_indices()
    if success is not True:
        messages.error(request, 'The following error(s) occured: {}'.format(
            error_msg))
    else:
        messages.success(request, 'All indices successfully deleted.')

    return redirect('search:admin')

@login_required
def delete_one(request, configuration):
    """
    Delete a single index.

    Args:
        ``request`` (django.http.HttpRequest): The request object.

        ``configuration`` (str): The code of the Questionnaire
        configuration.

    Returns:
        ``HttpResponse``. A rendered Http Response (redirected to the
        search admin home page).
    """
    if request.user.is_superuser is not True:
        raise PermissionDenied()

    success, error_msg = delete_single_index(configuration)
    if success is not True:
        messages.error(request, 'The following error(s) occured: {}'.format(
            error_msg))
    else:
        messages.success(request, 'Index "{}" successfully deleted.'.format(
            configuration))

    return redirect('search:admin')

def search(request):
    """
    Do a full text search.

    Args:
        ``request`` (django.http.HttpRequest): The request object.
    """
    search = simple_search(request.GET.get('q', ''))
    hits = search.get('hits', {}).get('hits', [])

    list_values = get_list_values(configuration_code=None, es_hits=hits)

    return render(request, 'sample/questionnaire/list.html', {
        'list_values': list_values,
    })
<|endoftext|>


<commit_before>'''
searx is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

searx is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with searx. If not, see < http://www.gnu.org/licenses/ >.

(C) 2013- by Adam Tauber, <asciimoo@gmail.com>
'''

import gc
import sys
import threading
from time import time
from uuid import uuid4
from flask_babel import gettext
import requests.exceptions
import searx.poolrequests as requests_lib
from searx.engines import (
    categories, engines, settings
)
from searx.answerers import ask
from searx.utils import gen_useragent
from searx.query import RawTextQuery, SearchQuery, VALID_LANGUAGE_CODE
from searx.results import ResultContainer
from searx import logger
from searx.plugins import plugins
from searx.exceptions import SearxParameterException

try:
    from thread import start_new_thread
except:
    from _thread import start_new_thread

if sys.version_info[0] == 3:
    unicode = str

logger = logger.getChild('search')

number_of_searches = 0

def send_http_request(engine, request_params):
    # create dictionary which contain all
    # informations about the request
    request_args = dict(
        headers=request_params['headers'],
        cookies=request_params['cookies'],
        verify=request_params['verify']
    )

    # specific type of request (GET or POST)
    if request_params['method'] == 'GET':
        req = requests_lib.get
    else:
        req = requests_lib.post
        request_args['data'] = request_params['data']

    # send the request
    return req(request_params['url'], **request_args)

def search_one_request(engine, query, request_params):
    # update request parameters dependent on
    # search-engine (contained in engines folder)
    engine.request(query, request_params)

    # ignoring empty urls
    if request_params['url'] is None:
        return []

    if not request_params['url']:
        return []

    # send request
    response = send_http_request(engine, request_params)

    # parse the response
    response.search_params = request_params
    return engine.response(response)

def search_one_request_safe(engine_name, query, request_params, result_container, start_time, timeout_limit):
    # set timeout for all HTTP requests
    requests_lib.set_timeout_for_thread(timeout_limit, start_time=start_time)
    # reset the HTTP total time
    requests_lib.reset_time_for_thread()

    #
    engine = engines[engine_name]

    # suppose everything will be alright
    requests_exception = False

    try:
        # send requests and parse the results
        search_results = search_one_request(engine, query, request_params)

        # add results
        result_container.extend(engine_name, search_results)

        # update engine time when there is no exception
        with threading.RLock():
            engine.stats['engine_time'] += time() - start_time
            engine.stats['engine_time_count'] += 1
            # update stats with the total HTTP time
            engine.stats['page_load_time'] += requests_lib.get_time_for_thread()
            engine.stats['page_load_count'] += 1

    except Exception as e:
        search_duration = time() - start_time

        with threading.RLock():
            engine.stats['errors'] += 1

        if (issubclass(e.__class__, requests.exceptions.Timeout)):
            result_container.add_unresponsive_engine((engine_name, gettext('timeout')))
            # requests timeout (connect or read)
            logger.error("engine {0} : HTTP requests timeout"
                         "(search duration : {1} s, timeout: {2} s) : {3}"
                         .format(engine_name, search_duration, timeout_limit, e.__class__.__name__))
            requests_exception = True
        elif (issubclass(e.__class__, requests.exceptions.RequestException)):
            result_container.add_unresponsive_engine((engine_name, gettext('request exception')))
            # other requests exception
            logger.exception("engine {0} : requests exception"
                             "(search duration : {1} s, timeout: {2} s) : {3}"
                             .format(engine_name, search_duration, timeout_limit, e))
            requests_exception = True
        else:
            result_container.add_unresponsive_engine((
                engine_name,
                u'{0}: {1}'.format(gettext('unexpected crash'), e),
            ))
            # others errors
            logger.exception('engine {0} : exception : {1}'.format(engine_name, e))

    # suspend or not the engine if there are HTTP errors
    with threading.RLock():
        if requests_exception:
            # update continuous_errors / suspend_end_time
            engine.continuous_errors += 1
            engine.suspend_end_time = time() + min(settings['search']['max_ban_time_on_fail'],
                                                   engine.continuous_errors*settings['search']['ban_time_on_fail'])
        else:
            # no HTTP error (perhaps an engine error)
            # anyway, reset the suspend variables
            engine.continuous_errors = 0
            engine.suspend_end_time = 0

def search_multiple_requests(requests, result_container, start_time, timeout_limit):
    search_id = uuid4().__str__()

    for engine_name, query, request_params in requests:
        th = threading.Thread(
            target=search_one_request_safe,
            args=(engine_name, query, request_params, result_container, start_time, timeout_limit),
            name=search_id,
        )
        th._engine_name = engine_name
        th.start()

    for th in threading.enumerate():
        if th.name == search_id:
            remaining_time = max(0.0, timeout_limit - (time() - start_time))
            th.join(remaining_time)
            if th.isAlive():
                result_container.add_unresponsive_engine((th._engine_name, gettext('timeout')))
                logger.warning('engine timeout: {0}'.format(th._engine_name))

# get default reqest parameter
def default_request_params():
    return {
        'method': 'GET',
        'headers': {},
        'data': {},
        'url': '',
        'cookies': {},
        'verify': True
    }

def get_search_query_from_webapp(preferences, form):
    # no text for the query ?
    if not form.get('q'):
        raise SearxParameterException('q', '')

    # set blocked engines
    disabled_engines = preferences.engines.get_disabled()

    # parse query, if tags are set, which change
    # the serch engine or search-language
    raw_text_query = RawTextQuery(form['q'], disabled_engines)
    raw_text_query.parse_query()

    # set query
    query = raw_text_query.getSearchQuery()

    # get and check page number
    pageno_param = form.get('pageno', '1')
    if not pageno_param.isdigit() or int(pageno_param) < 1:
        raise SearxParameterException('pageno', pageno_param)
    query_pageno = int(pageno_param)

    # get language
    # set specific language if set on request, query or preferences
    # TODO support search with multible languages
    if len(raw_text_query.languages):
        query_lang = raw_text_query.languages[-1]
    elif 'language' in form:
        query_lang = form.get('language')
    else:
        query_lang = preferences.get_value('language')

    # provides backwards compatibility for requests using old language default
    if query_lang == 'all':
        query_lang = settings['search']['language']

    # check language
    if not VALID_LANGUAGE_CODE.match(query_lang):
        raise SearxParameterException('language', query_lang)

    # get safesearch
    if 'safesearch' in form:
        query_safesearch = form.get('safesearch')
        # first check safesearch
        if not query_safesearch.isdigit():
            raise SearxParameterException('safesearch', query_safesearch)
        query_safesearch = int(query_safesearch)
    else:
        query_safesearch = preferences.get_value('safesearch')

    # safesearch : second check
    if query_safesearch < 0 or query_safesearch > 2:
        raise SearxParameterException('safesearch', query_safesearch)

    # get time_range
    query_time_range = form.get('time_range')

    # check time_range
    if query_time_range not in ('None', None, '', 'day', 'week', 'month', 'year'):
        raise SearxParameterException('time_range', query_time_range)

    # query_engines
    query_engines = raw_text_query.engines

    # query_categories
    query_categories = []

    # if engines are calculated from query,
    # set categories by using that informations
    if query_engines and raw_text_query.specific:
        additional_categories = set()
        for engine in query_engines:
            if 'from_bang' in engine and engine['from_bang']:
                additional_categories.add('none')
            else:
                additional_categories.add(engine['category'])
        query_categories = list(additional_categories)

    # otherwise, using defined categories to
    # calculate which engines should be used
    else:
        # set categories/engines
        load_default_categories = True
        for pd_name, pd in form.items():
            if pd_name == 'categories':
                query_categories.extend(categ for categ in map(unicode.strip, pd.split(',')) if categ in categories)
            elif pd_name == 'engines':
                pd_engines = [{'category': engines[engine].categories[0],
                               'name': engine}
                              for engine in map(unicode.strip, pd.split(',')) if engine in engines]
                if pd_engines:
                    query_engines.extend(pd_engines)
                    load_default_categories = False
            elif pd_name.startswith('category_'):
                category = pd_name[9:]

                # if category is not found in list, skip
                if category not in categories:
                    continue

                if pd != 'off':
                    # add category to list
                    query_categories.append(category)
                elif category in query_categories:
                    # remove category from list if property is set to 'off'
                    query_categories.remove(category)

        if not load_default_categories:
            if not query_categories:
                query_categories = list(set(engine['category']
                                            for engine in query_engines))
        else:
            # if no category is specified for this search,
            # using user-defined default-configuration which
            # (is stored in cookie)
            if not query_categories:
                cookie_categories = preferences.get_value('categories')
                for ccateg in cookie_categories:
                    if ccateg in categories:
                        query_categories.append(ccateg)

            # if still no category is specified, using general
            # as default-category
            if not query_categories:
                query_categories = ['general']

            # using all engines for that search, which are
            # declared under the specific categories
            for categ in query_categories:
                query_engines.extend({'category': categ,
                                      'name': engine.name}
                                     for engine in categories[categ]
                                     if (engine.name, categ) not in disabled_engines)

    return SearchQuery(query, query_engines, query_categories,
                       query_lang, query_safesearch, query_pageno, query_time_range)

class Search(object):

    """Search information container"""

    def __init__(self, search_query):
        # init vars
        super(Search, self).__init__()
        self.search_query = search_query
        self.result_container = ResultContainer()

    # do search-request
    def search(self):
        global number_of_searches

        # start time
        start_time = time()

        # answeres ?
        answerers_results = ask(self.search_query)

        if answerers_results:
            for results in answerers_results:
                self.result_container.extend('answer', results)
            return self.result_container

        # init vars
        requests = []

        # increase number of searches
        number_of_searches += 1

        # set default useragent
        # user_agent = request.headers.get('User-Agent', '')
        user_agent = gen_useragent()

        search_query = self.search_query

        # max of all selected engine timeout
        timeout_limit = 0

        # start search-reqest for all selected engines
        for selected_engine in search_query.engines:
            if selected_engine['name'] not in engines:
                continue

            engine = engines[selected_engine['name']]

            # skip suspended engines
            if engine.suspend_end_time >= time():
                logger.debug('Engine currently suspended: %s', selected_engine['name'])
                continue

            # if paging is not supported, skip
            if search_query.pageno > 1 and not engine.paging:
                continue

            # if time_range is not supported, skip
            if search_query.time_range and not engine.time_range_support:
                continue

            # set default request parameters
            request_params = default_request_params()
            request_params['headers']['User-Agent'] = user_agent
            request_params['category'] = selected_engine['category']
            request_params['pageno'] = search_query.pageno

            if hasattr(engine, 'language') and engine.language:
                request_params['language'] = engine.language
            else:
                request_params['language'] = search_query.lang

            # 0 = None, 1 = Moderate, 2 = Strict
            request_params['safesearch'] = search_query.safesearch
            request_params['time_range'] = search_query.time_range

            # append request to list
            requests.append((selected_engine['name'], search_query.query, request_params))

            # update timeout_limit
            timeout_limit = max(timeout_limit, engine.timeout)

        if requests:
            # send all search-request
            search_multiple_requests(requests, self.result_container, start_time, timeout_limit)
            start_new_thread(gc.collect, tuple())

        # return results, suggestions, answers and infoboxes
        return self.result_container

class SearchWithPlugins(Search):

    """Similar to the Search class but call the plugins."""

    def __init__(self, search_query, ordered_plugin_list, request):
        super(SearchWithPlugins, self).__init__(search_query)
        self.ordered_plugin_list = ordered_plugin_list
        self.request = request

    def search(self):
        if plugins.call(self.ordered_plugin_list, 'pre_search', self.request, self):
            super(SearchWithPlugins, self).search()

        plugins.call(self.ordered_plugin_list, 'post_search', self.request, self)

        results = self.result_container.get_ordered_results()

        for result in results:
            plugins.call(self.ordered_plugin_list, 'on_result', self.request, self, result)

        return self.result_container
<commit_msg>[fix] pep8<commit_after>'''
searx is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

searx is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with searx. If not, see < http://www.gnu.org/licenses/ >.

(C) 2013- by Adam Tauber, <asciimoo@gmail.com>
'''

import gc
import sys
import threading
from time import time
from uuid import uuid4
from flask_babel import gettext
import requests.exceptions
import searx.poolrequests as requests_lib
from searx.engines import (
    categories, engines, settings
)
from searx.answerers import ask
from searx.utils import gen_useragent
from searx.query import RawTextQuery, SearchQuery, VALID_LANGUAGE_CODE
from searx.results import ResultContainer
from searx import logger
from searx.plugins import plugins
from searx.exceptions import SearxParameterException

try:
    from thread import start_new_thread
except:
    from _thread import start_new_thread

if sys.version_info[0] == 3:
    unicode = str

logger = logger.getChild('search')

number_of_searches = 0

def send_http_request(engine, request_params):
    # create dictionary which contain all
    # informations about the request
    request_args = dict(
        headers=request_params['headers'],
        cookies=request_params['cookies'],
        verify=request_params['verify']
    )

    # specific type of request (GET or POST)
    if request_params['method'] == 'GET':
        req = requests_lib.get
    else:
        req = requests_lib.post
        request_args['data'] = request_params['data']

    # send the request
    return req(request_params['url'], **request_args)

def search_one_request(engine, query, request_params):
    # update request parameters dependent on
    # search-engine (contained in engines folder)
    engine.request(query, request_params)

    # ignoring empty urls
    if request_params['url'] is None:
        return []

    if not request_params['url']:
        return []

    # send request
    response = send_http_request(engine, request_params)

    # parse the response
    response.search_params = request_params
    return engine.response(response)

def search_one_request_safe(engine_name, query, request_params, result_container, start_time, timeout_limit):
    # set timeout for all HTTP requests
    requests_lib.set_timeout_for_thread(timeout_limit, start_time=start_time)
    # reset the HTTP total time
    requests_lib.reset_time_for_thread()

    #
    engine = engines[engine_name]

    # suppose everything will be alright
    requests_exception = False

    try:
        # send requests and parse the results
        search_results = search_one_request(engine, query, request_params)

        # add results
        result_container.extend(engine_name, search_results)

        # update engine time when there is no exception
        with threading.RLock():
            engine.stats['engine_time'] += time() - start_time
            engine.stats['engine_time_count'] += 1
            # update stats with the total HTTP time
            engine.stats['page_load_time'] += requests_lib.get_time_for_thread()
            engine.stats['page_load_count'] += 1

    except Exception as e:
        search_duration = time() - start_time

        with threading.RLock():
            engine.stats['errors'] += 1

        if (issubclass(e.__class__, requests.exceptions.Timeout)):
            result_container.add_unresponsive_engine((engine_name, gettext('timeout')))
            # requests timeout (connect or read)
            logger.error("engine {0} : HTTP requests timeout"
                         "(search duration : {1} s, timeout: {2} s) : {3}"
                         .format(engine_name, search_duration, timeout_limit, e.__class__.__name__))
            requests_exception = True
        elif (issubclass(e.__class__, requests.exceptions.RequestException)):
            result_container.add_unresponsive_engine((engine_name, gettext('request exception')))
            # other requests exception
            logger.exception("engine {0} : requests exception"
                             "(search duration : {1} s, timeout: {2} s) : {3}"
                             .format(engine_name, search_duration, timeout_limit, e))
            requests_exception = True
        else:
            result_container.add_unresponsive_engine((
                engine_name,
                u'{0}: {1}'.format(gettext('unexpected crash'), e),
            ))
            # others errors
            logger.exception('engine {0} : exception : {1}'.format(engine_name, e))

    # suspend or not the engine if there are HTTP errors
    with threading.RLock():
        if requests_exception:
            # update continuous_errors / suspend_end_time
            engine.continuous_errors += 1
            engine.suspend_end_time = time() + min(settings['search']['max_ban_time_on_fail'],
                                                   engine.continuous_errors * settings['search']['ban_time_on_fail'])
        else:
            # no HTTP error (perhaps an engine error)
            # anyway, reset the suspend variables
            engine.continuous_errors = 0
            engine.suspend_end_time = 0

def search_multiple_requests(requests, result_container, start_time, timeout_limit):
    search_id = uuid4().__str__()

    for engine_name, query, request_params in requests:
        th = threading.Thread(
            target=search_one_request_safe,
            args=(engine_name, query, request_params, result_container, start_time, timeout_limit),
            name=search_id,
        )
        th._engine_name = engine_name
        th.start()

    for th in threading.enumerate():
        if th.name == search_id:
            remaining_time = max(0.0, timeout_limit - (time() - start_time))
            th.join(remaining_time)
            if th.isAlive():
                result_container.add_unresponsive_engine((th._engine_name, gettext('timeout')))
                logger.warning('engine timeout: {0}'.format(th._engine_name))

# get default reqest parameter
def default_request_params():
    return {
        'method': 'GET',
        'headers': {},
        'data': {},
        'url': '',
        'cookies': {},
        'verify': True
    }

def get_search_query_from_webapp(preferences, form):
    # no text for the query ?
    if not form.get('q'):
        raise SearxParameterException('q', '')

    # set blocked engines
    disabled_engines = preferences.engines.get_disabled()

    # parse query, if tags are set, which change
    # the serch engine or search-language
    raw_text_query = RawTextQuery(form['q'], disabled_engines)
    raw_text_query.parse_query()

    # set query
    query = raw_text_query.getSearchQuery()

    # get and check page number
    pageno_param = form.get('pageno', '1')
    if not pageno_param.isdigit() or int(pageno_param) < 1:
        raise SearxParameterException('pageno', pageno_param)
    query_pageno = int(pageno_param)

    # get language
    # set specific language if set on request, query or preferences
    # TODO support search with multible languages
    if len(raw_text_query.languages):
        query_lang = raw_text_query.languages[-1]
    elif 'language' in form:
        query_lang = form.get('language')
    else:
        query_lang = preferences.get_value('language')

    # provides backwards compatibility for requests using old language default
    if query_lang == 'all':
        query_lang = settings['search']['language']

    # check language
    if not VALID_LANGUAGE_CODE.match(query_lang):
        raise SearxParameterException('language', query_lang)

    # get safesearch
    if 'safesearch' in form:
        query_safesearch = form.get('safesearch')
        # first check safesearch
        if not query_safesearch.isdigit():
            raise SearxParameterException('safesearch', query_safesearch)
        query_safesearch = int(query_safesearch)
    else:
        query_safesearch = preferences.get_value('safesearch')

    # safesearch : second check
    if query_safesearch < 0 or query_safesearch > 2:
        raise SearxParameterException('safesearch', query_safesearch)

    # get time_range
    query_time_range = form.get('time_range')

    # check time_range
    if query_time_range not in ('None', None, '', 'day', 'week', 'month', 'year'):
        raise SearxParameterException('time_range', query_time_range)

    # query_engines
    query_engines = raw_text_query.engines

    # query_categories
    query_categories = []

    # if engines are calculated from query,
    # set categories by using that informations
    if query_engines and raw_text_query.specific:
        additional_categories = set()
        for engine in query_engines:
            if 'from_bang' in engine and engine['from_bang']:
                additional_categories.add('none')
            else:
                additional_categories.add(engine['category'])
        query_categories = list(additional_categories)

    # otherwise, using defined categories to
    # calculate which engines should be used
    else:
        # set categories/engines
        load_default_categories = True
        for pd_name, pd in form.items():
            if pd_name == 'categories':
                query_categories.extend(categ for categ in map(unicode.strip, pd.split(',')) if categ in categories)
            elif pd_name == 'engines':
                pd_engines = [{'category': engines[engine].categories[0],
                               'name': engine}
                              for engine in map(unicode.strip, pd.split(',')) if engine in engines]
                if pd_engines:
                    query_engines.extend(pd_engines)
                    load_default_categories = False
            elif pd_name.startswith('category_'):
                category = pd_name[9:]

                # if category is not found in list, skip
                if category not in categories:
                    continue

                if pd != 'off':
                    # add category to list
                    query_categories.append(category)
                elif category in query_categories:
                    # remove category from list if property is set to 'off'
                    query_categories.remove(category)

        if not load_default_categories:
            if not query_categories:
                query_categories = list(set(engine['category']
                                            for engine in query_engines))
        else:
            # if no category is specified for this search,
            # using user-defined default-configuration which
            # (is stored in cookie)
            if not query_categories:
                cookie_categories = preferences.get_value('categories')
                for ccateg in cookie_categories:
                    if ccateg in categories:
                        query_categories.append(ccateg)

            # if still no category is specified, using general
            # as default-category
            if not query_categories:
                query_categories = ['general']

            # using all engines for that search, which are
            # declared under the specific categories
            for categ in query_categories:
                query_engines.extend({'category': categ,
                                      'name': engine.name}
                                     for engine in categories[categ]
                                     if (engine.name, categ) not in disabled_engines)

    return SearchQuery(query, query_engines, query_categories,
                       query_lang, query_safesearch, query_pageno, query_time_range)

class Search(object):

    """Search information container"""

    def __init__(self, search_query):
        # init vars
        super(Search, self).__init__()
        self.search_query = search_query
        self.result_container = ResultContainer()

    # do search-request
    def search(self):
        global number_of_searches

        # start time
        start_time = time()

        # answeres ?
        answerers_results = ask(self.search_query)

        if answerers_results:
            for results in answerers_results:
                self.result_container.extend('answer', results)
            return self.result_container

        # init vars
        requests = []

        # increase number of searches
        number_of_searches += 1

        # set default useragent
        # user_agent = request.headers.get('User-Agent', '')
        user_agent = gen_useragent()

        search_query = self.search_query

        # max of all selected engine timeout
        timeout_limit = 0

        # start search-reqest for all selected engines
        for selected_engine in search_query.engines:
            if selected_engine['name'] not in engines:
                continue

            engine = engines[selected_engine['name']]

            # skip suspended engines
            if engine.suspend_end_time >= time():
                logger.debug('Engine currently suspended: %s', selected_engine['name'])
                continue

            # if paging is not supported, skip
            if search_query.pageno > 1 and not engine.paging:
                continue

            # if time_range is not supported, skip
            if search_query.time_range and not engine.time_range_support:
                continue

            # set default request parameters
            request_params = default_request_params()
            request_params['headers']['User-Agent'] = user_agent
            request_params['category'] = selected_engine['category']
            request_params['pageno'] = search_query.pageno

            if hasattr(engine, 'language') and engine.language:
                request_params['language'] = engine.language
            else:
                request_params['language'] = search_query.lang

            # 0 = None, 1 = Moderate, 2 = Strict
            request_params['safesearch'] = search_query.safesearch
            request_params['time_range'] = search_query.time_range

            # append request to list
            requests.append((selected_engine['name'], search_query.query, request_params))

            # update timeout_limit
            timeout_limit = max(timeout_limit, engine.timeout)

        if requests:
            # send all search-request
            search_multiple_requests(requests, self.result_container, start_time, timeout_limit)
            start_new_thread(gc.collect, tuple())

        # return results, suggestions, answers and infoboxes
        return self.result_container

class SearchWithPlugins(Search):

    """Similar to the Search class but call the plugins."""

    def __init__(self, search_query, ordered_plugin_list, request):
        super(SearchWithPlugins, self).__init__(search_query)
        self.ordered_plugin_list = ordered_plugin_list
        self.request = request

    def search(self):
        if plugins.call(self.ordered_plugin_list, 'pre_search', self.request, self):
            super(SearchWithPlugins, self).search()

        plugins.call(self.ordered_plugin_list, 'post_search', self.request, self)

        results = self.result_container.get_ordered_results()

        for result in results:
            plugins.call(self.ordered_plugin_list, 'on_result', self.request, self, result)

        return self.result_container
<|endoftext|>