def test_method_detection_requirements(tmp_path): """Test detecting installation method to be used - requirements.""" with open(os.path.join(tmp_path, "requirements.txt"), "w"): pass work_dir = os.path.join(tmp_path, "requirements") os.makedirs(work_dir) with cwd(work_dir): flexmock(micropipenv).should_receive("install_requirements").once() micropipenv.install(method=None)
def test_method_detection_pipenv(tmp_path): """Test detecting installation method to be used - Pipenv.""" with open(os.path.join(tmp_path, "Pipfile.lock"), "w"): pass work_dir = os.path.join(tmp_path, "pipenv") os.makedirs(work_dir) with cwd(work_dir): flexmock(micropipenv).should_receive("install_pipenv").once() micropipenv.install(method=None)
def test_method_detection_poetry(tmp_path): """Test detecting installation method to be used - Poetry.""" # Touch files with specific names so that detection can find them. with open(os.path.join(tmp_path, "pyproject.toml"), "w"): pass with open(os.path.join(tmp_path, "poetry.lock"), "w"): pass work_dir = os.path.join(tmp_path, "poetry") os.makedirs(work_dir) with cwd(work_dir): flexmock(micropipenv).should_receive("install_poetry").once() micropipenv.install(method=None)
def install(dev: bool) -> None: """Install dependencies as stated in Pipfile.lock or requirements.txt. This command assumes requirements files are present and dependencies are already resolved. If that's not the case, issue `thamos advise` before calling this. """ with workdir(): method = ("pipenv" if configuration.requirements_format == "pipenv" else "requirements") if not dev and method == "pipenv": _LOGGER.warning( "Development dependencies will not be installed - see %s", jl("no_dev")) micropipenv.install(method=method, deploy=True, dev=dev)
def install( runtime_environment_name: typing.Optional[str] = None, dev: bool = False, pip_args: typing.Optional[typing.Tuple[str]] = None, ) -> None: """Perform installation of packages for the given runtime environment. If the runtime environment is not specified, the first environment stated in the configuration is used. """ method = ("pipenv" if thoth_config.requirements_format == "pipenv" else "requirements") if not dev and method == "pipenv": _LOGGER.warning( "Development dependencies will not be installed - see %s", jl("no_dev")) with cwd(thoth_config.get_overlays_directory(runtime_environment_name)): if method == "pipenv": if not os.path.isfile("Pipfile.lock"): raise NoRequirementsFile( f"No Pipfile.lock found in {os.getcwd()!r} needed to install dependencies, " "issue `thamos advise` resolve dpeendencies") if not os.path.isfile( "Pipfile"): # Required for computing digests. raise NoRequirementsFile( f"No Pipfile found in {os.getcwd()!r} needed for the installation process" ) else: if not os.path.isfile("requirements.txt"): raise NoRequirementsFile( f"No requirements.txt file found in {os.getcwd()!r} needed to install dependencies" ) _LOGGER.info( "Using %r installation method to install dependencies stated in %r", method, os.getcwd(), ) micropipenv.install(method=method, deploy=True, dev=dev, pip_args=pip_args)
def advise( debug: bool = False, no_write: bool = False, recommendation_type: str = None, runtime_environment: str = None, no_wait: bool = False, no_static_analysis: bool = False, json_output: bool = False, force: bool = False, dev: bool = False, no_user_stack: bool = False, install: bool = False, write_advised_manifest_changes: Optional[str] = None, ): """Ask Thoth for recommendations on application stack.""" if install and no_wait: _LOGGER.error("Cannot install dependencies as --no-wait was provided") sys.exit(1) if install and no_write: _LOGGER.error( "Cannot install dependencies if lock files are not written") sys.exit(1) with workdir(): if not dev and configuration.requirements_format == "pipenv": _LOGGER.warning( "Development dependencies will not be considered during the resolution process - see %s", jl("no_dev"), ) # In CLI we always call to obtain only the best software stack (count is implicitly set to 1). results = thoth_advise_here( recommendation_type=recommendation_type, runtime_environment_name=runtime_environment, debug=debug, nowait=no_wait, force=force, source_type=ThothAdviserIntegrationEnum.CLI, no_static_analysis=no_static_analysis, dev=dev, no_user_stack=no_user_stack, ) if not results: return sys.exit(2) if no_wait: # Echo the analysis id to user when not waiting. click.echo(results) sys.exit(0) result, error = results if error: if json_output: json.dump(result, sys.stdout, indent=2) else: stack_info = (result.get("report") or {}).get("stack_info") if stack_info: _print_report( stack_info, json_output=json_output, title="Application stack guidance", ) print( result.get("error_msg") or "No error message was provided by the service.") sys.exit(4) if not no_write: if result["report"] and result["report"]["stack_info"]: _print_report( result["report"]["stack_info"], json_output=json_output, title="Application stack guidance", ) # Print report of the best one - thus index zero. if result["report"] and result["report"]["products"]: if result["report"]["products"][0]["justification"]: _print_report( result["report"]["products"][0]["justification"], json_output=json_output, title="Recommended stack report", ) else: click.echo( "No justification was made for the recommended stack") pipfile = result["report"]["products"][0]["project"][ "requirements"] pipfile_lock = result["report"]["products"][0]["project"][ "requirements_locked"] _write_configuration( result["report"]["products"][0]["advised_runtime_environment"], recommendation_type, dev, ) _write_files(pipfile, pipfile_lock, configuration.requirements_format) # type: ignore if write_advised_manifest_changes: advised_manifest_changes = result["report"]["products"][0][ "project"].get("advised_manifest_changes") with open(write_advised_manifest_changes, "w") as advised_manifest_changes_file: json.dump(advised_manifest_changes or {}, advised_manifest_changes_file) advised_manifest_changes_file.write("\n") if install: method = ("pipenv" if configuration.requirements_format == "pipenv" else "requirements") micropipenv.install(method=method, deploy=True, dev=dev) else: click.echo(json.dumps(result, indent=2)) sys.exit(0)