def test_build_package(): event_loop = new_event_loop() asyncio.set_event_loop(event_loop) try: with TemporaryDirectory(prefix='test_colcon_') as tmp_path_str: tmp_path = Path(tmp_path_str) python_build_task = PythonBuildTask() package = PackageDescriptor(tmp_path / 'src') package.name = 'test_package' package.type = 'python' context = TaskContext( pkg=package, args=SimpleNamespace( path=str(tmp_path / 'src'), build_base=str(tmp_path / 'build'), install_base=str(tmp_path / 'install'), symlink_install=False, ), dependencies={} ) python_build_task.set_context(context=context) pkg = python_build_task.context.pkg pkg.path.mkdir() (pkg.path / 'setup.py').write_text( 'from setuptools import setup\n' 'setup(\n' ' name="test_package",\n' ' packages=["my_module"],\n' ')\n' ) (pkg.path / 'my_module').mkdir() (pkg.path / 'my_module' / '__init__.py').touch() src_base = Path(python_build_task.context.args.path) source_files_before = set(src_base.rglob('*')) event_loop.run_until_complete(python_build_task.build()) source_files_after = set(src_base.rglob('*')) assert source_files_before == source_files_after build_base = Path(python_build_task.context.args.build_base) assert 1 == len(list(build_base.rglob('my_module/__init__.py'))) install_base = Path(python_build_task.context.args.install_base) assert 1 == len(list(install_base.rglob('my_module/__init__.py'))) pkg_info, = install_base.rglob('PKG-INFO') assert 'Name: test-package' in pkg_info.read_text().splitlines() finally: event_loop.close()
def execute(self, args, jobs, *, on_error=OnError.interrupt): # noqa: D102 # avoid debug message from asyncio when colcon uses debug log level asyncio_logger = logging.getLogger('asyncio') asyncio_logger.setLevel(logging.INFO) loop = new_event_loop() asyncio.set_event_loop(loop) coro = self._execute(args, jobs, on_error=on_error) future = asyncio.ensure_future(coro, loop=loop) try: logger.debug('run_until_complete') loop.run_until_complete(future) except KeyboardInterrupt: logger.debug('run_until_complete was interrupted') # override job rc with special SIGINT value for job in self._ongoing_jobs: job.returncode = SIGINT_RESULT # ignore further SIGINTs signal.signal(signal.SIGINT, signal.SIG_IGN) # wait for jobs which have also received a SIGINT if not future.done(): logger.debug('run_until_complete again') loop.run_until_complete(future) assert future.done() # read potential exception to avoid asyncio error _ = future.exception() logger.debug('run_until_complete finished') return signal.SIGINT except Exception as e: # noqa: F841 exc = traceback.format_exc() logger.error('Exception in job execution: {e}\n{exc}'.format_map( locals())) return 1 finally: # HACK on Windows closing the event loop seems to hang after Ctrl-C # even though no futures are pending if sys.platform != 'win32': logger.debug('closing loop') loop.close() logger.debug('loop closed') result = future.result() logger.debug("run_until_complete finished with '{result}'".format_map( locals())) return result
def test_run_cancel(): # with callbacks, canceled stdout_lines = [] def stdout_callback(line): nonlocal stdout_lines stdout_lines.append(line) coroutine = run([ sys.executable, '-c', r"import time; time.sleep(1); print('line1\nline2')" ], stdout_callback, None) loop = new_event_loop() asyncio.set_event_loop(loop) task = asyncio.Task(coroutine, loop=loop) assert task.cancel() is True try: with pytest.raises(asyncio.CancelledError): loop.run_until_complete(task) finally: loop.close()
def execute(self, args, jobs, *, on_error=OnError.interrupt): # noqa: D102 # avoid debug message from asyncio when colcon uses debug log level asyncio_logger = logging.getLogger('asyncio') asyncio_logger.setLevel(logging.INFO) rc = 0 loop = new_event_loop() asyncio.set_event_loop(loop) jobs = jobs.copy() try: while jobs: name, job = jobs.popitem(last=False) coro = job() future = asyncio.ensure_future(coro, loop=loop) try: logger.debug( "run_until_complete '{name}'".format_map(locals())) loop.run_until_complete(future) except KeyboardInterrupt: logger.debug( "run_until_complete '{name}' was interrupted" .format_map(locals())) # override job rc with special SIGINT value job.returncode = SIGINT_RESULT # ignore further SIGINTs signal.signal(signal.SIGINT, signal.SIG_IGN) # wait for job which has also received a SIGINT if not future.done(): logger.debug( "run_until_complete '{name}' again" .format_map(locals())) loop.run_until_complete(future) assert future.done() # read potential exception to avoid asyncio error _ = future.exception() # noqa: F841 logger.debug( "run_until_complete '{name}' finished" .format_map(locals())) return signal.SIGINT except Exception as e: # noqa: F841 exc = traceback.format_exc() logger.error( "Exception in job execution '{name}': {e}\n{exc}" .format_map(locals())) return 1 result = future.result() logger.debug( "run_until_complete '{name}' finished with '{result}'" .format_map(locals())) if result: if not rc: rc = result if on_error in (OnError.interrupt, OnError.skip_pending): # skip pending jobs return rc if on_error == OnError.skip_downstream: # skip downstream jobs of failed one for pending_name, pending_job in list(jobs.items()): if job.identifier in pending_job.dependencies: del jobs[pending_name] finally: for task in asyncio.Task.all_tasks(): if not task.done(): logger.error("Task '{task}' not done".format_map(locals())) # HACK on Windows closing the event loop seems to hang after Ctrl-C # even though no futures are pending if sys.platform != 'win32': logger.debug('closing loop') loop.close() logger.debug('loop closed') return rc