def close_existing_session(self): # make sure room is closed resp = self.post(reverse('CloseBrowserBotsSession')) if not resp.ok: msg = ('Request to close existing browser bots session failed. ' 'Response: {} {}'.format(repr(resp), resp.text)) raise AssertionError(msg)
async def create_session_then_send_start_link(self, use_browser_bots, **session_kwargs): try: session = otree.session.create_session_traceback_wrapper( **session_kwargs) if use_browser_bots: otree.bots.browser.initialize_session(session_pk=session.id, case_number=None) # the "elif" is because if it uses browser bots, then exogenous data is mocked # as part of run_bots. # 2020-07-07: this queries the DB, shouldn't i use database_sync_to_async? # i don't get any error elif session.is_demo: session.mock_exogenous_data() except Exception as e: if isinstance(e, otree.session.CreateSessionError): e = e.__cause__ traceback_str = ''.join( traceback.format_exception(type(e), e, e.__traceback__)) await self.send_response_to_browser( dict(error=f'Failed to create session: {e}', traceback=traceback_str)) # i used to do "raise" here. # if I raise, then in non-demo sessions, the traceback is not displayed # as it should be. # Instead, there is an error # "Server error occurred, check Sentry or the logs" # I guess the websocket gets cut off? that's also why my test_traceback test was failing. # why did I use raise in the first place? # was it just so the traceback would go to the console or Sentry? # if we show it in the browser, there's no need to show it anywhere else, right? # maybe it was just a fallback in case the TB was truncated? # or because the traceback should not be shown outside of DEBUG mode else: from otree.asgi import reverse session_home_view = ('MTurkCreateHIT' if session.is_mturk else 'SessionStartLinks') await self.send_response_to_browser( {'session_url': reverse(session_home_view, code=session.code)})
def launch_browser(self, num_participants, secret_code): wait_room_url = urljoin( self.server_url, reverse('BrowserBotStartLink', admin_secret_code=secret_code), ) for browser_cmd in self.browser_cmds: args = [browser_cmd] if os.environ.get('BROWSER_BOTS_USE_HEADLESS'): args.append('--headless') # needed in windows args.append('--disable-gpu') # for some reason --screenshot OR --remote-debugging-port is necessary to get my JS to execute?!? # NO idea why. --remote-debugging-port gets me further than --screenshot, which gets stuck # on skip_lookahead # --remote-debugging-port=9222 works also args.append('--remote-debugging-port=9222') for i in range(num_participants): args.append(wait_room_url) try: return Popen(args) except FileNotFoundError: pass msg = ( 'Could not find a browser at the following path(s):\n\n' '{}\n\n' 'Note: in settings.py, you can set BROWSER_COMMAND ' 'to the path to your browser executable. ' 'Otherwise, oTree will try to launch Chrome from its usual path.' ).format('\n'.join(self.browser_cmds)) # we should show the original exception, because it might have # valuable info about why the browser didn't launch, # not raise from None. raise FileNotFoundError(msg)
def vars_for_template(self): session = self.session room = session.get_room() from otree.models import Participant p_codes = values_flat(session.pp_set.order_by('id_in_session'), Participant.code) participant_urls = [] for code in p_codes: rel_url = otree.common.participant_start_url(code) url = self.request.base_url.replace(path=rel_url) participant_urls.append(url) context = dict(use_browser_bots=session.use_browser_bots, participant_urls=participant_urls) if room: context.update( room_wide_url=room.get_room_wide_url(self.request), room=room, collapse_links=True, ) else: from otree.asgi import reverse anonymous_url = self.request.base_url.replace( path=reverse('JoinSessionAnonymously', anonymous_code=session._anonymous_code)) context.update( anonymous_url=anonymous_url, num_participants=len(participant_urls), splitscreen_mode_on=len(participant_urls) <= 3, ) return context
class URLs: create_browser_bots = reverse('CreateBrowserBotsSession')