def test_normal(self): """Release a package and make sure it is valid.""" def _make_fake_git_repository_at_directory(root): repository = git.Repo.init(root) repository.index.add(".") repository.index.commit("initial commit") source_path = tempfile.mkdtemp(suffix="_rez_package_source_path") self.delete_item_later(source_path) with open(os.path.join(source_path, "package.py"), "w") as handler: handler.write( textwrap.dedent("""\ name = "some_package" version = "1.0.0" build_command = "echo 'foo'" """)) _make_fake_git_repository_at_directory(source_path) package = packages_.get_developer_package(source_path) options = mock.MagicMock() options.cmd = "release" options.debug = False options.message = "Fake release message" options.no_message = False options.process = "local" options.variants = None options.vcs = None parser = mock.MagicMock() parser.prog = "rez release" release_path = tempfile.mkdtemp(suffix="_rez_package_release_path") self.delete_item_later(release_path) with wurlitzer.pipes(): creator.release(finder.get_package_root(package), options, parser, release_path) release_package = packages_.get_developer_package( os.path.join(release_path, "some_package", "1.0.0")) self.assertIsNotNone(release_package)
def test_no_change(self, _create_pull_request): """Don't change the imports of any Rez package or file.""" root = tempfile.mktemp(suffix="_test_single_change_source_packages") self.delete_item_later(root) packages = [ _make_package_with_modules( # This package won't be changed "a_unchanging_package", [ ( os.path.join("in", "folder", "some_module.py"), textwrap.dedent("""\ import os import textwrap def foo(): import shlex """), ), ("another_file.py", ""), ( "more_files.py", textwrap.dedent("""\ import custom.namespace from blah import here, there, everywhere """), ), ], root, ) ] repository, packages, remote_root = testify.make_fake_repository( packages, root) self.delete_item_later(repository.working_dir) self.delete_item_later(remote_root) release_path = tempfile.mkdtemp( suffix="_a_release_location_for_testing") options, parser = _make_fake_release_data() for package in packages: creator.release( finder.get_package_root(package), options, parser, release_path, search_paths=[repository.working_dir], quiet=True, ) move_imports_arguments, text = _get_test_commands() text = shlex.split(text) sys.argv[1:] = text arguments = _Arguments(move_imports_arguments, text) with rez_configuration.patch_release_packages_path(release_path): _, unfixed, invalids, skips = _get_test_results( "move_imports", arguments=arguments, paths={release_path}) self.assertEqual(set(), unfixed) self.assertEqual([], invalids) self.assertEqual( [("a_unchanging_package", "No namespaces need to be replaced.")], [(skip.package.name, skip.reason) for skip in skips], ) self.assertEqual(0, _create_pull_request.call_count)
def test_egg(self, _create_pull_request): """Bump a released Rez package which only contains a single zipped .egg file.""" def _create_package(root, name, version, requirements=None): text = textwrap.dedent("""\ name = "{name}" version = "{version}" description = "A package.py Rez package that won't be converted." build_command = "python {{root}}/rezbuild.py" def commands(): import os env.PYTHONPATH.append(os.path.join("{{root}}", "python.egg")) """) text = text.format(name=name, version=version) if requirements: text += "\nrequires = {requirements!r}".format( requirements=requirements) with open(os.path.join(root, "package.py"), "w") as handler: handler.write(text) with open(os.path.join(root, "rezbuild.py"), "w") as handler: handler.write( textwrap.dedent("""\ #!/usr/bin/env python # -*- coding: utf-8 -*- import os import shutil import zipfile def main(): source = os.environ["REZ_BUILD_SOURCE_PATH"] build = os.environ["REZ_BUILD_PATH"] python_directory = os.path.join(source, "python") with zipfile.ZipFile(os.path.join(build, "python.egg"), "w") as handler: for root, folders, files in os.walk(python_directory): relative_root = os.path.relpath(root, python_directory) for folder in folders: handler.write( os.path.join(root, folder), os.path.join(relative_root, folder), ) for file_ in files: handler.write( os.path.join(root, file_), os.path.join(relative_root, file_), ) shutil.copy2( handler.filename, os.path.join( os.environ["REZ_BUILD_INSTALL_PATH"], os.path.basename(handler.filename) ), ) if __name__ == "__main__": main() """)) python_root = os.path.join(root, "python") os.makedirs(python_root) common.make_files( { "something": { "__init__.py": None, "inner_folder": { "__init__.py": None, }, }, "some_other_package_folder": { "__init__.py": None, "some_module.py": None, }, }, python_root, ) def _make_package_with_contents(root, name, version, create_package): directory = os.path.join(root, name) os.makedirs(directory) create_package(directory, name, version) return finder.get_nearest_rez_package(directory) root = tempfile.mkdtemp(suffix="_test_is_definition_build_package") self.delete_item_later(root) packages = [ _make_package_with_contents(root, "another_package", "1.2.0", _create_package), _make_package_with_contents( root, "some_package", "1.2.0", functools.partial(_create_package, requirements=["another_package-1"]), ), ] repository, packages, remote_root = testify.make_fake_repository( packages, root) self.delete_item_later(repository.working_dir) self.delete_item_later(remote_root) release_path = tempfile.mkdtemp( suffix="_a_release_location_for_testing") self.delete_item_later(release_path) options, parser = _make_fake_release_data() for package in packages: creator.release( finder.get_package_root(package), options, parser, release_path, search_paths=[repository.working_dir], quiet=True, ) text = 'PR github-token --packages another_package-1.1 --instructions "Do it!" --new minor' text = shlex.split(text) sys.argv[1:] = text # Simulate the act of a user with a locally built package that # they want to test against other existing releases. # source_root = tempfile.mkdtemp(suffix="_another_source_root") source_package = _make_package_with_contents(source_root, "another_package", "1.3.0", _create_package) install_path = tempfile.mkdtemp(suffix="_install_path") local_built_package = creator.build(source_package, install_path) arguments = _BumpArguments( additional_paths=[ inspection.get_packages_path_from_package(local_built_package) ], instructions="Do something!", new="minor", packages=["another_package-1.3"], pull_request_name="PR", token="github-token", ssl_no_verify=False, cached_users="", fallback_reviewers=None, base_url="", ) with rez_configuration.patch_release_packages_path(release_path): ran_packages, unfixed, invalids, skips = _get_test_results( "bump", arguments=arguments, paths={release_path}) package_file = next(iter(ran_packages)).filepath with open(package_file, "r") as handler: text = handler.read() expected = textwrap.dedent("""\ name = "some_package" version = "1.3.0" description = "A package.py Rez package that won't be converted." build_command = "python {root}/rezbuild.py" def commands(): import os env.PYTHONPATH.append(os.path.join("{root}", "python.egg")) requires = [ "another_package-1.3", ]""") self.assertEqual(expected, text) self.assertEqual((set(), [], []), (unfixed, invalids, skips)) self.assertEqual(1, _create_pull_request.call_count)
def _make_fake_released_packages(self, other_package): """Create 2 basic Rez packages to use for testing. Args: other_package (str): If "yaml", one of the packages created will be a package.yaml file. Otherwise, it gets added as a package.py file. Returns: str: The path where all of the created packages will go to. """ root = tempfile.mkdtemp(suffix="_test_replace_yaml") self.delete_item_later(root) packages = [ _make_rez_package( "another_package", "package.py", textwrap.dedent("""\ name = "another_package" version = "1.2.0" description = "A package.py Rez package that won't be converted." build_command = "echo 'foo'" """), root, ) ] if other_package == "yaml": packages.append( _make_rez_package( "some_package", "package.yaml", textwrap.dedent("""\ name: some_package version: 1.2.0 description: "A YAML-based package that will be converted." build_command: "echo 'foo'" """), root, )) else: packages.append( _make_rez_package( "some_package", "package.py", textwrap.dedent("""\ name = "some_package" version = "1.2.0" description = "A YAML-based package that will be converted." build_command = "echo 'foo'" """), root, )) repository, packages, remote_root = testify.make_fake_repository( packages, root) self.delete_item_later(repository.working_dir) self.delete_item_later(remote_root) release_path = tempfile.mkdtemp(suffix="_some_release_location") self.delete_item_later(release_path) options, parser = _make_fake_release_data() for package in packages: creator.release( finder.get_package_root(package), options, parser, release_path, search_paths=[repository.working_dir], quiet=True, ) return release_path
def test_multiple_changes(self, _create_pull_request): """Change 2+ packages at once.""" root = tempfile.mktemp(suffix="_test_single_change_source_packages") self.delete_item_later(root) packages = [ _make_package_with_modules( # This package will end up getting changed "some_package", [( os.path.join("in", "folder", "some_module.py"), textwrap.dedent("""\ if True: from some.namespace import here, there, everywhere """), )], root, ), _make_package_with_modules( # This package will also be changed "another_package", [ ( os.path.join("a_folder", "a_file.py"), textwrap.dedent("""\ import os, textwrap, some.namespace.here, another_one.here """), ), ("another_file.py", ""), ( "more_files.py", textwrap.dedent("""\ import custom.namespace from blah import here, there, everywhere """), ), ], root, ), ] repository, packages, remote_root = testify.make_fake_repository( packages, root) self.delete_item_later(repository.working_dir) self.delete_item_later(remote_root) release_path = tempfile.mkdtemp( suffix="_a_release_location_for_testing") options, parser = _make_fake_release_data() for package in packages: creator.release( finder.get_package_root(package), options, parser, release_path, search_paths=[repository.working_dir], quiet=True, ) move_imports_arguments, text = _get_test_commands() text = shlex.split(text) sys.argv[1:] = text arguments = _Arguments(move_imports_arguments, text) with rez_configuration.patch_release_packages_path(release_path): processed_packages, unfixed, invalids, skips = _get_test_results( "move_imports", arguments=arguments, paths={release_path}) self.assertEqual(set(), unfixed) self.assertEqual([], invalids) self.assertEqual([], skips) processed_packages = sorted(processed_packages, key=operator.attrgetter("name")) cloned_package = finder.get_package_root(processed_packages[1]) path = os.path.join(cloned_package, "python", "in", "folder", "some_module.py") if not os.path.isfile(path): raise RuntimeError( 'Path "{path}" does not exist.'.format(path=path)) with open(path, "r") as handler: code_package_1 = handler.read() expected_package_1 = textwrap.dedent("""\ if True: from a.new.space import somewhere from some.namespace import there, everywhere """) cloned_package = finder.get_package_root(processed_packages[0]) path = os.path.join(cloned_package, "python", "a_folder", "a_file.py") if not os.path.isfile(path): raise RuntimeError( 'Path "{path}" does not exist.'.format(path=path)) with open(path, "r") as handler: code = handler.read() expected = textwrap.dedent("""\ import os, textwrap, a.new.space.somewhere, another_one.here """) self.assertEqual(expected_package_1, code_package_1) self.assertEqual(expected, code) self.assertEqual(2, _create_pull_request.call_count)
def test_single_change(self, _create_pull_request): """Change only one package. Raises: RuntimeError: If an expected cloned file does not exist. """ root = tempfile.mktemp(suffix="_test_single_change_source_packages") self.delete_item_later(root) packages = [ _make_package_with_modules( # This package will end up getting changed "some_package", [( os.path.join("in", "folder", "some_module.py"), textwrap.dedent("""\ if True: from some.namespace import here, there, everywhere """), )], root, ), _make_package_with_modules( # This package won't be changed "a_unchanging_package", [ ( os.path.join("in", "folder", "some_module.py"), textwrap.dedent("""\ import os import textwrap def foo(): import shlex """), ), ("another_file.py", ""), ( "more_files.py", textwrap.dedent("""\ import custom.namespace from blah import here, there, everywhere """), ), ], root, ), ] repository, packages, remote_root = testify.make_fake_repository( packages, root) self.delete_item_later(repository.working_dir) self.delete_item_later(remote_root) release_path = tempfile.mkdtemp( suffix="_a_release_location_for_testing") options, parser = _make_fake_release_data() for package in packages: creator.release( finder.get_package_root(package), options, parser, release_path, search_paths=[repository.working_dir], quiet=True, ) move_imports_arguments, text = _get_test_commands() text = shlex.split(text) sys.argv[1:] = text arguments = _Arguments(move_imports_arguments, text) with rez_configuration.patch_release_packages_path(release_path): processed_packages, unfixed, invalids, skips = _get_test_results( "move_imports", arguments=arguments, paths={release_path}) self.assertEqual(set(), unfixed) self.assertEqual([], invalids) self.assertEqual( [("a_unchanging_package", "No namespaces need to be replaced.")], [(skip.package.name, skip.reason) for skip in skips], ) cloned_package = finder.get_package_root(next( iter(processed_packages))) path = os.path.join(cloned_package, "python", "in", "folder", "some_module.py") if not os.path.isfile(path): raise RuntimeError( 'Path "{path}" does not exist.'.format(path=path)) with open(path, "r") as handler: code = handler.read() expected = textwrap.dedent("""\ if True: from a.new.space import somewhere from some.namespace import there, everywhere """) self.assertEqual(expected, code) self.assertEqual(1, _create_pull_request.call_count)
def _release_packages(packages, search_paths=None): """Release 1+ Rez packages. Args: packages (list[:class:`rez.packages_.Package`]): The source Rez packages that will be built and released. search_paths (list[str], optional): The directories on-disk that can be used to help find extra dependencies that a Rez package might require. Default is None. Raises: ValueError: If `packages` is invalid. Returns: str: The directory where the released package was sent to. Normally, this should always be `new_release_path`. But if `new_release_path` wasn't given then this returns a temporary directory. """ if not packages: raise ValueError("No packages were given") if not search_paths: search_paths = [] options = mock.MagicMock() options.cmd = "release" options.debug = False options.message = "Fake release message" options.no_message = False options.process = "local" options.variants = None options.vcs = None parser = mock.MagicMock() parser.prog = "rez release" package = packages[0] _LOGGER.info('Releasing the fake package "%s" to a temporary directory.', package.name) temporary_path = tempfile.mkdtemp(suffix="_release_path_test") # Rez prints a lot of text to console during release so we'll silence it all with wurlitzer.pipes(): new_release_path = creator.release( finder.get_package_root(package), options, parser, temporary_path, search_paths=search_paths, ) for package in packages[1:]: with wurlitzer.pipes(): _LOGGER.info( 'Releasing the fake package "%s" to "%s".', package.name, new_release_path, ) creator.release( finder.get_package_root(package), options, parser, new_release_path, search_paths=search_paths, ) return new_release_path