def executable(self, env): """@return butility.Path to executable - its not verified to be existing @note for now this is uncached, but its okay for our use @note we always resolve environment variables """ executables = self.data().executable if not executables: raise ValueError("no executable set for package '%s'" % self.name()) error = None executable_path = None for executable in executables: executable_path = Path._expandvars_deep(executable, env) try: executable_path = self.to_abs_path(executable_path) except EnvironmentError as err: if '$' in executable_path: # give it more time, let them work with it until something breaks # Don't have another choice executable_path = Path(executable_path) else: error = err continue # end handle conversion if os.name == 'nt': # We assume exe by default, and not com or bat. # Even though magic isn't good, I see no point in making this configurable, people # can just be explicit about the extension win_ext = '.exe' if not executable_path.ext(): executable_path += win_ext # handle extension # end handle windows # If we have variables in the path, we can't assume anything (nor resolve) as it might be too early # for that. In that case, we assume the best. Otherwise, the executable must exist if not executable_path.containsvars() and not executable_path.isfile(): continue # end return executable_path # end for each executable to try assert executable_path or error, "Should have collected at least one error at this point" if error: raise error return executable_path
def to_abs_path(self, path): """Convert the given possibly relative path to an absolute path, if necessary @note it is not checked for existence @param path string or butility.Path @return absolute version of the path, as butility.Path @throws ValueError if the path is relative and there is no valid root path @note assumes the best when an environment variable is found, which never be made absolute. Will only appliy to paths like '$FOO/bar', not to 'foo/$BAR'""" path = Path(path) if path.isabs(): return path if path.containsvars(): return path if self.root_path() is None: raise EnvironmentError("Cannot convert '%s' to absolute path in package '%s' without a single valid tree, tried: [%s]" % (path, self.name(), ', '.join(self._data.trees))) # end handle root path return self.root_path() / path