async def media_app(request, nursery, tmp_path): ts0 = time.perf_counter() from kivy.core.window import Window from kivy.context import Context from kivy.clock import ClockBase from kivy.base import stopTouchApp from kivy.logger import LoggerHistory context = Context(init=False) context['Clock'] = ClockBase(async_lib='trio') context.push() Window.create_window() Window.register() Window.initialized = True Window.canvas.clear() from more_kivy_app.app import report_exception_in_app import cpl_media cpl_media.error_callback = report_exception_in_app app = DemoTestApp(yaml_config_path=str(tmp_path / 'config.yaml'), ini_file=str(tmp_path / 'config.ini')) 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 >= 10: raise TimeoutError() await app.wait_clock_frames(5) ts1 = time.perf_counter() yield 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 >= 10: raise TimeoutError() finally: stopTouchApp() app.clean_up() for child in Window.children[:]: Window.remove_widget(child) context.pop() del context LoggerHistory.clear_history() ts3 = time.perf_counter() print(ts1 - ts0, ts2 - ts1, ts3 - ts2)
def kivy_exception_manager(): from kivy.context import Context from kivy.base import ExceptionManagerBase, ExceptionManager context = Context(init=False) context['ExceptionManager'] = ExceptionManagerBase() context.push() try: yield ExceptionManager finally: context.pop()
def kivy_metrics(): from kivy.context import Context from kivy.metrics import MetricsBase, Metrics from kivy._metrics import dispatch_pixel_scale context = Context(init=False) context['Metrics'] = MetricsBase() context.push() # need to do it to reset the global value dispatch_pixel_scale() try: yield Metrics finally: context.pop() Metrics._set_cached_scaling()
def kivy_clock(): from kivy.context import Context from kivy.clock import ClockBase context = Context(init=False) context['Clock'] = ClockBase() context.push() from kivy.clock import Clock Clock._max_fps = 0 try: Clock.start_clock() yield Clock Clock.stop_clock() finally: context.pop()
def kivy_benchmark(benchmark, kivy_clock): from kivy.core.window import Window from kivy.cache import Cache from kivy.utils import platform import kivy from kivy.core.gl import glGetString, GL_VENDOR, GL_RENDERER, GL_VERSION from kivy.context import Context from kivy.clock import ClockBase from kivy.factory import FactoryBase, Factory from kivy.lang.builder import BuilderBase, Builder context = Context(init=False) context['Clock'] = ClockBase() context['Factory'] = FactoryBase.create_from(Factory) context['Builder'] = BuilderBase.create_from(Builder) for category in list(Cache._objects.keys()): if category not in Cache._categories: continue for key in list(Cache._objects[category].keys()): Cache.remove(category, key) gc.collect() benchmark.extra_info['platform'] = str(sys.platform) benchmark.extra_info['python_version'] = str(sys.version) benchmark.extra_info['python_api'] = str(sys.api_version) benchmark.extra_info['kivy_platform'] = platform benchmark.extra_info['kivy_version'] = kivy.__version__ benchmark.extra_info['gl_vendor'] = str(glGetString(GL_VENDOR)) benchmark.extra_info['gl_renderer'] = str(glGetString(GL_RENDERER)) benchmark.extra_info['gl_version'] = str(glGetString(GL_VERSION)) context.push() try: yield benchmark finally: context.pop()
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)
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()
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)
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)
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()