Example #1
0
    def __init__(self, **kwargs):
        self._context = Context(init=True)
        self._context['ExceptionManager'] = SandboxExceptionManager(self)
        self._context.sandbox = self
        self._context.push()
        self.on_context_created()
        self._container = None
        super(Sandbox, self).__init__(**kwargs)
        self._container = SandboxContent(size=self.size, pos=self.pos)
        super(Sandbox, self).add_widget(self._container)
        self._context.pop()

        # force SandboxClock's scheduling
        Clock.schedule_interval(self._clock_sandbox, 0)
        Clock.schedule_once(self._clock_sandbox_draw, -1)
        self.main_clock = object.__getattribute__(Clock, '_obj')
Example #2
0
class Sandbox(FloatLayout):
    '''Sandbox widget, used to get back all the exceptions raised in a child
    into the Sandbox itself.
    '''

    def __init__(self, **kwargs):
        self._context = Context(init=True)
        self._context['ExceptionManager'] = SandboxExceptionManager(self)
        self._context.sandbox = self
        self._context.push()
        self.on_context_created()
        self._container = None
        super(Sandbox, self).__init__(**kwargs)
        self._container = SandboxContent(size=self.size, pos=self.pos)
        super(Sandbox, self).add_widget(self._container)
        self._context.pop()

        # force SandboxClock's scheduling
        Clock.schedule_interval(self._clock_sandbox, 0)
        Clock.schedule_once(self._clock_sandbox_draw, -1)
        self.main_clock = object.__getattribute__(Clock, '_obj')

    def __enter__(self):
        self._context.push()

    def __exit__(self, _type, value, traceback):
        self._context.pop()
        if _type is not None:
            return self.on_exception(value, _traceback=traceback)

    def on_context_created(self):
        '''Override this method in order to load kv, or anything you need with
        the new created context.
        '''
        pass

    def on_exception(self, exception, _traceback=None):
        '''Override this method in order to catch all the exceptions from
        children.

        If you return True, it will not reraise the exception.
        If you return False, the exception will be raised to the parent.
        '''
        import traceback
        traceback.print_tb(_traceback)
        return True

    on_touch_down = sandbox(Widget.on_touch_down)
    on_touch_move = sandbox(Widget.on_touch_move)
    on_touch_up = sandbox(Widget.on_touch_up)
        
    @sandbox
    def add_widget(self, *args, **kwargs):
        self._container.add_widget(*args, **kwargs)

    @sandbox
    def remove_widget(self, *args, **kwargs):
        self._container.remove_widget(*args, **kwargs)

    @sandbox
    def clear_widgets(self, *args, **kwargs):
        self._container.clear_widgets()

    @sandbox
    def on_size(self, *args):
        if self._container:
            self._container.size = self.size

    @sandbox
    def on_pos(self, *args):
        if self._container:
            self._container.pos = self.pos

    @sandbox
    def _clock_sandbox(self, dt):
        #import pdb; pdb.set_trace()
        Clock.tick()
        Builder.sync()

    @sandbox
    def _clock_sandbox_draw(self, dt):
        Clock.tick_draw()
        Builder.sync()
        self.main_clock.schedule_once(self._call_draw, 0)

    def _call_draw(self, dt):
        self.main_clock.schedule_once(self._clock_sandbox_draw, -1)
Example #3
0
async def ceed_app(request, nursery, temp_file, tmp_path, tmp_path_factory,
                   app_list):

    params = request.param if hasattr(request,
                                      'param') and request.param else {}
    ts0 = time.perf_counter()
    from kivy.core.window import Window
    from kivy.context import Context
    from kivy.clock import ClockBase
    from kivy.animation import Animation
    from kivy.base import stopTouchApp
    from kivy.factory import FactoryBase, Factory
    from kivy.lang.builder import BuilderBase, Builder
    from kivy.logger import LoggerHistory

    context = Context(init=False)
    context['Clock'] = ClockBase(async_lib='trio')
    # context['Factory'] = FactoryBase.create_from(Factory)
    # have to make sure all ceed files are imported before this because
    # globally read kv files will not be loaded again in the new builder,
    # except if manually loaded, which we don't do
    # context['Builder'] = BuilderBase.create_from(Builder)
    context.push()

    Window.create_window()
    Window.register()
    Window.initialized = True
    Window.canvas.clear()

    from kivy.clock import Clock
    Clock._max_fps = 0

    import ceed.view.controller
    ceed.view.controller.ignore_vpixx_import_error = True

    if params.get('persist_config'):
        base = str(tmp_path_factory.getbasetemp() / params['persist_config'])
        app = CeedTestApp(json_config_path=base + 'config.yaml',
                          ini_file=base + 'config.ini',
                          open_player_thread=False)
    else:
        app = CeedTestApp(json_config_path=temp_file('config.yaml'),
                          ini_file=temp_file('config.ini'),
                          open_player_thread=False)
    app.ceed_data.root_path = str(tmp_path)

    try:
        app.set_async_lib('trio')
        nursery.start_soon(app.async_run)

        ts = time.perf_counter()
        while not app.app_has_started:
            await trio.sleep(.1)
            if time.perf_counter() - ts >= 120:
                raise TimeoutError()

        await app.wait_clock_frames(5)

        ts1 = time.perf_counter()
        yield weakref.proxy(app)
        ts2 = time.perf_counter()

        stopTouchApp()

        ts = time.perf_counter()
        while not app.app_has_stopped:
            await trio.sleep(.1)
            if time.perf_counter() - ts >= 40:
                raise TimeoutError()

    finally:
        stopTouchApp()
        for anim in list(Animation._instances):
            anim._unregister()
        app.clean_up()
        for child in Window.children[:]:
            Window.remove_widget(child)

        context.pop()
        del context
        LoggerHistory.clear_history()

    app_list.append((weakref.ref(app), weakref.ref(request)))

    ts3 = time.perf_counter()
    print(ts1 - ts0, ts2 - ts1, ts3 - ts2)
Example #4
0
class Sandbox(FloatLayout):
    '''Sandbox widget, used to trap all the exceptions raised by child
    widgets.
    '''
    def __init__(self, **kwargs):
        self._context = Context(init=True)
        self._context['ExceptionManager'] = SandboxExceptionManager(self)
        self._context.sandbox = self
        self._context.push()
        self.on_context_created()
        self._container = None
        super(Sandbox, self).__init__(**kwargs)
        self._container = SandboxContent(size=self.size, pos=self.pos)
        super(Sandbox, self).add_widget(self._container)
        self._context.pop()

        # force SandboxClock's scheduling
        Clock.schedule_interval(self._clock_sandbox, 0)
        Clock.schedule_once(self._clock_sandbox_draw, -1)
        self.main_clock = object.__getattribute__(Clock, '_obj')

    def __enter__(self):
        self._context.push()

    def __exit__(self, _type, value, traceback):
        self._context.pop()
        if _type is not None:
            return self.on_exception(value, _traceback=traceback)

    def on_context_created(self):
        '''Override this method in order to load your kv file or do anything
        else with the newly created context.
        '''
        pass

    def on_exception(self, exception, _traceback=None):
        '''Override this method in order to catch all the exceptions from
        children.

        If you return True, it will not reraise the exception.
        If you return False, the exception will be raised to the parent.
        '''
        import traceback
        traceback.print_tb(_traceback)
        return True

    on_touch_down = sandbox(Widget.on_touch_down)
    on_touch_move = sandbox(Widget.on_touch_move)
    on_touch_up = sandbox(Widget.on_touch_up)

    @sandbox
    def add_widget(self, *args, **kwargs):
        self._container.add_widget(*args, **kwargs)

    @sandbox
    def remove_widget(self, *args, **kwargs):
        self._container.remove_widget(*args, **kwargs)

    @sandbox
    def clear_widgets(self, *args, **kwargs):
        self._container.clear_widgets()

    @sandbox
    def on_size(self, *args):
        if self._container:
            self._container.size = self.size

    @sandbox
    def on_pos(self, *args):
        if self._container:
            self._container.pos = self.pos

    @sandbox
    def _clock_sandbox(self, dt):
        # import pdb; pdb.set_trace()
        Clock.tick()
        Builder.sync()

    @sandbox
    def _clock_sandbox_draw(self, dt):
        Clock.tick_draw()
        Builder.sync()
        self.main_clock.schedule_once(self._call_draw, 0)

    def _call_draw(self, dt):
        self.main_clock.schedule_once(self._clock_sandbox_draw, -1)
Example #5
0
async def kivy_app(request, nursery):
    gc.collect()
    if apps:
        last_app, last_request = apps.pop()
        assert last_app() is None, \
            'Memory leak: failed to release app for test ' + repr(last_request)

    from os import environ
    environ['KIVY_USE_DEFAULTCONFIG'] = '1'

    # force window size + remove all inputs
    from kivy.config import Config
    Config.set('graphics', 'width', '320')
    Config.set('graphics', 'height', '240')
    for items in Config.items('input'):
        Config.remove_option('input', items[0])

    from kivy.core.window import Window
    from kivy.context import Context
    from kivy.clock import ClockBase
    from kivy.factory import FactoryBase, Factory
    from kivy.app import App
    from kivy.lang.builder import BuilderBase, Builder
    from kivy.base import stopTouchApp
    from kivy import kivy_data_dir
    from kivy.logger import LoggerHistory

    kivy_eventloop = environ.get('KIVY_EVENTLOOP', 'asyncio')
    if kivy_eventloop == 'asyncio':
        pytest.importorskip(
            'pytest_asyncio',
            reason='KIVY_EVENTLOOP == "asyncio" but '
                   '"pytest_asyncio" is not installed')
        async_lib = 'asyncio'
    elif kivy_eventloop == 'trio':
        pytest.importorskip(
            'pytest_trio',
            reason='KIVY_EVENTLOOP == "trio" but '
                   '"pytest_trio" is not installed')
        async_lib = 'trio'
    else:
        pytest.skip(
            'KIVY_EVENTLOOP must be set to either of "asyncio" or '
            '"trio" to run async tests')

    context = Context(init=False)
    context['Clock'] = ClockBase(async_lib=async_lib)

    # have to make sure all global kv files are loaded before this because
    # globally read kv files (e.g. on module import) will not be loaded again
    # in the new builder, except if manually loaded, which we don't do
    context['Factory'] = FactoryBase.create_from(Factory)
    context['Builder'] = BuilderBase.create_from(Builder)
    context.push()

    Window.create_window()
    Window.register()
    Window.initialized = True
    Window.canvas.clear()

    app = request.param[0]()
    app.set_async_lib(async_lib)

    if async_lib == 'asyncio':
        import asyncio
        loop = asyncio.get_event_loop()
        loop.create_task(app.async_run())
    else:
        nursery.start_soon(app.async_run)
    from kivy.clock import Clock
    Clock._max_fps = 0

    ts = time.perf_counter()
    while not app.app_has_started:
        await app.async_sleep(.1)
        if time.perf_counter() - ts >= 10:
            raise TimeoutError()

    await app.wait_clock_frames(5)

    yield app

    stopTouchApp()

    ts = time.perf_counter()
    while not app.app_has_stopped:
        await app.async_sleep(.1)
        if time.perf_counter() - ts >= 10:
            raise TimeoutError()

    for child in Window.children[:]:
        Window.remove_widget(child)
    context.pop()

    # release all the resources
    del context
    LoggerHistory.clear_history()
    apps.append((weakref.ref(app), request))
    del app
    gc.collect()
Example #6
0
async def kivy_app(request, nursery):
    from os import environ
    environ['KIVY_USE_DEFAULTCONFIG'] = '1'

    # force window size + remove all inputs
    from kivy.config import Config
    Config.set('graphics', 'width', '320')
    Config.set('graphics', 'height', '240')
    for items in Config.items('input'):
        Config.remove_option('input', items[0])

    from kivy.core.window import Window
    from kivy.context import Context
    from kivy.clock import ClockBase
    from kivy.lang.builder import BuilderBase, Builder
    from kivy.base import stopTouchApp
    from kivy import kivy_data_dir

    kivy_eventloop = environ.get('KIVY_EVENTLOOP', 'asyncio')
    if kivy_eventloop == 'asyncio':
        pytest.importorskip('pytest_asyncio',
                            reason='KIVY_EVENTLOOP == "asyncio" but '
                            '"pytest_asyncio" is not installed')
        async_lib = 'asyncio'
    elif kivy_eventloop == 'trio':
        pytest.importorskip('pytest_trio',
                            reason='KIVY_EVENTLOOP == "trio" but '
                            '"pytest_trio" is not installed')
        async_lib = 'trio'
    else:
        pytest.skip(
            reason='KIVY_EVENTLOOP must be set to either of "asyncio" or '
            '"trio" to run async tests')

    context = Context(init=False)
    context['Clock'] = ClockBase(async_lib=async_lib)
    # context['Builder'] = BuilderBase()
    context.push()
    # Builder.load_file(
    #     os.path.join(kivy_data_dir, 'style.kv'), rulesonly=True)

    Window.create_window()
    Window.register()
    Window.initialized = True
    Window.canvas.clear()

    app = request.param[0]()

    if async_lib == 'asyncio':
        import asyncio
        loop = asyncio.get_event_loop()
        loop.create_task(app.async_run())
    else:
        nursery.start_soon(app.async_run)

    ts = time.perf_counter()
    while not app.app_has_started:
        await async_sleep(.1)
        if time.perf_counter() - ts >= 10:
            raise TimeoutError()

    await app.wait_clock_frames(5)

    yield app

    stopTouchApp()

    ts = time.perf_counter()
    while not app.app_has_stopped:
        await async_sleep(.1)
        if time.perf_counter() - ts >= 10:
            raise TimeoutError()

    for child in Window.children[:]:
        Window.remove_widget(child)
    context.pop()
    gc.collect()