def activation_shell_code(self, shell=None): """Get shell code that should be run to activate this suite.""" from rez.shells import create_shell from rez.rex import RexExecutor executor = RexExecutor(interpreter=create_shell(shell), parent_variables=["PATH"], shebang=False) executor.env.PATH.append(self.tools_path) return executor.get_output().strip()
def test_command(self): sh = create_shell() _, _, _, command = sh.startup_capabilities(command=True) if command: r = self._create_context(["hello_world"]) p = r.execute_shell(command="hello_world", stdout=subprocess.PIPE) self.assertEqual(_stdout(p).decode("utf-8"), "Hello Rez World!")
def append_system_paths(self): """Append system paths to $PATH.""" from rez.shells import Shell, create_shell sh = self.interpreter if isinstance(self.interpreter, Shell) \ else create_shell() paths = sh.get_syspaths() paths_str = os.pathsep.join(paths) self.env.PATH.append(paths_str)
def test_norc(self): sh = create_shell() _, norc, _, command = sh.startup_capabilities(norc=True, command=True) if norc and command: r = self._create_context(["hello_world"]) p = r.execute_shell(norc=True, command="hello_world", stdout=subprocess.PIPE) self.assertEqual(_stdout(p), "Hello Rez World!")
def test_norc(self): sh = create_shell() _, norc, _, command = sh.startup_capabilities(norc=True, command=True) if norc and command: r = self._create_context(["hello_world"]) p = r.execute_shell(norc=True, command="hello_world", stdout=subprocess.PIPE, text=True) self.assertEqual(_stdout(p), "Hello Rez World!")
def _rex_appending(): from rez.shells import create_shell sh = create_shell() env.FOO.append("hey") info(sh.get_key_token("FOO")) env.FOO.append(literal("$DAVE")) info(sh.get_key_token("FOO")) env.FOO.append("Dave's not here man") info(sh.get_key_token("FOO"))
def _rex_assigning(): from rez.shells import create_shell sh = create_shell() def _print(value): env.FOO = value # Wrap the output in quotes to prevent the shell from # interpreting parts of our output as commands. This can happen # when we include special characters (&, <, >, ^) in a # variable. info('"${FOO}"') env.GREET = "hi" env.WHO = "Gary" _print("ello") _print(literal("ello")) _print(expandable("ello")) info('') _print("\\") _print("\\'") _print("\\\"") _print(literal("\\")) _print(literal("\\'")) _print(literal("\\\"")) _print("\\path1\\path2\\path3") _print(literal("\\path1").e("\\path2\\path3")) _print("hello world") _print("hello 'world'") _print('hello "world"') _print(literal("hello world")) _print(literal("hello 'world'")) _print(literal('hello "world"')) # Generic form of variables _print("hey $WHO") _print("hey ${WHO}") _print(expandable("${GREET} ").e("$WHO")) _print(expandable("${GREET} ").l("$WHO")) _print(literal("${WHO}")) _print(literal("${WHO}").e(" $WHO")) # Make sure we are escaping &, <, >, ^ properly. _print('hey & world') _print('hey > world') _print('hey < world') _print('hey ^ world') # Platform dependent form of variables. for token in sh.get_all_key_tokens("WHO"): _print("hey " + token) _print(expandable("${GREET} ").e(token)) _print(expandable("${GREET} ").l(token)) _print(literal(token)) _print(literal(token).e(" " + token))
def _get_application_parent_environ(): from rez.config import config from rez.shells import create_shell if not config.get("inherit_parent_environment", True): # bleeding-rez, isolate enabled. sh = create_shell() return sh.environment() return (allzparkconfig.application_parent_environment() or os.environ.copy())
def test_command(self): # TODO: issues with binding the 'hello_world' package means it is not # possible to run this test on Windows. The 'hello_world' executable # is not registered correctly on Windows so always returned the # incorrect error code. sh = create_shell() _, _, _, command = sh.startup_capabilities(command=True) if command: r = self._create_context(["hello_world"]) p = r.execute_shell(command="hello_world", stdout=subprocess.PIPE) self.assertEqual(_stdout(p), "Hello Rez World!")
def test_command_returncode(self): sh = create_shell() _, _, _, command = sh.startup_capabilities(command=True) if command: r = self._create_context(["hello_world"]) command = "hello_world -q -r 66" commands = (command, command.split()) for cmd in commands: with r.execute_shell(command=cmd, stdout=subprocess.PIPE) as p: p.wait() self.assertEqual(p.returncode, 66)
def test_stdin(self): sh = create_shell() _, _, stdin, _ = sh.startup_capabilities(stdin=True) if stdin: r = self._create_context(["hello_world"]) p = r.execute_shell(stdout=subprocess.PIPE, stdin=subprocess.PIPE, norc=True) stdout, _ = p.communicate(input="hello_world\n") stdout = stdout.strip() self.assertEqual(stdout, "Hello Rez World!")
def _execute_code(func, expected_output): loc = inspect.getsourcelines(func)[0][1:] code = textwrap.dedent('\n'.join(loc)) r = self._create_context([]) p = r.execute_rex_code(code, stdout=subprocess.PIPE, text=True) out, _ = p.communicate() self.assertEqual(p.returncode, 0) sh = create_shell() output = out.strip().split("\n") self.assertEqual(output, expected_output)
def command(opts, parser, extra_arg_groups=None): from rez.shells import create_shell from rez.utils.formatting import columnise from rez.rex import RexExecutor, Python from pprint import pformat with open(opts.FILE) as f: code = f.read() interp = None if opts.format is None: interp = create_shell() elif opts.format in ('dict', 'table'): interp = Python(passive=True) else: interp = create_shell(opts.format) parent_env = {} if opts.no_env else None if opts.parent_vars == "all": parent_vars = True else: parent_vars = opts.parent_vars ex = RexExecutor(interpreter=interp, parent_environ=parent_env, parent_variables=parent_vars) ex.execute_code(code, filename=opts.FILE) o = ex.get_output() if isinstance(o, dict): if opts.format == "table": rows = [x for x in sorted(o.iteritems())] print '\n'.join(columnise(rows)) else: print pformat(o) else: print o
def test_rez_env_output(self): # here we are making sure that running a command via rez-env prints # exactly what we expect. sh = create_shell() # Assumes that the shell has an echo command, build-in or alias cmd = [os.path.join(system.rez_bin_path, "rez-env"), "--", "echo", "hey"] process = subprocess.Popen( cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True ) sh_out = process.communicate()[0] self.assertEqual(sh_out.strip(), "hey")
def test_rez_command(self): sh = create_shell() _, _, _, command = sh.startup_capabilities(command=True) if command: r = self._create_context([]) p = r.execute_shell(command="rezolve -h") p.wait() self.assertEqual(p.returncode, 0) p = r.execute_shell(command="rez-env -h") p.wait() self.assertEqual(p.returncode, 0)
def test_no_output(self): sh = create_shell() _, _, _, command = sh.startup_capabilities(command=True) if command: r = self._create_context(["hello_world"]) p = r.execute_shell(command="hello_world -q", stdout=subprocess.PIPE, text=True) self.assertEqual( _stdout(p), '', "This test and others will fail, because one or more of your " "startup scripts are printing to stdout. Please remove the " "printout and try again.")
def test_rez_command(self): sh = create_shell() _, _, _, command = sh.startup_capabilities(command=True) if command: r = self._create_context([]) with r.execute_shell(command="rezolve -h") as p: p.wait() self.assertEqual(p.returncode, 0) with r.execute_shell(command="rez-env -h") as p: p.wait() self.assertEqual(p.returncode, 0)
def _execute_code(func, expected_output): loc = inspect.getsourcelines(func)[0][1:] code = textwrap.dedent('\n'.join(loc)) r = self._create_context([]) p = r.execute_rex_code(code, stdout=subprocess.PIPE) out, _ = p.communicate() self.assertEqual(p.returncode, 0) # PowerShell and Unix uses \n, cmd etc use \r\n sh = create_shell() output = out.decode("utf-8").strip().split(sh.line_terminator()) self.assertEqual(output, expected_output)
def test_rcfile(self): sh = create_shell() rcfile, _, _, command = sh.startup_capabilities(rcfile=True, command=True) if rcfile and command: f, path = tempfile.mkstemp() os.write(f, "hello_world\n") os.close(f) r = self._create_context(["hello_world"]) p = r.execute_shell(rcfile=path, command="hello_world -q", stdout=subprocess.PIPE) self.assertEqual(_stdout(p), "Hello Rez World!") os.remove(path)
def test_command_returncode(self): # TODO: issues with binding the 'hello_world' package means it is not # possible to run this test on Windows. The 'hello_world' executable # is not registered correctly on Windows so always returned the # incorrect error code. sh = create_shell() _, _, _, command = sh.startup_capabilities(command=True) if command: r = self._create_context(["hello_world"]) command = "hello_world -q -r 66" commands = (command, command.split()) for cmd in commands: p = r.execute_shell(command=cmd, stdout=subprocess.PIPE) p.wait() self.assertEqual(p.returncode, 66)
def test_no_output(self): # TODO: issues with binding the 'hello_world' package means it is not # possible to run this test on Windows. The 'hello_world' executable # is not registered correctly on Windows so always returned the # incorrect error code. sh = create_shell() _, _, _, command = sh.startup_capabilities(command=True) if command: r = self._create_context(["hello_world"]) p = r.execute_shell(command="hello_world -q", stdout=subprocess.PIPE) self.assertEqual( _stdout(p), '', "This test and others will fail, because one or more of your " "startup scripts are printing to stdout. Please remove the " "printout and try again.")
def build(self, context, variant, build_path, install_path, install=False, build_type=BuildType.local): def _pr(s): if self.verbose: print s # find cmake binary if self.settings.cmake_binary: exe = self.settings.cmake_binary else: exe = context.which("cmake", fallback=True) if not exe: raise RezCMakeError("could not find cmake binary") found_exe = which(exe) if not found_exe: raise RezCMakeError("cmake binary does not exist: %s" % exe) sh = create_shell() # assemble cmake command cmd = [found_exe, "-d", self.working_dir] cmd += (self.settings.cmake_args or []) cmd += (self.build_args or []) cmd.append("-DCMAKE_INSTALL_PREFIX=%s" % install_path) cmd.append("-DCMAKE_MODULE_PATH=%s" % sh.get_key_token("CMAKE_MODULE_PATH")) cmd.append("-DCMAKE_BUILD_TYPE=%s" % self.build_target) cmd.append("-DREZ_BUILD_TYPE=%s" % build_type.name) cmd.append("-DREZ_BUILD_INSTALL=%d" % (1 if install else 0)) cmd.extend(["-G", self.build_systems[self.cmake_build_system]]) if config.rez_1_cmake_variables and \ not config.disable_rez_1_compatibility and \ build_type == BuildType.central: cmd.append("-DCENTRAL=1") # execute cmake within the build env _pr("Executing: %s" % ' '.join(cmd)) if not os.path.abspath(build_path): build_path = os.path.join(self.working_dir, build_path) build_path = os.path.realpath(build_path) callback = functools.partial(self._add_build_actions, context=context, package=self.package, variant=variant, build_type=build_type) # run the build command and capture/print stderr at the same time retcode, _, _ = context.execute_shell(command=cmd, block=True, cwd=build_path, actions_callback=callback) ret = {} if retcode: ret["success"] = False return ret if self.write_build_scripts: # write out the script that places the user in a build env, where # they can run make directly themselves. build_env_script = os.path.join(build_path, "build-env") create_forwarding_script(build_env_script, module=("build_system", "cmake"), func_name="_FWD__spawn_build_shell", working_dir=self.working_dir, build_dir=build_path, variant_index=variant.index) ret["success"] = True ret["build_env_script"] = build_env_script return ret # assemble make command if self.settings.make_binary: cmd = [self.settings.make_binary] else: cmd = ["make"] cmd += (self.child_build_args or []) if not any(x.startswith("-j") for x in (self.child_build_args or [])): n = variant.config.build_thread_count cmd.append("-j%d" % n) # execute make within the build env _pr("\nExecuting: %s" % ' '.join(cmd)) retcode, _, _ = context.execute_shell(command=cmd, block=True, cwd=build_path, actions_callback=callback) if not retcode and install and "install" not in cmd: cmd.append("install") # execute make install within the build env _pr("\nExecuting: %s" % ' '.join(cmd)) retcode, _, _ = context.execute_shell(command=cmd, block=True, cwd=build_path, actions_callback=callback) ret["success"] = (not retcode) return ret
def test_rex_code(self): """Test that Rex code run in the shell creates the environment variable values that we expect.""" def _execute_code(func, expected_output): loc = inspect.getsourcelines(func)[0][1:] code = textwrap.dedent('\n'.join(loc)) r = self._create_context([]) p = r.execute_rex_code(code, stdout=subprocess.PIPE, text=True) out, _ = p.communicate() self.assertEqual(p.returncode, 0) output = out.strip().split("\n") self.assertEqual(output, expected_output) def _rex_assigning(): from rez.shells import create_shell sh = create_shell() def _print(value): env.FOO = value # Wrap the output in quotes to prevent the shell from # interpreting parts of our output as commands. This can happen # when we include special characters (&, <, >, ^) in a # variable. info('"${FOO}"') env.GREET = "hi" env.WHO = "Gary" _print("ello") _print(literal("ello")) _print(expandable("ello")) info('') _print("\\") _print("\\'") _print("\\\"") _print(literal("\\")) _print(literal("\\'")) _print(literal("\\\"")) _print("\\path1\\path2\\path3") _print(literal("\\path1").e("\\path2\\path3")) _print("hello world") _print("hello 'world'") _print('hello "world"') _print(literal("hello world")) _print(literal("hello 'world'")) _print(literal('hello "world"')) # Generic form of variables _print("hey $WHO") _print("hey ${WHO}") _print(expandable("${GREET} ").e("$WHO")) _print(expandable("${GREET} ").l("$WHO")) _print(literal("${WHO}")) _print(literal("${WHO}").e(" $WHO")) # Make sure we are escaping &, <, >, ^ properly. _print('hey & world') _print('hey > world') _print('hey < world') _print('hey ^ world') # Platform dependent form of variables. for token in sh.get_all_key_tokens("WHO"): _print("hey " + token) _print(expandable("${GREET} ").e(token)) _print(expandable("${GREET} ").l(token)) _print(literal(token)) _print(literal(token).e(" " + token)) expected_output = [ "ello", "ello", "ello", "", "\\", "\\'", "\\\"", "\\", "\\'", "\\\"", "\\path1\\path2\\path3", "\\path1\\path2\\path3", "hello world", "hello 'world'", 'hello "world"', "hello world", "hello 'world'", 'hello "world"', "hey Gary", "hey Gary", "hi Gary", "hi $WHO", "${WHO}", "${WHO} Gary", "hey & world", "hey > world", "hey < world", "hey ^ world" ] # Assertions for other environment variable types from rez.shells import create_shell sh = create_shell() for token in sh.get_all_key_tokens("WHO"): expected_output += [ "hey Gary", "hi Gary", "hi " + token, token, token + " Gary", ] # We are wrapping all variable outputs in quotes in order to make sure # our shell isn't interpreting our output as instructions when echoing # it but this means we need to wrap our expected output as well. Only # exception is empty string, which is just passed through. expected_output = ['"{}"'.format(o) if o else o for o in expected_output] _execute_code(_rex_assigning, expected_output) def _rex_appending(): from rez.shells import create_shell sh = create_shell() env.FOO.append("hey") info(sh.get_key_token("FOO")) env.FOO.append(literal("$DAVE")) info(sh.get_key_token("FOO")) env.FOO.append("Dave's not here man") info(sh.get_key_token("FOO")) expected_output = [ "hey", os.pathsep.join(["hey", "$DAVE"]), os.pathsep.join(["hey", "$DAVE", "Dave's not here man"]) ] _execute_code(_rex_appending, expected_output)
def build(self, context, variant, build_path, install_path, install=False, build_type=BuildType.local): def _pr(s): if self.verbose: print s # find cmake binary if self.settings.cmake_binary: exe = self.settings.cmake_binary else: exe = context.which("cmake", fallback=True) if not exe: raise RezCMakeError("could not find cmake binary") found_exe = which(exe) if not found_exe: raise RezCMakeError("cmake binary does not exist: %s" % exe) sh = create_shell() # assemble cmake command cmd = [found_exe, "-d", self.working_dir] cmd += (self.settings.cmake_args or []) cmd += (self.build_args or []) cmd.append("-DCMAKE_INSTALL_PREFIX=%s" % install_path) cmd.append("-DCMAKE_MODULE_PATH=%s" % sh.get_key_token("CMAKE_MODULE_PATH")) cmd.append("-DCMAKE_BUILD_TYPE=%s" % self.build_target) cmd.append("-DREZ_BUILD_TYPE=%s" % build_type.name) cmd.append("-DREZ_BUILD_INSTALL=%d" % (1 if install else 0)) cmd.extend(["-G", self.build_systems[self.cmake_build_system]]) if config.rez_1_cmake_variables and \ not config.disable_rez_1_compatibility and \ build_type == BuildType.central: cmd.append("-DCENTRAL=1") # execute cmake within the build env _pr("Executing: %s" % ' '.join(cmd)) if not os.path.abspath(build_path): build_path = os.path.join(self.working_dir, build_path) build_path = os.path.realpath(build_path) callback = functools.partial(self._add_build_actions, context=context, package=self.package, variant=variant, build_type=build_type) # run the build command and capture/print stderr at the same time retcode, _, _ = context.execute_shell(command=cmd, block=True, cwd=build_path, actions_callback=callback) ret = {} if retcode: ret["success"] = False return ret if self.write_build_scripts: # write out the script that places the user in a build env, where # they can run make directly themselves. build_env_script = os.path.join(build_path, "build-env") create_forwarding_script(build_env_script, module=("build_system", "cmake"), func_name="_FWD__spawn_build_shell", working_dir=self.working_dir, build_dir=build_path, variant_index=variant.index) ret["success"] = True ret["build_env_script"] = build_env_script return ret # assemble make command if self.settings.make_binary: cmd = [self.settings.make_binary] else: cmd = ["make"] cmd += (self.child_build_args or []) if not any(x.startswith("-j") for x in (self.child_build_args or [])): n = variant.config.build_thread_count or cpu_count() cmd.append("-j%d" % n) # execute make within the build env _pr("\nExecuting: %s" % ' '.join(cmd)) retcode, _, _ = context.execute_shell(command=cmd, block=True, cwd=build_path, actions_callback=callback) if not retcode and install and "install" not in cmd: cmd.append("install") # execute make install within the build env _pr("\nExecuting: %s" % ' '.join(cmd)) retcode, _, _ = context.execute_shell(command=cmd, block=True, cwd=build_path, actions_callback=callback) ret["success"] = (not retcode) return ret