def bind(path, version_range=None, opts=None, parser=None): rez_version = Version(rez.__version__) check_version(rez_version, version_range) rez_major_version = rez_version.trim(1) rez_major_minor_version = rez_version.trim(2) next_major = int(str(rez_major_version)) + 1 rez_req_str = "rez-%s+<%d" % (str(rez_major_minor_version), next_major) gui_lib = getattr(opts, "gui_lib", "") def make_root(variant, root): # copy source rez_path = rez.__path__[0] site_path = os.path.dirname(rez_path) rezgui_path = os.path.join(site_path, "rezgui") shutil.copytree(rezgui_path, os.path.join(root, "rezgui")) # create rez-gui executable binpath = make_dirs(root, "bin") filepath = os.path.join(binpath, "rez-gui") create_executable_script(filepath, rez_gui_source) # create package with make_package("rezgui", path, make_root=make_root) as pkg: pkg.version = rez_version pkg.variants = [system.variant] pkg.commands = commands pkg.tools = ["rez-gui"] pkg.requires = [rez_req_str] if gui_lib: pkg.requires.append(gui_lib) return "rezgui", rez_version
def create_context(pip_version=None, python_version=None): """Create a context containing the specific pip and python. Args: pip_version (str or `Version`): Version of pip to use, or latest if None. python_version (str or `Version`): Python version to use, or latest if None. Returns: `ResolvedContext`: Context containing pip and python. """ # determine pip pkg to use for install, and python variants to install on if pip_version: pip_req = "pip-%s" % str(pip_version) else: pip_req = "pip" if python_version: ver = Version(str(python_version)) major_minor_ver = ver.trim(2) py_req = "python-%s" % str(major_minor_ver) else: # use latest major.minor package = get_latest_package("python") if package: major_minor_ver = package.version.trim(2) else: # no python package. We're gonna fail, let's just choose current # python version (and fail at context creation time) major_minor_ver = ".".join(map(str, sys.version_info[:2])) py_req = "python-%s" % str(major_minor_ver) # use pip + latest python to perform pip download operations request = [pip_req, py_req] with convert_errors( from_=(PackageFamilyNotFoundError, PackageNotFoundError), to=BuildError, msg="Cannot run - pip or python rez " "package is not present", ): context = ResolvedContext(request) # print pip package used to perform the install pip_variant = context.get_resolved_package("pip") pip_package = pip_variant.parent print_info("Using %s (%s)" % (pip_package.qualified_name, pip_variant.uri)) return context
def __init__(self, parent=None): super(AboutDialog, self).__init__(parent) self.setWindowTitle("About Rez") version = Version(__version__) public_version = version.trim(2) label = QtGui.QLabel( "<font size='+2'><b>Rez version %s</b></font><br><br>" "Build version %s." % (str(public_version), str(version))) close_btn = QtGui.QPushButton("Close") github_btn = QtGui.QPushButton("Github") github_icon = get_icon("github_32", as_qicon=True) github_btn.setIcon(github_icon) btn_pane = create_pane([None, github_btn, close_btn], True, compact=True) create_pane([label, None, btn_pane], False, parent_widget=self) github_btn.clicked.connect(self._goto_github) close_btn.clicked.connect(self.close) close_btn.setFocus()
def _load(self): data = self.parent._data.copy() if "versions" in data: del data["versions"] version_str = self.get("version") data["version"] = version_str version = Version(version_str) overrides = self.parent.version_overrides if overrides: for range_, data_ in overrides.iteritems(): if version in range_: data.update(data_) del data["version_overrides"] return data
def test_4(self): """test package creation.""" package_data = { "name": "foo", "version": "1.0.0", "description": "something foo-like", "requires": ["python-2.6+"]} package = create_package("foo", package_data) self.assertEqual(package.version, Version("1.0.0")) self.assertEqual(package.description, "something foo-like") self.assertEqual(package.requires, [PackageRequest("python-2.6+")]) family = package.parent self.assertEqual(family.name, package.name) packages = list(family.iter_packages()) self.assertEqual(len(packages), 1) self.assertEqual(package, packages[0])
def test_6(self): """test variant iteration.""" expected_data = dict( name="variants_py", version=Version("2.0"), description="package with variants", base=os.path.join(self.py_packages_path, "variants_py", "2.0"), requires=[PackageRequest("python-2.7")], commands=SourceCode('env.PATH.append("{root}/bin")')) requires_ = ["platform-linux", "platform-osx"] package = get_package("variants_py", "2.0") for i, variant in enumerate(package.iter_variants()): data = variant.validated_data() self.assertDictEqual(data, expected_data) self.assertEqual(variant.index, i) self.assertEqual(variant.parent, package)
def bind(path, version_range=None, opts=None, parser=None): version = Version("1.0") check_version(version, version_range) def make_root(variant, root): binpath = make_dirs(root, "bin") filepath = os.path.join(binpath, "hello_world") create_executable_script( filepath, hello_world_source, py_script_mode=ExecutableScriptMode.platform_specific) with make_package("hello_world", path, make_root=make_root) as pkg: pkg.version = version pkg.tools = ["hello_world"] pkg.commands = commands return pkg.installed_variants
def test_reorder(self): """Test ordering.""" expected_null_result = ["7", "6", "5"] expected_split_result = ["2.6.0", "2.5.2", "2.7.0", "2.6.8"] expected_timestamp_result = [ "1.1.1", "1.1.0", "1.0.6", "1.0.5", "1.2.0", "2.0.0", "2.1.5", "2.1.0" ] orderer = PerFamilyOrder(order_dict=dict( pysplit=NullPackageOrder(), python=VersionSplitPackageOrder(Version("2.6.0")), timestamped=TimestampPackageOrder(timestamp=3001, rank=3)), default_order=SortedOrder(descending=False)) self._test_reorder(orderer, "pysplit", expected_null_result) self._test_reorder(orderer, "python", expected_split_result) self._test_reorder(orderer, "timestamped", expected_timestamp_result) self._test_reorder(orderer, "pymum", ["1", "2", "3"])
def test_9(self): """test package orderers.""" from rez.package_order import NullPackageOrder, PerFamilyOrder, \ VersionSplitPackageOrder, TimestampPackageOrder, SortedOrder, \ to_pod, from_pod def _test(orderer, package_name, expected_order): it = iter_packages(package_name) descending = sorted(it, key=lambda x: x.version, reverse=True) pod = to_pod(orderer) orderer2 = from_pod(pod) for orderer_ in (orderer, orderer2): ordered = orderer_.reorder(descending) result = [str(x.version) for x in ordered] self.assertEqual(result, expected_order) null_orderer = NullPackageOrder() split_orderer = VersionSplitPackageOrder(Version("2.6.0")) timestamp_orderer = TimestampPackageOrder(timestamp=3001, rank=3) expected_null_result = ["7", "6", "5"] expected_split_result = ["2.6.0", "2.5.2", "2.7.0", "2.6.8"] expected_timestamp_result = [ "1.1.1", "1.1.0", "1.0.6", "1.0.5", "1.2.0", "2.0.0", "2.1.5", "2.1.0" ] _test(null_orderer, "pysplit", expected_null_result) _test(split_orderer, "python", expected_split_result) _test(timestamp_orderer, "timestamped", expected_timestamp_result) fam_orderer = PerFamilyOrder( order_dict=dict(pysplit=null_orderer, python=split_orderer, timestamped=timestamp_orderer), default_order=SortedOrder(descending=False)) _test(fam_orderer, "pysplit", expected_null_result) _test(fam_orderer, "python", expected_split_result) _test(fam_orderer, "timestamped", expected_timestamp_result) _test(fam_orderer, "pymum", ["1", "2", "3"])
def install_variant(self, variant_resource, dry_run=False, overrides=None): if not self.is_connected: raise PackageRepositoryError("%s is not connected to [%s]." % (self.location, self.database_uri)) overrides = overrides or {} # Name and version overrides are a special case - they change the # destination variant to be created/replaced. # variant_name = variant_resource.name variant_version = variant_resource.version if "name" in overrides: variant_name = overrides["name"] if variant_name is self.remove: raise PackageRepositoryError( "Cannot remove package attribute 'name'") if "version" in overrides: ver = overrides["version"] if ver is self.remove: raise PackageRepositoryError( "Cannot remove package attribute 'version'") if isinstance(ver, basestring): ver = Version(ver) overrides = overrides.copy() overrides["version"] = ver variant_version = ver # cannot install over one's self, just return existing variant if variant_resource._repository is self and \ variant_name == variant_resource.name and \ variant_version == variant_resource.version: return variant_resource # install the variant variant = self._create_variant(variant_resource, dry_run=dry_run, overrides=overrides) return variant
def remove_package(name, version, path): """Remove a package from its repository. Note that you are able to remove a package that is hidden (ie ignored). This is why a Package instance is not specified (if the package were hidden, you wouldn't be able to get one). Args: name (str): Name of package. version (Version or str): Version of the package, eg '1.0.0' path (str): Package repository path containing the package. Returns: bool: True if the package was removed, False if package not found. """ if isinstance(version, basestring): version = Version(version) repo = package_repository_manager.get_repository(path) return repo.remove_package(name, version)
def get_package_from_repository(name, version, path): """Get a package from a repository. Args: name (str): Name of the package, eg 'maya'. version (Version or str): Version of the package, eg '1.0.0' Returns: `Package` object, or None if the package was not found. """ repo = package_repository_manager.get_repository(path) if isinstance(version, basestring): version = Version(version) package_resource = repo.get_package(name, version) if package_resource is None: return None return Package(package_resource)
def bind(path, version_range=None, opts=None, parser=None): # find executable, determine version if opts and opts.root: bin_path = opts.root else: possible_paths = [r'C:\Program Files (x86)\QuickTime'] for root_path in possible_paths: if os.path.exists(root_path): bin_path = root_path break else: raise EnvironmentError( 'Unable to find Quicktime on this system in the paths; {}'.format( ', '.join(possible_paths) ) ) if platform_.name == 'windows': from win32api import GetFileVersionInfo, LOWORD, HIWORD try: info = GetFileVersionInfo(os.path.join(bin_path, 'QuickTimePlayer.exe'), "\\") ms = info['FileVersionMS'] ls = info['FileVersionLS'] version = Version('{}.{}.{}.{}'.format(HIWORD(ms), LOWORD(ms), HIWORD(ls), LOWORD(ls))) except: raise EnvironmentError('Unknown version') else: raise EnvironmentError('Only binds on windows at the moment') check_version(version, version_range) with make_package("quicktime", path) as pkg: pkg.version = version if platform_.name == 'windows': pkg.tools = ["QuickTimePlayer.exe"] pkg.commands = win_commands(bin_path) else: raise EnvironmentError('Only binds on windows at the moment') pkg.variants = [system.variant] return "quicktime", version
def test_package_remove(self): """Test package remove.""" pkg_name = "pydad" pkg_version = Version("2") # copy packages to a temp repo repo_path = os.path.join(self.root, "tmp4_packages") shutil.copytree(self.solver_packages_path, repo_path) # verify that source pkg exists src_pkg = get_package_from_repository(pkg_name, pkg_version, repo_path) self.assertNotEqual(src_pkg, None) # remove it was_removed = remove_package(pkg_name, pkg_version, repo_path) self.assertTrue(was_removed) # verify that source pkg no longer exists (and isn't simply ignored) repo = package_repository_manager.get_repository(repo_path) i = repo.unignore_package(pkg_name, pkg_version) self.assertEqual(i, -1)
def extract_version(exepath, version_arg, word_index=-1, version_rank=3): """Run an executable and get the program version. Args: exepath: Filepath to executable. version_arg: Arg to pass to program, eg "-V". Can also be a list. word_index: Expect the Nth word of output to be the version. version_rank: Cap the version to this many tokens. Returns: `Version` object. """ if isinstance(version_arg, basestring): version_arg = [version_arg] args = [exepath] + version_arg log("running: %s" % ' '.join(args)) p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate() if p.returncode: raise RezBindError("failed to execute %s: %s\n(error code %d)" % (exepath, stderr, p.returncode)) stdout = stdout.strip().split('\n')[0].strip() log("extracting version from output: '%s'" % stdout) try: strver = stdout.split()[word_index] toks = strver.replace('.', ' ').replace('-', ' ').split() strver = '.'.join(toks[:version_rank]) version = Version(strver) except Exception as e: raise RezBindError("failed to parse version from output '%s': %s" % (stdout, str(e))) log("extracted version: '%s'" % str(version)) return version
def test_singleton(self): """Validate we can build a PackageOrderList object from configuration values.""" config.override("package_orderers", [{ "type": "per_family", "orderers": [{ "packages": ["python"], "type": "version_split", "first_version": "2.9.9" }] }]) expected = PackageOrderList() expected.append( PerFamilyOrder(order_dict={ "python": VersionSplitPackageOrder(Version("2.9.9")) })) # Clear @classproperty cache try: delattr(PackageOrderList, '_class_property_singleton') except AttributeError: pass self.assertEqual(expected, PackageOrderList.singleton)
def test_5(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) # a developer package with features such as expanding requirements, # early-binding attribute functions, and preprocessing path = os.path.join(self.packages_base_path, "developer_dynamic") 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"])
def bind(path, version_range=None, opts=None, parser=None): version = Version(system.platform) check_version(version, version_range) def post_commands(): """Setup default XDG_* environment variables. https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html#variables """ import os xdg_defaults = ( ('XDG_DATA_HOME', ['$HOME/.local/share']), ('XDG_DATA_DIRS', ['/usr/local/share', '/usr/share']), ('XDG_CONFIG_HOME', ['$HOME/.config']), ('XDG_CONFIG_DIRS', ['/etc/xdg']), ('XDG_CACHE_HOME', ['$HOME/.cache']), ) for xdg_var, defaults in xdg_defaults: invalid_var = undefined(xdg_var) or not str(env[xdg_var]) paths = [] if invalid_var else str(env[xdg_var]).split(os.pathsep) append = len(defaults) != 1 for default_path in defaults: expanded = expandvars(default_path) if not (default_path in paths or expanded in paths): if append: env[xdg_var].append(expanded) else: env[xdg_var] = expanded with make_package("platform", path) as pkg: pkg.version = version pkg.relocatable = True if system.platform == 'linux': pkg.post_commands = post_commands return pkg.installed_variants
def test_remove_packages_ignored_since(self): pkg_name = "pydad" pkg_version = Version("2") # copy packages to a temp repo repo_path = os.path.join(self.root, "tmp5_packages") shutil.copytree(self.solver_packages_path, repo_path) # verify that source pkg exists src_pkg = get_package_from_repository(pkg_name, pkg_version, repo_path) self.assertNotEqual(src_pkg, None) # ignore it repo = package_repository_manager.get_repository(repo_path) i = repo.ignore_package(pkg_name, pkg_version) self.assertEqual(i, 1) # remove all ignored packages num_removed = remove_packages_ignored_since(days=0, paths=[repo_path]) self.assertEqual(num_removed, 1) # verify that source pkg no longer exists (and isn't simply ignored) i = repo.unignore_package(pkg_name, pkg_version) self.assertEqual(i, -1)
def _decode(obj): if not isinstance(obj, dict): return obj if "::rez:sourcecode::" in obj: value = obj["::rez:sourcecode::"] source_code = SourceCode() # Reference: SourceCode.__setstate__ source_code.source = value["source"] source_code.filepath = value["filepath"] source_code.funcname = value["funcname"] source_code.eval_as_function = value["eval_as_function"] source_code.decorators = value["decorators"] return source_code if "::rez:version::" in obj: value = obj["::rez:version::"] return Version(value["version"]) return obj
def find_pip_from_context(python_version, pip_version=None): """Find pip from rez context. Args: python_version (str or `Version`): Python version to use pip_version (str or `Version`): Version of pip to use, or latest. Returns: 3-tuple: - str: Python executable or None if we fell back to system pip. - str: Pip version or None if we fell back to system pip. - `ResolvedContext`: Context containing pip, or None if we fell back to system pip. """ target = "python" package_request = [] if python_version: ver = Version(str(python_version)) python_major_minor_ver = ver.trim(2) else: # use latest major.minor package = get_latest_package("python") if package: python_major_minor_ver = package.version.trim(2) else: raise BuildError("Found no python package.") python_package = "python-%s" % str(python_major_minor_ver) package_request.append(python_package) if pip_version: target = "pip" if pip_version == "latest": package_request.append("pip") else: package_request.append("pip-%s" % str(pip_version)) print_info("Trying to use pip from %s package", target) try: context = ResolvedContext(package_request) except (PackageFamilyNotFoundError, PackageNotFoundError): print_debug("No rez package called %s found", target) return None, None, None py_exe_name = "python" if platform_.name != "windows": # Python < 2 on Windows doesn't have versionned executable. py_exe_name += str(python_major_minor_ver.trim(1)) py_exe = context.which(py_exe_name) proc = context.execute_command( # -E and -s are used to isolate the environment as much as possible. # See python --help for more details. We absolutely don't want to get # pip from the user home. [ py_exe, "-E", "-s", "-c", "import pip, sys; sys.stdout.write(pip.__version__)" ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) out, err = proc.communicate() if proc.returncode: print_debug("Failed to get pip from package %s", target) print_debug(out) print_debug(err) return None, None, None pip_version = out.strip() variant = context.get_resolved_package(target) package = variant.parent print_info("Found pip-%s inside %s. Will use it with %s", pip_version, package.uri, py_exe) return py_exe, pip_version, context
def bind(path, version_range=None, opts=None, parser=None): if platform_.name != 'windows': raise EnvironmentError('Only binds on windows at the moment') # find executable, determine version if opts and opts.root: bin_path = opts.root else: installed_versions = [] autodesk_root = r'C:\Program Files\Autodesk' for app_folder in os.listdir(autodesk_root): if app_folder.startswith('3ds Max'): installed_versions.append( (app_folder, Version(app_folder.replace('3ds Max', '').strip()))) if len(installed_versions) < 1: raise EnvironmentError( 'Unable to find any installed version of 3ds Max under "{}"'. format(autodesk_root)) app_folder, version = sorted(installed_versions, key=lambda v: v[1])[-1] bin_path = os.path.join(autodesk_root, app_folder) from win32api import GetFileVersionInfo, LOWORD, HIWORD try: info = GetFileVersionInfo(os.path.join(bin_path, '3dsmax.exe'), "\\") ms = info['FileVersionMS'] ls = info['FileVersionLS'] version = Version('{}.{}.{}.{}'.format(HIWORD(ms), LOWORD(ms), HIWORD(ls), LOWORD(ls))) except: raise EnvironmentError('Unknown version') check_version(version, version_range) def make_root(resources_path, variant, path): import shutil shutil.copy(os.path.join(resources_path, '3dsmax_icon.png'), os.path.join(path, '3dsmax_icon.png')) make_root_partial = functools.partial( make_root, resource_filename(Requirement.parse('rez'), "rez/bind/resources")) with make_package("3dsmax", path, make_root=make_root_partial) as pkg: pkg.version = version pkg.tools = ["3dsmax"] pkg.description = '3D DCC application' pkg.authors = ['Autodesk'] pkg.requires = ['roaming_user'] pkg.nice_name = '3DS Max' pkg.tools_info = { '3dsmax': { 'command': [ 'start', '3DSMax', '/D', '%ADSK_3DSMAX_x64_2015%', '/wait', '/B', '3dsmax.exe' ], 'nice_name': '3ds Max', 'priority': 89, 'icon': '{root}/3dsmax_icon.png', 'launch_in_prompt': False } } pkg.commands = win_commands(bin_path) pkg.variants = [system.variant] return "3dsmax", version
def _create_random_version(self): ver_str = '.'.join(self.make_token.create_random_token_string() for i in range(random.randint(0, 6))) return Version(ver_str, make_token=self.make_token)
def test_version_range(self): def _eq(a, b): _print("'%s' == '%s'" % (a, b)) a_range = VersionRange(a) b_range = VersionRange(b) self.assertTrue(a_range == b_range) self.assertTrue(a_range.issuperset(a_range)) self.assertTrue(a_range.issuperset(b_range)) self.assertTrue(VersionRange(str(a_range)) == a_range) self.assertTrue(VersionRange(str(b_range)) == a_range) self.assertTrue(hash(a_range) == hash(b_range)) a_ = a.replace('.', '-') a_ = a_.replace("--", "..") a_range_ = VersionRange(a_) self.assertTrue(a_range_ == a_range) self.assertTrue(hash(a_range_) == hash(a_range)) range_strs = a.split('|') ranges = [VersionRange(x) for x in range_strs] ranges_ = ranges[0].union(ranges[1:]) self.assertTrue(ranges_ == a_range) self.assertTrue(a_range | b_range == a_range) self.assertTrue(a_range - b_range is None) self.assertTrue(b_range - a_range is None) self.assertTrue(VersionRange() & a_range == a_range) self.assertTrue(b_range.span() & a_range == a_range) a_inv = a_range.inverse() self.assertTrue(a_inv == ~b_range) if a_inv: self.assertTrue(~a_inv == a_range) self.assertTrue(a_range | a_inv == VersionRange()) self.assertTrue(a_range & a_inv is None) a_ranges = a_range.split() a_range_ = a_ranges[0].union(a_ranges[1:]) self.assertTrue(a_range_ == b_range) def _and(a, b, c): _print("'%s' & '%s' == '%s'" % (a, b, c)) a_range = VersionRange(a) b_range = VersionRange(b) c_range = None if c is None else VersionRange(c) self.assertTrue(a_range & b_range == c_range) self.assertTrue(b_range & a_range == c_range) a_or_b = a_range | b_range a_and_b = a_range & b_range a_sub_b = a_range - b_range b_sub_a = b_range - a_range ranges = [a_and_b, a_sub_b, b_sub_a] ranges = [x for x in ranges if x] self.assertTrue(ranges[0].union(ranges[1:]) == a_or_b) def _inv(a, b): a_range = VersionRange(a) b_range = VersionRange(b) self.assertTrue(~a_range == b_range) self.assertTrue(~b_range == a_range) self.assertTrue(a_range | b_range == VersionRange()) self.assertTrue(a_range & b_range is None) # simple cases _print() _eq("", "") _eq("1", "1") _eq("1.0.0", "1.0.0") _eq("3+<3_", "3") _eq("_+<__", "_") _eq("1.2+<=2.0", "1.2..2.0") _eq("10+,<20", "10+<20") _eq("1+<1.0", "1+<1.0") _eq(">=2", "2+") # optimised cases _eq("3|3", "3") _eq("3|1", "1|3") _eq("5|3|1", "1|3|5") _eq("1|1_", "1+<1__") _eq("1|1_|1__", "1+,<1___") _eq("|", "") _eq("||", "||||||||") _eq("1|1_+", "1+") _eq("<1|1", "<1_") _eq("1+<3|3+<5", "1+<5") _eq(">4<6|1+<3", "1+<3|>4,<6") _eq("4+<6|1+<3|", "") _eq("4|2+", "2+") _eq("3|<5", "<5") _eq("<3|>3", ">3|<3") _eq("3+|<3", "") _eq("3+|<4", "") _eq("2+<=6|3+<5", "2..6") _eq("3+,<5|2+<=6", "2+<=6") _eq("2|2+", "2+") _eq("2|2.1+", "2+") _eq("2|<2.1", "<2_") _eq("3..3", "==3") _eq(">=3,<=3", "==3") # AND'ing _and("3", "3", "3") _and("1", "==1", "==1") _and("", "==1", "==1") _and("3", "4", None) _and("<3", "5+", None) _and("4+<6", "6+<8", None) _and("2+", "<=4", "2..4") _and("1", "1.0", "1.0") _and("4..6", "6+<8", "==6") # inverse _inv("3+", "<3") _inv("<=3", ">3") _inv("3.5", "<3.5|3.5_+") self.assertTrue(~VersionRange() is None) # odd (but valid) cases _eq(">", ">") # greater than the empty version _eq("+", "") # greater or equal to empty version (is all vers) _eq(">=", "") # equivalent to above _eq("<=", "==") # less or equal to empty version (is only empty) _eq("..", "==") # from empty version to empty version _eq("+<=", "==") # equivalent to above invalid_range = [ "4+<2", # lower bound greater than upper ">3<3", # both greater and less than same version ">3<=3", # greater and less or equal to same version "3+<3" # greater and equal to, and less than, same version ] for s in invalid_range: self.assertRaises(VersionError, VersionRange, s) invalid_syntax = [ "<", # less than the empty version "><", # both greater and less than empty version ">3>4", # both are lower bounds "<3<4", # both are upper bounds "<4>3", # upper bound before lower ",<4", # leading comma "4+,", # trailing comma "1>=", # pre-lower-op in post "+1", # post-lower-op in pre "4<", # pre-upper-op in post "1+<2<3" # more than two bounds ] for s in invalid_syntax: self.assertRaises(VersionError, VersionRange, s) # test simple logic self.assertTrue(VersionRange("").is_any()) self.assertTrue(VersionRange("2+<4").bounded()) self.assertTrue(VersionRange("2+").lower_bounded()) self.assertTrue(not VersionRange("2+").upper_bounded()) self.assertTrue(not VersionRange("2+").bounded()) self.assertTrue(VersionRange("<2").upper_bounded()) self.assertTrue(not VersionRange("<2").lower_bounded()) self.assertTrue(not VersionRange("<2").bounded()) # test range from version(s) v = Version("3") self.assertTrue( VersionRange.from_version(v, "eq") == VersionRange("==3")) self.assertTrue( VersionRange.from_version(v, "gt") == VersionRange(">3")) self.assertTrue( VersionRange.from_version(v, "gte") == VersionRange("3+")) self.assertTrue( VersionRange.from_version(v, "lt") == VersionRange("<3")) self.assertTrue( VersionRange.from_version(v, "lte") == VersionRange("<=3")) range1 = VersionRange.from_version(Version("2"), "gte") range2 = VersionRange.from_version(Version("4"), "lte") _eq(str(range1 & range2), "2..4") v2 = Version("6.0") v3 = Version("4") self.assertTrue( VersionRange.from_versions([v, v2, v3]) == VersionRange( "==3|==4|==6.0")) # test behaviour in sets def _eq2(a, b): _print("'%s' == '%s'" % (a, b)) self.assertTrue(a == b) a = VersionRange("1+<=2.5") b = VersionRange("1..2.5") c = VersionRange(">=5") d = VersionRange(">6.1.0") e = VersionRange("3.2") _eq2(set([a]) - set([a]), set()) _eq2(set([a]) - set([b]), set()) _eq2(set([a, a]) - set([a]), set()) _eq2(set([b, c, d, e]) - set([a]), set([c, d, e])) _eq2(set([b, c, e]) | set([c, d]), set([b, c, d, e])) _eq2(set([b, c]) & set([c, d]), set([c]))
def _eq(a, b): _print("'%s' == '%s'" % (a, b)) self.assertTrue(Version(a) == Version(b))
def _lt(a, b): _print("'%s' < '%s'" % (a, b)) self.assertTrue(self.make_token(a) < self.make_token(b)) self.assertTrue(Version(a) < Version(b))
def test_pod(self): """Validate we can save and load a VersionSplitPackageOrder to it's pod representation.""" self._test_pod( VersionSplitPackageOrder(first_version=Version("1.2.3")))
def test_repr(self): """Validate we can represent a VersionSplitPackageOrder as a string.""" inst = VersionSplitPackageOrder(first_version=Version("1,2,3")) self.assertEqual("VersionSplitPackageOrder(1,2,3)", repr(inst))
# Update this value to version up Rez. Do not place anything else in this file. _rez_version = "2.12.0" try: from rez.vendor.version.version import Version _rez_Version = Version(_rez_version) except: # the installer imports this file... pass # Copyright 2013-2016 Allan Johns. # # This library is free software: you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation, either # version 3 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see <http://www.gnu.org/licenses/>.
def test_misc(self): self.assertEqual(Version("1.2.12").as_tuple(), ("1", "2", "12"))
def pip_install_package(source_name, pip_version=None, python_version=None, mode=InstallMode.min_deps, release=False, prefix=None, extra_args=None): """Install a pip-compatible python package as a rez package. Args: source_name (str): Name of package or archive/url containing the pip package source. This is the same as the arg you would pass to the 'pip install' command. pip_version (str or `Version`): Version of pip to use to perform the install, uses latest if None. python_version (str or `Version`): Python version to use to perform the install, and subsequently have the resulting rez package depend on. mode (`InstallMode`): Installation mode, determines how dependencies are managed. release (bool): If True, install as a released package; otherwise, it will be installed as a local package. extra_args (List[str]): Additional options to the pip install command. Returns: 2-tuple: List of `Variant`: Installed variants; List of `Variant`: Skipped variants (already installed). """ installed_variants = [] skipped_variants = [] py_exe, context = find_pip(pip_version, python_version) print_info("Installing %r with pip taken from %r", source_name, py_exe) # TODO: should check if packages_path is writable before continuing with pip # if prefix is not None: packages_path = prefix else: packages_path = (config.release_packages_path if release else config.local_packages_path) targetpath = mkdtemp(suffix="-rez", prefix="pip-") if context and config.debug("package_release"): buf = StringIO() print("\n\npackage download environment:", file=buf) context.print_info(buf) _log(buf.getvalue()) # Build pip commandline cmd = [py_exe, "-m", "pip", "install"] _extra_args = extra_args or config.pip_extra_args or [] if "--no-use-pep517" not in _extra_args: cmd.append("--use-pep517") if not _option_present(_extra_args, "-t", "--target"): cmd.append("--target=%s" % targetpath) if mode == InstallMode.no_deps and "--no-deps" not in _extra_args: cmd.append("--no-deps") cmd.extend(_extra_args) cmd.append(source_name) # run pip # # Note: https://github.com/pypa/pip/pull/3934. If/when this PR is merged, # it will allow explicit control of where to put bin files. # _cmd(context=context, command=cmd) # determine version of python in use if context is None: # since we had to use system pip, we have to assume system python version py_ver_str = '.'.join(map(str, sys.version_info)) py_ver = Version(py_ver_str) else: python_variant = context.get_resolved_package("python") py_ver = python_variant.version # Collect resulting python packages using distlib distribution_path = DistributionPath([targetpath]) distributions = list(distribution_path.get_distributions()) dist_names = [x.name for x in distributions] def log_append_pkg_variants(pkg_maker): template = '{action} [{package.qualified_name}] {package.uri}{suffix}' actions_variants = [ ( print_info, 'Installed', installed_variants, pkg_maker.installed_variants or [], ), ( print_debug, 'Skipped', skipped_variants, pkg_maker.skipped_variants or [], ), ] for print_, action, variants, pkg_variants in actions_variants: for variant in pkg_variants: variants.append(variant) package = variant.parent suffix = (' (%s)' % variant.subpath) if variant.subpath else '' print_(template.format(**locals())) # get list of package and dependencies for distribution in distributions: # convert pip requirements into rez requirements rez_requires = get_rez_requirements(installed_dist=distribution, python_version=py_ver, name_casings=dist_names) # log the pip -> rez requirements translation, for debugging _log("Pip to rez requirements translation information for " + distribution.name_and_version + ":\n" + pformat({ "pip": { "run_requires": map(str, distribution.run_requires) }, "rez": rez_requires })) # determine where pip files need to be copied into rez package src_dst_lut = _get_distribution_files_mapping(distribution, targetpath) # build tools list tools = [] for relpath in src_dst_lut.values(): dir_, filename = os.path.split(relpath) if dir_ == "bin": tools.append(filename) # Sanity warning to see if any files will be copied if not src_dst_lut: message = 'No source files exist for {}!' if not _verbose: message += '\nTry again with rez-pip --verbose ...' print_warning(message.format(distribution.name_and_version)) def make_root(variant, path): """Using distlib to iterate over all installed files of the current distribution to copy files to the target directory of the rez package variant """ for rel_src, rel_dest in src_dst_lut.items(): src = os.path.join(targetpath, rel_src) dest = os.path.join(path, rel_dest) if not os.path.exists(os.path.dirname(dest)): os.makedirs(os.path.dirname(dest)) shutil.copyfile(src, dest) if _is_exe(src): shutil.copystat(src, dest) # create the rez package name = pip_to_rez_package_name(distribution.name) version = pip_to_rez_version(distribution.version) requires = rez_requires["requires"] variant_requires = rez_requires["variant_requires"] metadata = rez_requires["metadata"] with make_package(name, packages_path, make_root=make_root) as pkg: # basics (version etc) pkg.version = version if distribution.metadata.summary: pkg.description = distribution.metadata.summary # requirements and variants if requires: pkg.requires = requires if variant_requires: pkg.variants = [variant_requires] # commands commands = [] commands.append("env.PYTHONPATH.append('{root}/python')") if tools: pkg.tools = tools commands.append("env.PATH.append('{root}/bin')") pkg.commands = '\n'.join(commands) # Make the package use hashed variants. This is required because we # can't control what ends up in its variants, and that can easily # include problematic chars (>, +, ! etc). # TODO: https://github.com/nerdvegas/rez/issues/672 # pkg.hashed_variants = True # add some custom attributes to retain pip-related info pkg.pip_name = distribution.name_and_version pkg.from_pip = True pkg.is_pure_python = metadata["is_pure_python"] distribution_metadata = distribution.metadata.todict() help_ = [] if "home_page" in distribution_metadata: help_.append(["Home Page", distribution_metadata["home_page"]]) if "download_url" in distribution_metadata: help_.append( ["Source Code", distribution_metadata["download_url"]]) if help_: pkg.help = help_ if "author" in distribution_metadata: author = distribution_metadata["author"] if "author_email" in distribution_metadata: author += ' ' + distribution_metadata["author_email"] pkg.authors = [author] log_append_pkg_variants(pkg) # cleanup shutil.rmtree(targetpath) # print summary # if installed_variants: print_info("%d packages were installed.", len(installed_variants)) else: print_warning("NO packages were installed.") if skipped_variants: print_warning( "%d packages were already installed.", len(skipped_variants), ) return installed_variants, skipped_variants
def version(self): ver_str = self.get("version", "") return Version(ver_str)
def test_reordere(self): """Validate package ordering with a VersionSplitPackageOrder""" orderer = VersionSplitPackageOrder(Version("2.6.0")) expected = ["2.6.0", "2.5.2", "2.7.0", "2.6.8"] self._test_reorder(orderer, "python", expected)