def test_variant_install(self): """test variant installation.""" repo_path = os.path.join(self.root, "packages") if not os.path.exists(repo_path): os.makedirs(repo_path) def _data(obj): d = obj.validated_data() keys = package_release_keys + ("base", ) for key in keys: d.pop(key, None) return d # package with variants and package without dev_pkgs_list = (("developer", "developer_changed"), ("developer_novar", "developer_novar_changed")) for path1, path2 in dev_pkgs_list: path = os.path.join(self.packages_base_path, path1) package = get_developer_package(path) # install variants of the developer package into new repo variant = next(package.iter_variants()) result = variant.install(repo_path, dry_run=True) self.assertEqual(result, None) for variant in package.iter_variants(): variant.install(repo_path) variant = next(package.iter_variants()) result = variant.install(repo_path, dry_run=True) self.assertNotEqual(result, None) # now there should be a package that matches the dev package installed_package = get_package(package.name, package.version, paths=[repo_path]) data = _data(package) data_ = _data(installed_package) self.assertDictEqual(data, data_) # make a change in the dev pkg, outside of the variants. path = os.path.join(self.packages_base_path, path2) package = get_developer_package(path) # install a variant again. Even though the variant is already installed, # this should update the package, because data outside the variant changed. variant = next(package.iter_variants()) result = variant.install(repo_path, dry_run=True) self.assertEqual(result, None) variant.install(repo_path) # check that the change was applied. This effectively also checks that the # variant order hasn't changed. installed_package = get_package(package.name, package.version, paths=[repo_path]) data = _data(package) data_ = _data(installed_package) self.assertDictEqual(data, data_)
def _make_package(help_=tuple()): """Make a Rez package with the given help attribute for testing. Args: help_ (str or list[list[str, str]]): A single help string or a list of display + help string pairs. The left of the pair is the text users might see. The right side is either an absolute or relative path on-disk or a website URL. Returns: :class:`rez.packages.DeveloperPackage`: The generated package. """ directory = tempfile.mkdtemp(suffix="_make_package") atexit.register(functools.partial(shutil.rmtree, directory)) name = "does_not_matter" version = "1.0.0" with package_maker.make_package(name, directory) as maker: maker.name = name maker.version = version maker.help = help_ return packages_.get_developer_package( os.path.join(directory, name, version))
def _FWD__spawn_build_shell(working_dir, build_path, variant_index, install, install_path=None): # This spawns a shell that the user can run the build command in directly context = ResolvedContext.load(os.path.join(build_path, "build.rxt")) package = get_developer_package(working_dir) variant = package.get_variant(variant_index) config.override("prompt", "BUILD>") actions_callback = functools.partial(CustomBuildSystem._add_build_actions, context=context, package=package, variant=variant, build_type=BuildType.local, install=install, build_path=build_path, install_path=install_path) post_actions_callback = functools.partial( CustomBuildSystem.add_pre_build_commands, variant=variant, build_type=BuildType.local, install=install, build_path=build_path, install_path=install_path) retcode, _, _ = context.execute_shell( block=True, cwd=build_path, actions_callback=actions_callback, post_actions_callback=post_actions_callback) sys.exit(retcode)
def __init__(self, working_dir, opts=None, package=None, write_build_scripts=False, verbose=False, build_args=[], child_build_args=[]): """Create a build system instance. Args: working_dir: Directory to build source from. opts: argparse.Namespace object which may contain constructor params, as set by our bind_cli() classmethod. package (`DeveloperPackage`): Package to build. If None, defaults to the package in the working directory. write_build_scripts: If True, create build scripts rather than perform the full build. The user can then run these scripts to place themselves into a build environment and invoke the build system directly. build_args: Extra cli build arguments. child_build_args: Extra cli args for child build system, ignored if there is no child build system. """ self.working_dir = working_dir if not self.is_valid_root(working_dir): raise BuildSystemError( "Not a valid working directory for build system %r: %s" % (self.name(), working_dir)) self.package = package or get_developer_package(working_dir) self.write_build_scripts = write_build_scripts self.build_args = build_args self.child_build_args = child_build_args self.verbose = verbose self.opts = opts
def test_4(self): """Test package config overrides.""" conf = os.path.join(self.config_path, "test2.py") config2 = Config([self.root_config_file, conf]) with _replace_config(config2): pkg = get_developer_package(self.config_path) c = pkg.config self._test_basic(c) # check overrides from package.py are working os.environ["REZ_BUILD_DIRECTORY"] = "foo" # should have no effect self.assertEqual(c.build_directory, "weeble") self.assertEqual(c.plugins.release_vcs.tag_name, "tag") # check list modification is working self.assertEqual(c.release_hooks, ["foo", "bah"]) # check list modification within plugin settings is working self.assertEqual(c.plugins.release_hook.emailer.recipients, ["*****@*****.**", "*****@*****.**"]) # check system expansion in package overridden setting works expected_value = "*****@*****.**" % system.user self.assertEqual(c.plugins.release_hook.emailer.sender, expected_value) # check env-var expansion in package overridden setting works os.environ["FUNK"] = "dude" expected_value = ["FOO", "BAH_dude", "EEK"] self.assertEqual(c.parent_variables, expected_value) self._test_overrides(c)
def is_valid_root(cls, path, package=None): if package is None: try: package = get_developer_package(path) except PackageMetadataError: return False return (getattr(package, "build_command", None) is not None)
def get_current_developer_package(): from rez.packages import get_developer_package global _package if _package is None: _package = get_developer_package(os.getcwd()) return _package
def __init__(self, source_path): """Create a release hook. Args: source_path: Path containing source that was released. """ self.source_path = source_path self.package = get_developer_package(source_path) self.type_settings = self.package.config.plugins.release_hook self.settings = self.type_settings.get(self.name())
def test_developer_dynamic_global_preprocess_string(self): """test developer package with a global preprocess function as string""" # a developer package with features such as expanding requirements, # global preprocessing self.update_settings( {"package_preprocess_function": "global_preprocess.inject_data"}) path = os.path.join(self.packages_base_path, "developer_dynamic_global_preprocess") package = get_developer_package(path) self.assertEqual(package.description, "This.") self.assertEqual(package.added_by_global_preprocess, True)
def test_developer_pkg(self): """test developer package.""" path = os.path.join(self.packages_base_path, "developer") package = get_developer_package(path) expected_data = dict(name="foo", version=Version("3.0.1"), description="a foo type thing.", authors=["joe.bloggs"], requires=[PackageRequest('bah-1.2+<2')], variants=[[PackageRequest('floob-4.1')], [PackageRequest('floob-2.0')]], uuid="28d94bcd1a934bb4999bcf70a21106cc") data = package.validated_data() self.assertDictEqual(data, expected_data)
def get_current_developer_package(): from rez.packages import get_developer_package from rez.exceptions import PackageMetadataError global _package if _package is None: try: _package = get_developer_package(os.getcwd()) except PackageMetadataError: # no package, or bad package pass return _package
def get_valid_build_systems(working_dir, package=None): """Returns the build system classes that could build the source in given dir. Args: working_dir (str): Dir containing the package definition and potentially build files. package (`Package`): Package to be built. This may or may not be needed to determine the build system. For eg, cmake just has to look for a CMakeLists.txt file, whereas the 'build_command' package field must be present for the 'custom' build system type. Returns: List of class: Valid build system class types. """ from rez.plugin_managers import plugin_manager from rez.exceptions import PackageMetadataError try: package = package or get_developer_package(working_dir) except PackageMetadataError: # no package, or bad package pass if package: if getattr(package, "build_command", None) is not None: buildsys_name = "custom" else: buildsys_name = getattr(package, "build_system", None) # package explicitly specifies build system if buildsys_name: cls = plugin_manager.get_plugin_class('build_system', buildsys_name) return [cls] # detect valid build systems clss = [] for buildsys_name in get_buildsys_types(): cls = plugin_manager.get_plugin_class('build_system', buildsys_name) if cls.is_valid_root(working_dir, package=package): clss.append(cls) # Sometimes files for multiple build systems can be present, because one # build system uses another (a 'child' build system) - eg, cmake uses # make. Detect this case and ignore files from the child build system. # child_clss = set(x.child_build_system() for x in clss) clss = list(set(clss) - child_clss) return clss
def __init__(self, pkg_root, vcs_root=None): if vcs_root is None: result = self.find_vcs_root(pkg_root) if not result: raise ReleaseVCSError("Could not find %s repository for the " "path %s" % (self.name(), pkg_root)) vcs_root = result[0] else: assert(self.is_valid_root(vcs_root)) self.vcs_root = vcs_root self.pkg_root = pkg_root self.package = get_developer_package(pkg_root) self.type_settings = self.package.config.plugins.release_vcs self.settings = self.type_settings.get(self.name())
def test_developer_dynamic_global_preprocess_func(self): """test developer package with a global preprocess function as function""" # a developer package with features such as expanding requirements, # global preprocessing def preprocess(this, data): data["dynamic_attribute_added"] = {'test': True} self.update_settings({"package_preprocess_function": preprocess}) path = os.path.join(self.packages_base_path, "developer_dynamic_global_preprocess") package = get_developer_package(path) self.assertEqual(package.description, "This.") self.assertEqual(package.dynamic_attribute_added, {'test': True})
def test_developer_dynamic_local_preprocess(self): """test developer package with a local preprocess function""" # a developer package with features such as expanding requirements, # early-binding attribute functions, and preprocessing # Here we will also verifies that the local preprocess function wins over # the global one. self.update_settings( {"package_preprocess_function": "global_preprocess.inject_data"}) path = os.path.join(self.packages_base_path, "developer_dynamic_local_preprocess") package = get_developer_package(path) self.assertEqual(package.description, "This.") self.assertEqual(package.requires, [PackageRequest('versioned-3')]) self.assertEqual(package.authors, ["tweedle-dee", "tweedle-dum"]) self.assertFalse(hasattr(package, "added_by_global_preprocess")) self.assertEqual(package.added_by_local_preprocess, True)
def test_developer_dynamic_after(self): """test developer package with both global and local preprocess in after mode""" # a developer package with features such as expanding requirements, # global preprocessing def preprocess(this, data): data["dynamic_attribute_added"] = {'value_set_by': 'global'} data["added_by_global_preprocess"] = True self.update_settings( { "package_preprocess_function": preprocess, "package_preprocess_mode": "after" } ) path = os.path.join(self.packages_base_path, "developer_dynamic_local_preprocess_additive") package = get_developer_package(path) self.assertEqual(package.description, "This.") self.assertEqual(package.authors, ["tweedle-dee", "tweedle-dum"]) self.assertEqual(package.dynamic_attribute_added, {'value_set_by': 'local'}) self.assertEqual(package.added_by_global_preprocess, True) self.assertEqual(package.added_by_local_preprocess, True)
def command(opts, parser, extra_arg_groups=None): from rez.packages import get_developer_package from rez.serialise import FileFormat from rez.exceptions import PackageMetadataError import os.path import os import sys if opts.PATH: path = os.path.expanduser(opts.PATH) else: path = os.getcwd() try: package = get_developer_package(path, format=FileFormat.yaml) except PackageMetadataError: package = None if package is None: print("Couldn't load the package at %r" % path, file=sys.stderr) sys.exit(1) package.print_info(format_=FileFormat.py)
def build_eggs( # pylint: disable=too-many-arguments source, destination, eggs, symlink=linker.must_symlink(), symlink_folders=linker.must_symlink_folders(), symlink_files=linker.must_symlink_files(), data_patterns=None, ): """Copy or symlink all items in ``source`` to ``destination``. Args: source (str): The absolute path to the root directory of the Rez package. destination (str): The location where the built files will be copied or symlinked from. eggs (iter[str], optional): The local paths which will be compressed into .egg (zip) files. Default is None. symlink (bool, optional): If True, symlinking will always happen. It implies If ``symlink_folders`` and ``symlink_files`` are both True. If False, symlinking is not guaranteed to always happen. symlink_folders (bool, optional): If True and ``source`` is a folder, make a symlink from ``destination`` which points back to ``source``. If False, run ``command`` instead. symlink_files (bool, optional): If True and ``source`` is a file, make a symlink from ``destination`` which points back to ``source``. If False, run ``command`` instead. """ _validate_egg_names(eggs) if not data_patterns: data_patterns = set() package = packages.get_developer_package( os.path.dirname(os.environ["REZ_BUILD_PROJECT_FILE"])) platform = _get_platform() if platform: platforms = [platform] else: # This is apparently a common value to many "Linux, Windows, etc" platforms = ["any"] setuptools_data = _SetuptoolsData( package_name=os.environ["REZ_BUILD_PROJECT_NAME"], version=os.environ["REZ_BUILD_PROJECT_VERSION"], description=os.environ["REZ_BUILD_PROJECT_DESCRIPTION"], author=", ".join(package.authors or []), url=_find_api_documentation(package.help or []), python_requires=_get_python_requires(), platforms=platforms, ) for name in eggs: _run_command( functools.partial( _build_eggs, name=name, setuptools_data=setuptools_data, data_patterns=data_patterns, ), os.path.join(source, name), os.path.join(destination, name + ".egg"), symlink, symlink_folders, symlink_files, )