import logging from django.conf import settings, global_settings from django.core.management.base import BaseCommand from django.test.utils import ( setup_databases, setup_test_environment, teardown_databases, teardown_test_environment, ) from otree.bots.runner import run_all_bots_for_session_config import otree.common logger = logging.getLogger('otree') from otree.constants import AUTO_NAME_BOTS_EXPORT_FOLDER MSG_BOTS_HELP = 'Run oTree bots' class Command(BaseCommand): help = MSG_BOTS_HELP def _get_action(self, parser, signature): option_strings = list(signature) for idx, action in enumerate(parser._actions): if action.option_strings == option_strings: return parser._actions[idx] def add_arguments(self, parser): # Positional arguments parser.add_argument( 'session_config_name', nargs='?', help='If omitted, all sessions in SESSION_CONFIGS are run', ) parser.add_argument( 'num_participants', type=int, nargs='?', help='Number of participants (if omitted, use num_demo_participants)', ) # don't call it --data because then people might think that # that's the *input* data folder parser.add_argument( '--export', nargs='?', const=AUTO_NAME_BOTS_EXPORT_FOLDER, dest='export_path', help=( 'Saves the data generated by the tests. ' 'Runs the "export data" command, ' 'outputting the CSV files to the specified directory, ' 'or an auto-generated one.' ), ) parser.add_argument( '--save', nargs='?', const=AUTO_NAME_BOTS_EXPORT_FOLDER, dest='export_path', help=('Alias for --export.'), ) v_action = self._get_action(parser, ("-v", "--verbosity")) v_action.default = '1' v_action.help = ( 'Verbosity level; 0=minimal output, 1=normal output,' '2=verbose output (DEFAULT), 3=very verbose output' ) def prepare_global_state(self): ''' separate function so it's easier to patch these are optimizations that are mostly redundant with what runtests.py does. ''' # To make tests run faster, autorefresh should be set to True # http://whitenoise.evans.io/en/latest/django.html#whitenoise-makes-my-tests-run-slow settings.WHITENOISE_AUTOREFRESH = True # same hack as in resetdb code # because pytest.main() uses the serializer # it breaks if the app has migrations but they aren't up to date otree.common.patch_migrations_module() settings.STATICFILES_STORAGE = global_settings.STATICFILES_STORAGE def handle( self, *, verbosity, session_config_name, num_participants, export_path, **options ): self.prepare_global_state() setup_test_environment() old_config = setup_databases( interactive=False, verbosity=verbosity, aliases={'default'} ) try: run_all_bots_for_session_config( session_config_name=session_config_name, num_participants=num_participants, export_path=export_path, ) finally: teardown_databases(old_config, verbosity=verbosity) teardown_test_environment()