def test_create_environment_hooks(): with TemporaryDirectory(prefix='test_colcon_') as basepath: with EntryPointContext(extension1=Extension1, extension2=Extension2): with patch('colcon_core.environment.logger.error') as error: hooks = create_environment_hooks(basepath, 'pkg_name') assert len(hooks) == 2 assert hooks[0] == '{basepath}/share/pkg_name/hook/one.ext' \ .format_map(locals()) assert hooks[1] == '{basepath}/share/pkg_name/hook/two.ext' \ .format_map(locals()) # the raised exception is catched and results in an error message assert error.call_count == 1 assert len(error.call_args[0]) == 1 assert error.call_args[0][0].startswith( "Exception in environment extension 'extension2': \n")
async def build(self, *, additional_hooks=None): # noqa: D102 pkg = self.context.pkg args = self.context.args logger.info( "Building Python package in '{args.path}'".format_map(locals())) try: env = await get_command_environment( 'setup_py', args.build_base, self.context.dependencies) except RuntimeError as e: logger.error(str(e)) return 1 setup_py_data = get_setup_data(self.context.pkg, env) # `setup.py egg_info` requires the --egg-base to exist os.makedirs(args.build_base, exist_ok=True) # `setup.py develop|install` requires the python lib path to exist python_lib = os.path.join( args.install_base, self._get_python_lib(args)) os.makedirs(python_lib, exist_ok=True) # and being in the PYTHONPATH env = dict(env) env['PYTHONPATH'] = python_lib + os.pathsep + \ env.get('PYTHONPATH', '') if not args.symlink_install: rc = await self._undo_develop(pkg, args, env) if rc and rc.returncode: return rc.returncode # invoke `setup.py install` step with lots of arguments # to avoid placing any files in the source space cmd = [ executable, 'setup.py', 'egg_info', '--egg-base', args.build_base, 'build', '--build-base', os.path.join( args.build_base, 'build'), 'install', '--prefix', args.install_base, '--record', os.path.join(args.build_base, 'install.log'), # prevent installation of dependencies specified in setup.py '--single-version-externally-managed', ] self._append_install_layout(args, cmd) rc = await check_call(self.context, cmd, cwd=args.path, env=env) if rc and rc.returncode: return rc.returncode else: self._undo_install(pkg, args, setup_py_data, python_lib) self._symlinks_in_build(args, setup_py_data) # invoke `setup.py develop` step in build space # to avoid placing any files in the source space # --editable causes this to skip creating/editing the # easy-install.pth file cmd = [ executable, 'setup.py', 'develop', '--prefix', args.install_base, '--editable', '--build-directory', os.path.join(args.build_base, 'build'), '--no-deps', ] if setup_py_data.get('data_files'): cmd += ['install_data', '--install-dir', args.install_base] self._append_install_layout(args, cmd) rc = await check_call( self.context, cmd, cwd=args.build_base, env=env) if rc and rc.returncode: return rc.returncode # explicitly add the build directory to the PYTHONPATH # to maintain the desired order if additional_hooks is None: additional_hooks = [] base_path = args.build_base # if the Python packages are in a subdirectory # that needs to be appended to the build directory package_dir = setup_py_data.get('package_dir') or {} if '' in package_dir: base_path = os.path.join(base_path, package_dir['']) additional_hooks += create_environment_hook( 'pythonpath_develop', Path(base_path), pkg.name, 'PYTHONPATH', base_path, mode='prepend') hooks = create_environment_hooks(args.install_base, pkg.name) create_environment_scripts( pkg, args, default_hooks=hooks, additional_hooks=additional_hooks)
async def build(self, *, additional_hooks=None): # noqa: D102 pkg = self.context.pkg args = self.context.args logger.info( "Building Python package in '{args.path}'".format_map(locals())) try: env = await get_command_environment( 'setup_py', args.build_base, self.context.dependencies) except RuntimeError as e: logger.error(str(e)) return 1 setup_py_data = get_setup_data(self.context.pkg, env) # `setup.py egg_info` requires the --egg-base to exist os.makedirs(args.build_base, exist_ok=True) # `setup.py develop|install` requires the python lib path to exist python_lib = os.path.join( args.install_base, self._get_python_lib(args)) os.makedirs(python_lib, exist_ok=True) # and being in the PYTHONPATH env = dict(env) env['PYTHONPATH'] = python_lib + os.pathsep + \ env.get('PYTHONPATH', '') if not args.symlink_install: rc = await self._undo_develop(pkg, args, env) if rc and rc.returncode: return rc.returncode # invoke `setup.py install` step with lots of arguments # to avoid placing any files in the source space cmd = [ executable, 'setup.py', 'egg_info', '--egg-base', args.build_base, 'build', '--build-base', os.path.join( args.build_base, 'build'), 'install', '--prefix', args.install_base, '--record', os.path.join(args.build_base, 'install.log'), # prevent installation of dependencies specified in setup.py '--single-version-externally-managed', ] self._append_install_layout(args, cmd) cmd += [ 'bdist_egg', '--dist-dir', os.path.join( args.build_base, 'dist'), ] rc = await check_call(self.context, cmd, cwd=args.path, env=env) if rc and rc.returncode: return rc.returncode else: self._undo_install(pkg, args, setup_py_data, python_lib) self._symlinks_in_build(args, setup_py_data) # invoke `setup.py develop` step in build space # to avoid placing any files in the source space cmd = [ executable, 'setup.py', 'develop', '--prefix', args.install_base, '--no-deps', ] if setup_py_data.get('data_files', []): cmd += ['install_data', '--install-dir', args.install_base] self._append_install_layout(args, cmd) rc = await check_call( self.context, cmd, cwd=args.build_base, env=env) if rc and rc.returncode: return rc.returncode hooks = create_environment_hooks(args.install_base, pkg.name) create_environment_scripts( pkg, args, default_hooks=hooks, additional_hooks=additional_hooks)