Exemplo n.º 1
0
 def get_context_data(self, **kwargs):
     session_config_summaries = [
         info_about_session_config(session_config)
         for session_config in SESSION_CONFIGS_DICT.values()
     ]
     kwargs.update({'session_config_summaries': session_config_summaries})
     return super(CreateSession, self).get_context_data(**kwargs)
Exemplo n.º 2
0
    def get_context_data(self, **kwargs):
        title = getattr(settings, 'DEMO_PAGE_TITLE', 'Demo')
        intro_html = (
            getattr(settings, 'DEMO_PAGE_INTRO_HTML', '') or
            getattr(settings, 'DEMO_PAGE_INTRO_TEXT', ''))
        context = super(DemoIndex, self).get_context_data(**kwargs)

        session_info = []
        for session_config in SESSION_CONFIGS_DICT.values():
            session_info.append(
                {
                    'name': session_config['name'],
                    'display_name': session_config['display_name'],
                    'url': reverse(
                        'CreateDemoSession', args=(session_config['name'],)
                    ),
                    'num_demo_participants': session_config[
                        'num_demo_participants'
                    ]
                }
            )

        context.update({
            'session_info': session_info,
            'title': title,
            'intro_html': intro_html,
            'is_debug': settings.DEBUG,
        })
        return context
Exemplo n.º 3
0
    def vars_for_template(self):
        title = getattr(settings, 'DEMO_PAGE_TITLE', 'Demo')
        intro_html = getattr(settings, 'DEMO_PAGE_INTRO_HTML', '')
        session_info = []
        for session_config in SESSION_CONFIGS_DICT.values():
            session_info.append({
                'name':
                session_config['name'],
                'display_name':
                session_config['display_name'],
                'url':
                self.request.url_for('CreateDemoSession',
                                     config_name=session_config['name']),
                'num_demo_participants':
                session_config['num_demo_participants'],
            })

        if os.environ.get('OTREEHUB_PUB'):
            otreehub_app_name = os.environ.get('OTREEHUB_APP_NAME')
            otreehub_url = f'https://www.otreehub.com/projects/{otreehub_app_name}/'
        else:
            otreehub_url = ''

        return dict(
            session_info=session_info,
            title=title,
            intro_html=intro_html,
            is_debug=settings.DEBUG,
            otreehub_url=otreehub_url,
        )
Exemplo n.º 4
0
    def get_context_data(self, **kwargs):
        title = getattr(settings, 'DEMO_PAGE_TITLE', 'Demo')
        intro_html = getattr(settings, 'DEMO_PAGE_INTRO_HTML', '') or getattr(
            settings, 'DEMO_PAGE_INTRO_TEXT', '')

        session_info = []
        for session_config in SESSION_CONFIGS_DICT.values():
            session_info.append({
                'name':
                session_config['name'],
                'display_name':
                session_config['display_name'],
                'url':
                reverse('CreateDemoSession', args=(session_config['name'], )),
                'num_demo_participants':
                session_config['num_demo_participants'],
            })

        if os.environ.get('OTREEHUB_PUB'):
            otreehub_app_name = os.environ.get('OTREEHUB_APP_NAME')
            otreehub_url = f'https://www.otreehub.com/projects/{otreehub_app_name}/'
        else:
            otreehub_url = ''

        return super().get_context_data(
            session_info=session_info,
            title=title,
            intro_html=intro_html,
            is_debug=settings.DEBUG,
            otreehub_url=otreehub_url,
            **kwargs,
        )
Exemplo n.º 5
0
    def get_context_data(self, **kwargs):
        intro_text = settings.DEMO_PAGE_INTRO_TEXT
        context = super(DemoIndex, self).get_context_data(**kwargs)

        session_info = []
        for session_config in SESSION_CONFIGS_DICT.values():
            session_info.append(
                {
                    'name': session_config['name'],
                    'display_name': session_config['display_name'],
                    'url': reverse(
                        'CreateDemoSession', args=(session_config['name'],)
                    ),
                    'num_demo_participants': session_config[
                        'num_demo_participants'
                    ]
                }
            )

        context.update({
            'session_info': session_info,
            'intro_text': intro_text,
            'is_debug': settings.DEBUG,
        })
        return context
Exemplo n.º 6
0
    def get_context_data(self, **kwargs):
        intro_text = settings.DEMO_PAGE_INTRO_TEXT
        context = super(DemoIndex, self).get_context_data(**kwargs)

        session_info = []
        for session_config in SESSION_CONFIGS_DICT.values():
            session_info.append(
                {
                    'name': session_config['name'],
                    'display_name': session_config['display_name'],
                    'url': reverse(
                        'create_demo_session', args=(session_config['name'],)
                    ),
                    'num_demo_participants': session_config[
                        'num_demo_participants'
                    ]
                }
            )

        context.update({
            'session_info': session_info,
            'intro_text': intro_text,
            'is_debug': settings.DEBUG
        })
        return context
Exemplo n.º 7
0
    def get_context_data(self, **kwargs):
        x = super().get_context_data(
            configs=SESSION_CONFIGS_DICT.values(),
            **kwargs,
        )

        return x
Exemplo n.º 8
0
    def get_context_data(self, **kwargs):
        title = getattr(settings, 'DEMO_PAGE_TITLE', 'Demo')
        intro_html = (getattr(settings, 'DEMO_PAGE_INTRO_HTML', '')
                      or getattr(settings, 'DEMO_PAGE_INTRO_TEXT', ''))
        context = super(DemoIndex, self).get_context_data(**kwargs)

        session_info = []
        for session_config in SESSION_CONFIGS_DICT.values():
            session_info.append({
                'name':
                session_config['name'],
                'display_name':
                session_config['display_name'],
                'url':
                reverse('CreateDemoSession', args=(session_config['name'], )),
                'num_demo_participants':
                session_config['num_demo_participants']
            })

        context.update({
            'session_info': session_info,
            'title': title,
            'intro_html': intro_html,
            'is_debug': settings.DEBUG,
        })
        return context
Exemplo n.º 9
0
def run_all_bots_for_session_config(session_config_name, num_participants,
                                    export_path):
    """
    this means all test cases are in 1 big test case.
    so if 1 fails, the others will not get run.
    """
    if session_config_name:
        session_config_names = [session_config_name]
    else:
        session_config_names = SESSION_CONFIGS_DICT.keys()

    for config_name in session_config_names:
        try:
            config = SESSION_CONFIGS_DICT[config_name]
        except KeyError:
            # important to alert the user, since people might be trying to enter app names.
            msg = f"No session config with name '{config_name}'."
            raise Exception(msg) from None

        num_bot_cases = config.get_num_bot_cases()
        for case_number in range(num_bot_cases):
            logger.info("Creating '{}' session (test case {})".format(
                config_name, case_number))

            session = otree.session.create_session(
                session_config_name=config_name,
                num_participants=(num_participants
                                  or config['num_demo_participants']),
            )
            session_id = session.id

            run_bots(session_id, case_number=case_number)

            logger.info('Bots completed session')
    if export_path:

        now = datetime.datetime.now()

        if export_path == AUTO_NAME_BOTS_EXPORT_FOLDER:
            # oTree convention to prefix __temp all temp folders.
            export_path = now.strftime(
                '__temp_bots_%b%d_%Hh%Mm%S.%f')[:-5] + 's'

        os.makedirs(export_path, exist_ok=True)

        for app in settings.OTREE_APPS:
            model_module = otree.common.get_models_module(app)
            if model_module.Player.objects_exists():
                fpath = Path(export_path, "{}.csv".format(app))
                with fpath.open("w", encoding="utf8") as fp:
                    otree.export.export_app(app, fp)
        fpath = Path(export_path, "all_apps_wide.csv")
        with fpath.open("w", encoding="utf8") as fp:
            otree.export.export_wide(fp)

        logger.info('Exported CSV to folder "{}"'.format(export_path))
    else:
        logger.info('Tip: Run this command with the --export flag'
                    ' to save the data generated by bots.')
Exemplo n.º 10
0
 def get_context_data(self, **kwargs):
     return super().get_context_data(
         configs=SESSION_CONFIGS_DICT.values(),
         participant_urls=self.room.get_participant_urls(self.request),
         room_wide_url=self.room.get_room_wide_url(self.request),
         room=self.room,
         form=CreateSessionForm(room_name=self.room_name),
         collapse_links=True,
         **kwargs)
Exemplo n.º 11
0
 def get_context_data(self, **kwargs):
     x = super().get_context_data(
         configs=SESSION_CONFIGS_DICT.values(),
         # splinter makes request.GET.get('mturk') == ['1\\']
         # no idea why
         # so just see if it's non-empty
         **kwargs,
     )
     return x
Exemplo n.º 12
0
class CreateSessionForm(wtforms.Form):
    session_configs = SESSION_CONFIGS_DICT.values()
    session_config_choices = [(s['name'], s['display_name'])
                              for s in session_configs]

    session_config = wtforms.SelectField(
        choices=session_config_choices,
        validators=validators_required,
        render_kw=dict({'class': 'form-select'}),
    )

    num_participants = wtforms.IntegerField(
        validators=[
            wtvalidators.DataRequired(),
            wtvalidators.NumberRange(min=1)
        ],
        render_kw={
            'autofocus': True,
            'class': 'form-control w-auto'
        },
    )

    # too much weirdness with BooleanField and 'y'
    # so we render manually
    # it's a booleanfield so its default value will be 'y',
    # but it's a hidden widget that we are passing to the server
    # through .serializeArray, so we need to filter out
    is_mturk = wtforms.BooleanField()
    room_name = wtforms.StringField(widget=wtwidgets.HiddenInput())

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.is_mturk.object_data:
            label = "Number of MTurk workers (assignments)"
            description = (
                'Since workers can return an assignment or drop out, '
                'some "spare" participants will be created: '
                f'the oTree session will have {settings.MTURK_NUM_PARTICIPANTS_MULTIPLE} '
                'times more participant objects than the number you enter here.'
            )
        else:
            label = "Number of participants"
            description = ''

        self.num_participants.label = label
        self.num_participants.description = description

    def validate(self):
        if not super().validate():
            return False

        config = SESSION_CONFIGS_DICT[self.session_config.data]
        lcm = config.get_lcm()
        if self.num_participants.data % lcm:
            self.num_participants.errors.append(
                'Please enter a valid number of participants.')
        return not bool(self.errors)
Exemplo n.º 13
0
def test_all_bots_for_session_config(
        session_config_name, num_participants, export_path):
    """
    this means all configs and test cases are in 1 big test case.
    so if 1 fails, the others will not get run.
    to separate them, we would need to move some of this code
    to pytest_generate_tests in conftest.py
    """
    if session_config_name:
        session_config_names = [session_config_name]
    else:
        session_config_names = SESSION_CONFIGS_DICT.keys()

    for config_name in session_config_names:
        try:
            config = SESSION_CONFIGS_DICT[config_name]
        except KeyError:
            # important to alert the user, since people might be trying to enter app names.
            raise Exception(f"No session config with name '{config_name}'.") from None

        bot_modules = [f'{app_name}.tests' for app_name in config['app_sequence']]
        pytest.register_assert_rewrite(*bot_modules)

        num_bot_cases = config.get_num_bot_cases()
        for case_number in range(num_bot_cases):
            logger.info("Creating '{}' session (test case {})".format(
                config_name, case_number))

            session = otree.session.create_session(
                session_config_name=config_name,
                num_participants=(num_participants or config['num_demo_participants']),
            )

            run_bots(session, case_number=case_number)
            logger.info('Bots completed session')
    if export_path:

        now = datetime.datetime.now()

        if export_path == AUTO_NAME_BOTS_EXPORT_FOLDER:
            # oTree convention to prefix __temp all temp folders.
            export_path = now.strftime('__temp_bots_%b%d_%Hh%Mm%S.%f')[:-5] + 's'

        os.makedirs(export_path, exist_ok=True)


        for app in settings.INSTALLED_OTREE_APPS:
            model_module = otree.common_internal.get_models_module(app)
            if model_module.Player.objects.exists():
                fpath = Path(export_path, "{}.csv".format(app))
                with fpath.open("w", encoding="utf8") as fp:
                    otree.export.export_app(app, fp, file_extension='csv')
        fpath = Path(export_path, "all_apps_wide.csv")
        with fpath.open("w", encoding="utf8") as fp:
            otree.export.export_wide(fp, 'csv')

        logger.info('Exported CSV to folder "{}"'.format(export_path))
Exemplo n.º 14
0
 def get_context_data(self, **kwargs):
     x = super().get_context_data(
         configs=SESSION_CONFIGS_DICT.values(),
         # splinter makes request.GET.get('mturk') == ['1\\']
         # no idea why
         # so just see if it's non-empty
         form=CreateSessionForm(is_mturk=bool(self.request.GET.get('is_mturk'))),
         **kwargs,
     )
     return x
Exemplo n.º 15
0
class CreateSessionForm(forms.Form):
    session_configs = SESSION_CONFIGS_DICT.values()
    session_config_choices = (
        # use '' instead of None. '' seems to immediately invalidate the choice,
        # rather than None which seems to be coerced to 'None'.
        [('', '-----')] +
        [(s['name'], s['display_name']) for s in session_configs])

    session_config = forms.ChoiceField(
        choices=session_config_choices, required=True)

    num_participants = forms.IntegerField(required=False)
    is_mturk = forms.BooleanField(
        widget=widgets.HiddenInput,
        initial=False,
        required=False
    )
    room_name = forms.CharField(
        initial=None,
        widget=widgets.HiddenInput,
        required=False
    )

    def __init__(self, *args, is_mturk=False, room_name=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['room_name'].initial = room_name
        if is_mturk:
            self.fields['is_mturk'].initial = True
            self.fields['num_participants'].label = "Number of MTurk workers (assignments)"
            self.fields['num_participants'].help_text = (
                'Since workers can return an assignment or drop out, '
                'some "spare" participants will be created: '
                f'the oTree session will have {settings.MTURK_NUM_PARTICIPANTS_MULTIPLE}'
                '{} times more participant objects than the number you enter here.'
            )
        else:
            self.fields['num_participants'].label = "Number of participants"

    def clean(self):
        super().clean()
        if self.errors:
            return
        session_config_name = self.cleaned_data['session_config']

        config = SESSION_CONFIGS_DICT[session_config_name]
        lcm = config.get_lcm()
        num_participants = self.cleaned_data.get('num_participants')
        if num_participants is None or num_participants % lcm:
            raise forms.ValidationError(
                'Please enter a valid number of participants.'
            )
Exemplo n.º 16
0
    def run(self):
        options = self.options

        self.check_browser()
        self.set_urls()
        self.client = requests.session()
        self.ping_server()
        self.server_configuration_check()

        sessions_to_create = []

        if options["session_config_name"]:
            session_config_name = options["session_config_name"]
            if session_config_name not in SESSION_CONFIGS_DICT:
                raise ValueError(
                    'No session config named "{}"'.format(
                        session_config_name)
                )
            session_config_names = [session_config_name]

        else:
            # default to all session configs
            session_config_names = SESSION_CONFIGS_DICT.keys()

        self.max_name_length = max(
            len(config_name) for config_name in session_config_names
        )

        for session_config_name in session_config_names:
            session_config = SESSION_CONFIGS_DICT[session_config_name]
            num_bot_cases = session_config.get_num_bot_cases()
            for bot_case_number in range(num_bot_cases):
                num_participants = (options.get('num_participants') or
                                    session_config['num_demo_participants'])
                sessions_to_create.append({
                    'session_config_name': session_config_name,
                    'num_participants': num_participants,
                    'bot_case_number': bot_case_number,
                })

        total_time_spent = 0
        # run in a separate loop, because we want to validate upfront
        # that the session configs are valid, etc,
        # rather than the command failing halfway through
        for session_to_create in sessions_to_create:
            total_time_spent += self.run_session(**session_to_create)

        print('Total: {} seconds'.format(
            round(total_time_spent, 1)
        ))
Exemplo n.º 17
0
    def run(self):
        options = self.options

        self.check_browser()
        self.set_urls()
        self.client = requests.session()
        self.ping_server()
        self.server_configuration_check()

        sessions_to_create = []

        if options["session_config_name"]:
            session_config_name = options["session_config_name"]
            if session_config_name not in SESSION_CONFIGS_DICT:
                raise ValueError(
                    'No session config named "{}"'.format(
                        session_config_name)
                )
            session_config_names = [session_config_name]

        else:
            # default to all session configs
            session_config_names = SESSION_CONFIGS_DICT.keys()

        self.max_name_length = max(
            len(config_name) for config_name in session_config_names
        )

        for session_config_name in session_config_names:
            session_config = SESSION_CONFIGS_DICT[session_config_name]
            num_bot_cases = session_config.get_num_bot_cases()
            for case_number in range(num_bot_cases):
                num_participants = (options.get('num_participants') or
                                    session_config['num_demo_participants'])
                sessions_to_create.append({
                    'session_config_name': session_config_name,
                    'num_participants': num_participants,
                    'case_number': case_number,
                })

        total_time_spent = 0
        # run in a separate loop, because we want to validate upfront
        # that the session configs are valid, etc,
        # rather than the command failing halfway through
        for session_to_create in sessions_to_create:
            total_time_spent += self.run_session(**session_to_create)

        print('Total: {} seconds'.format(
            round(total_time_spent, 1)
        ))
Exemplo n.º 18
0
    def post_receive_json(self, form_data: dict):
        session_config_name = form_data['session_config']
        config = SESSION_CONFIGS_DICT.get(session_config_name)
        if not config:
            msg = f'Session config "{session_config_name}" does not exist.'
            self.send_json({'validation_errors': msg})
            return

        num_participants = config['num_demo_participants']
        use_browser_bots = config.get('use_browser_bots', False)

        self.create_session_then_send_start_link(
            session_config_name=session_config_name,
            use_browser_bots=use_browser_bots,
            num_participants=num_participants,
            is_demo=True)
Exemplo n.º 19
0
class CreateSessionForm(forms.Form):
    session_configs = SESSION_CONFIGS_DICT.values()
    session_config_choices = (
        # use '' instead of None. '' seems to immediately invalidate the choice,
        # rather than None which seems to be coerced to 'None'.
        [('', '-----')] +
        [(s['name'], s['display_name']) for s in session_configs])

    session_config = forms.ChoiceField(
        choices=session_config_choices, required=True)

    num_participants = forms.IntegerField()

    def __init__(self, *args, **kwargs):
        for_mturk = kwargs.pop('for_mturk')
        super().__init__(*args, **kwargs)
        if for_mturk:
            self.fields['num_participants'].label = "Number of MTurk workers"
            self.fields['num_participants'].help_text = (
                'Since workers can return the HIT or drop out, '
                'some "spare" participants will be created: '
                'the oTree session will have '
                '{} times more participants than the MTurk HIT. '
                'The number you enter in this field is number of '
                'workers required for your HIT.'.format(
                    settings.MTURK_NUM_PARTICIPANTS_MULTIPLE
                )
            )
        else:
            self.fields['num_participants'].label = "Number of participants"

    def clean_num_participants(self):
        session_config_name = self.cleaned_data.get('session_config')

        # I think when this is checked, it's possible that basic validation
        # for session_config_name was not done yet.
        # when I tested it was None
        # but maybe it could also be the empty string because that's what's
        # explicitly put above.
        if session_config_name:
            lcm = SESSION_CONFIGS_DICT[session_config_name].get_lcm()
            num_participants = self.cleaned_data['num_participants']
            if num_participants % lcm:
                raise forms.ValidationError(
                    'Please enter a valid number of participants.'
                )
            return num_participants
Exemplo n.º 20
0
    def run(self):

        self.check_browser()
        self.set_urls()
        self.client = requests_session()
        self.client.headers.update({'otree-rest-key': REST_KEY})

        sessions_to_create = []

        session_config_name = self.session_config_name
        if session_config_name:
            if session_config_name not in SESSION_CONFIGS_DICT:
                msg = 'No session config named "{}"'.format(session_config_name)
                raise ValueError(msg)
            session_config_names = [session_config_name]

        else:
            # default to all session configs
            session_config_names = SESSION_CONFIGS_DICT.keys()

        self.max_name_length = max(
            len(config_name) for config_name in session_config_names
        )

        for session_config_name in session_config_names:
            session_config = SESSION_CONFIGS_DICT[session_config_name]
            num_bot_cases = session_config.get_num_bot_cases()
            for case_number in range(num_bot_cases):
                num_participants = (
                    self.num_participants or session_config['num_demo_participants']
                )
                sessions_to_create.append(
                    {
                        'session_config_name': session_config_name,
                        'num_participants': num_participants,
                        'case_number': case_number,
                    }
                )

        total_time_spent = 0
        # run in a separate loop, because we want to validate upfront
        # that the session configs are valid, etc,
        # rather than the command failing halfway through
        for session_to_create in sessions_to_create:
            total_time_spent += self.run_session(**session_to_create)

        print('Total: {} seconds'.format(round(total_time_spent, 1)))
Exemplo n.º 21
0
 def render_to_response(self, context):
     session = Session.objects.get(code=self.kwargs['session_code'])
     events_by_app_name_then_group = defaultdict(lambda: {})
     for session_config in SESSION_CONFIGS_DICT.values():
         app_name = session_config['name']
         try:
             groups_query = getattr(session, app_name + '_group')
         except AttributeError:
             continue
         groups = list(groups_query.all())
         if groups:
             for group in groups:
                 events = Event.objects.filter(group_pk=group.pk)
                 events_by_app_name_then_group[app_name][group.pk] = [
                     e.message for e in events
                 ]
     return JsonResponse(events_by_app_name_then_group, safe=False)
Exemplo n.º 22
0
def pytest_generate_tests(metafunc):
    # if the test function has a parameter called session_config_name
    if 'session_config_name' in metafunc.fixturenames:
        option = metafunc.config.option
        session_config_name = option.session_config_name
        if session_config_name:
            session_config_names = [session_config_name]
        else:
            session_config_names = SESSION_CONFIGS_DICT.keys()
        num_participants = option.num_participants
        if num_participants:
            num_participants = int(num_participants)
        params = [[name, num_participants, False]
                  for name in session_config_names]
        if option.preserve_data and len(params) >= 1:
            params[-1][2] = True
        metafunc.parametrize("session_config_name,num_participants,run_export",
                             params)
Exemplo n.º 23
0
def pytest_generate_tests(metafunc):
    # if the test function has a parameter called session_config_name
    if 'session_config_name' in metafunc.fixturenames:
        option = metafunc.config.option
        session_config_name = option.session_config_name
        if session_config_name:
            session_config_names = [session_config_name]
        else:
            session_config_names = SESSION_CONFIGS_DICT.keys()
        num_participants = option.num_participants
        if num_participants:
            num_participants = int(num_participants)
        preserve_data = option.preserve_data

        params = [[name, num_participants, preserve_data]
                  for name in session_config_names]
        metafunc.parametrize(
            "session_config_name,num_participants,preserve_data", params)
Exemplo n.º 24
0
def pytest_generate_tests(metafunc):
    # if the test function has a parameter called session_config_name
    if 'session_config_name' in metafunc.fixturenames:
        option = metafunc.config.option
        session_config_name = option.session_config_name
        if session_config_name:
            session_config_names = [session_config_name]
        else:
            session_config_names = SESSION_CONFIGS_DICT.keys()
        num_participants = option.num_participants
        if num_participants:
            num_participants = int(num_participants)
        params = [
            [name, num_participants, False]
            for name in session_config_names]
        if option.preserve_data and len(params) >= 1:
            params[-1][2] = True
        metafunc.parametrize(
            "session_config_name,num_participants,run_export", params)
Exemplo n.º 25
0
class CreateSessionForm(forms.Form):
    session_configs = SESSION_CONFIGS_DICT.values()
    session_config_choices = (
        [('', '-----')] +
        [(s['name'], s['display_name']) for s in session_configs])

    session_config = forms.ChoiceField(
        choices=session_config_choices, required=True)

    num_participants = forms.IntegerField()

    def __init__(self, *args, **kwargs):
        for_mturk = kwargs.pop('for_mturk')
        super(CreateSessionForm, self).__init__(*args, **kwargs)
        if for_mturk:
            self.fields['num_participants'].label = "Number of workers"
            self.fields['num_participants'].help_text = (
                'Since workers can return the hit or drop out '
                '"spare" participants will be created. Namely server will '
                'have %s times more participants than MTurk HIT. '
                'The number you enter in this field is number of '
                'workers required for your HIT.'
                % settings.MTURK_NUM_PARTICIPANTS_MULTIPLE
            )
        else:
            self.fields['num_participants'].label = "Number of participants"

    def clean_num_participants(self):
        session_config_name = self.cleaned_data.get('session_config')

        # We must check for an empty string in case validation is not run
        if session_config_name != '':
            lcm = SESSION_CONFIGS_DICT[session_config_name].get_lcm()
            num_participants = self.cleaned_data['num_participants']
            if num_participants % lcm:
                raise forms.ValidationError(
                    'Please enter a valid number of participants.'
                )
            return num_participants
Exemplo n.º 26
0
    def handle(self, **options):
        session_config_names = options["session_name"]
        if not session_config_names:
            # default to all session configs
            session_config_names = SESSION_CONFIGS_DICT.keys()

        if options['verbosity'] == 0:
            level = logging.ERROR
        elif options['verbosity'] == 1:
            level = logging.WARNING
        elif options['verbosity'] == 2:
            level = logging.INFO
        else:  # 3
            level = logging.DEBUG

        options['verbosity'] = (options['verbosity']
                                if options['verbosity'] > 2 else 1)

        logging.basicConfig(level=level)
        logging.getLogger("otree").setLevel(level)
        runner.logger.setLevel(level)
        client.logger.setLevel(level)

        export_path = options["export"] or options["save"]
        preserve_data = bool(export_path)

        test_runner = runner.OTreeExperimentTestRunner(**options)

        coverage = options["coverage"]

        if coverage:
            with runner.covering(session_config_names) as coverage_report:
                failures, data = test_runner.run_tests(
                    session_config_names, preserve_data=preserve_data)
        else:
            failures, data = test_runner.run_tests(session_config_names,
                                                   preserve_data=preserve_data)
        if coverage:
            logger.info("Coverage Report")
            if coverage in [COVERAGE_CONSOLE, COVERAGE_ALL]:
                coverage_report.report()
            if coverage in [COVERAGE_HTML, COVERAGE_ALL]:
                html_coverage_results_dir = '_coverage_results'
                coverage_report.html_report(
                    directory=html_coverage_results_dir)
                msg = ("See '{}/index.html' for detailed results."
                       ).format(html_coverage_results_dir)
                logger.info(msg)

        if preserve_data:
            now = datetime.datetime.now()

            if export_path == 'auto_name':
                export_path = now.strftime('_bots_%b%d_%Hh%Mm%S.%f')[:-5] + 's'

            if os.path.isdir(export_path):
                msg = "Directory '{}' already exists".format(export_path)
                raise IOError(msg)

            os.makedirs(export_path)

            metadata = dict(options)
            metadata.update({
                "timestamp": now.isoformat(),
                "versions": otree_and_django_version(),
                "failures": failures,
                "error": bool(failures)
            })

            sizes = {}
            for session_name, session_data in data.items():
                session_data = session_data or ""
                sizes[session_name] = len(session_data.splitlines())
                fname = "{}.csv".format(session_name)
                fpath = os.path.join(export_path, fname)
                with codecs.open(fpath, "w", encoding="utf8") as fp:
                    fp.write(session_data)

                metainfo = "\n".join(
                    ["{}: {}".format(k, v)
                     for k, v in metadata.items()] + ["sizes:"] +
                    ["\t{}: {}".format(k, v) for k, v in sizes.items()] + [""])
                fpath = os.path.join(export_path, "meta.txt")
                with codecs.open(fpath, "w", encoding="utf8") as fp:
                    fp.write(metainfo)
            logger.info('Exported CSV to folder "{}"'.format(export_path))
        else:
            logger.info('Tip: Run this command with the --export flag'
                        ' to save the data generated by bots.')

        if failures:
            sys.exit(bool(failures))
Exemplo n.º 27
0
    url_name = 'redwood_debug'
    url_pattern = r'^redwood/debug/session/(?P<session_code>[a-zA-Z0-9_-]+)/$'
    template_name = 'otree_redwood/Debug.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['stats'] = stats.items()
        channel_layer = channels.asgi.get_channel_layer()
        if 'statistics' in channel_layer.extensions:
            context['global_channel_stats'] = channel_layer.global_statistics()
        context['connected_participants'] = Connection.objects.all()
        context['session_code'] = self.kwargs['session_code']
        return context


app_specific_exports = []
for session_config in SESSION_CONFIGS_DICT.values():
    app_name = session_config['name']
    dotted_path = app_name + '.views'
    display_name = session_config['display_name']
    try:
        module = import_module(dotted_path)
    except ImportError:
        continue
    table_fn = getattr(module, 'get_output_table', None)
    header_fn = getattr(module, 'get_output_table_header', None)
    if table_fn and header_fn:
        app_specific_exports.append(
            AppSpecificExportCSV(app_name, display_name, table_fn, header_fn))
Exemplo n.º 28
0
 def get_context_data(self, **kwargs):
     kwargs['configs'] = SESSION_CONFIGS_DICT.values()
     return super().get_context_data(**kwargs)
Exemplo n.º 29
0
    def handle(self, **options):
        session_config_names = options["session_name"]
        if not session_config_names:
            # default to all session configs
            session_config_names = SESSION_CONFIGS_DICT.keys()

        if options['verbosity'] == 0:
            level = logging.ERROR
        elif options['verbosity'] == 1:
            level = logging.WARNING
        elif options['verbosity'] == 2:
            level = logging.INFO
        else:  # 3
            level = logging.DEBUG

        options['verbosity'] = (
            options['verbosity'] if options['verbosity'] > 2 else 1)

        logging.basicConfig(level=level)
        logging.getLogger("otree").setLevel(level)
        runner.logger.setLevel(level)
        client.logger.setLevel(level)

        export_path = options["export"] or options["save"]
        preserve_data = bool(export_path)

        test_runner = runner.OTreeExperimentTestRunner(**options)

        coverage = options["coverage"]

        if coverage:
            with runner.covering(session_config_names) as coverage_report:
                failures, data = test_runner.run_tests(
                    session_config_names, preserve_data=preserve_data)
        else:
            failures, data = test_runner.run_tests(
                session_config_names, preserve_data=preserve_data)
        if coverage:
            logger.info("Coverage Report")
            if coverage in [COVERAGE_CONSOLE, COVERAGE_ALL]:
                coverage_report.report()
            if coverage in [COVERAGE_HTML, COVERAGE_ALL]:
                html_coverage_results_dir = '_coverage_results'
                coverage_report.html_report(
                    directory=html_coverage_results_dir)
                msg = ("See '{}/index.html' for detailed results.").format(
                    html_coverage_results_dir)
                logger.info(msg)

        if preserve_data:
            now = datetime.datetime.now()

            if export_path == 'auto_name':
                export_path = now.strftime('_bots_%b%d_%Hh%Mm%S.%f')[:-5] + 's'

            if os.path.isdir(export_path):
                msg = "Directory '{}' already exists".format(export_path)
                raise IOError(msg)

            os.makedirs(export_path)

            metadata = dict(options)
            metadata.update({
                "timestamp": now.isoformat(),
                "versions": otree_and_django_version(),
                "failures": failures, "error": bool(failures)})

            sizes = {}
            for session_name, session_data in data.items():
                session_data = session_data or ""
                sizes[session_name] = len(session_data.splitlines())
                fname = "{}.csv".format(session_name)
                fpath = os.path.join(export_path, fname)
                with codecs.open(fpath, "w", encoding="utf8") as fp:
                    fp.write(session_data)

                metainfo = "\n".join(
                    ["{}: {}".format(k, v) for k, v in metadata.items()] +
                    ["sizes:"] +
                    ["\t{}: {}".format(k, v) for k, v in sizes.items()] + [""])
                fpath = os.path.join(export_path, "meta.txt")
                with codecs.open(fpath, "w", encoding="utf8") as fp:
                    fp.write(metainfo)
            logger.info('Exported CSV to folder "{}"'.format(export_path))
        else:
            logger.info('Tip: Run this command with the --export flag'
                        ' to save the data generated by bots.')

        if failures:
            sys.exit(bool(failures))
Exemplo n.º 30
0
 def get_context_data(self, **kwargs):
     kwargs['configs'] = SESSION_CONFIGS_DICT.values()
     return super().get_context_data(**kwargs)
Exemplo n.º 31
0
 def get_context_data(self, **kwargs):
     session_config_summaries = [
         session_config.get_info()
         for session_config in SESSION_CONFIGS_DICT.values()]
     kwargs.update({'session_config_summaries': session_config_summaries})
     return super(CreateSession, self).get_context_data(**kwargs)