def requirements(state, dev=False, dev_only=False, hash=False): from pipenv.utils.dependencies import convert_deps_to_pip lockfile = state.project.lockfile_content for i, package_index in enumerate(lockfile["_meta"]["sources"]): prefix = "-i" if i == 0 else "--extra-index-url" echo(" ".join([prefix, package_index["url"]])) deps = {} if not dev_only: deps.update(lockfile["default"]) if dev or dev_only: deps.update(lockfile["develop"]) pip_deps = convert_deps_to_pip( deps, project=None, r=False, include_index=False, include_hashes=hash, include_markers=False, ) for d in pip_deps: echo(d) sys.exit(0)
def run_open(state, module, *args, **kwargs): """View a given module in your editor. This uses the EDITOR environment variable. You can temporarily override it, for example: EDITOR=atom pipenv open requests """ from ..core import ensure_project, inline_activate_virtual_environment # Ensure that virtualenv is available. ensure_project( state.project, three=state.three, python=state.python, validate=False, pypi_mirror=state.pypi_mirror, ) c = subprocess_run([ state.project._which("python"), "-c", "import {0}; print({0}.__file__)".format(module), ]) if c.returncode: echo(crayons.red("Module not found!")) sys.exit(1) if "__init__.py" in c.stdout: p = os.path.dirname(c.stdout.strip().rstrip("cdo")) else: p = c.stdout.strip().rstrip("cdo") echo(crayons.normal(f"Opening {p!r} in your EDITOR.", bold=True)) inline_activate_virtual_environment(state.project) edit(filename=p) return 0
def list(ctx: click.Context) -> None: '''Display all the stored key/value.''' file = ctx.obj['FILE'] if not os.path.isfile(file): raise click.BadParameter('Path "%s" does not exist.' % (file), ctx=ctx) dotenv_as_dict = dotenv_values(file) for k, v in dotenv_as_dict.items(): click.echo('%s=%s' % (k, v))
def unset(ctx: click.Context, key: Any) -> None: '''Removes the given key.''' file = ctx.obj['FILE'] quote = ctx.obj['QUOTE'] success, key = unset_key(file, key, quote) if success: click.echo("Successfully removed %s" % key) else: exit(1)
def show_help(ctx, param, value): if value and not ctx.resilient_parsing: if not ctx.invoked_subcommand: # legit main help echo(format_help(ctx.get_help())) else: # legit sub-command help echo(ctx.get_help(), color=ctx.color) ctx.exit()
def get(ctx: click.Context, key: Any) -> None: '''Retrieve the value for the given key.''' file = ctx.obj['FILE'] if not os.path.isfile(file): raise click.BadParameter('Path "%s" does not exist.' % (file), ctx=ctx) stored_value = get_key(file, key) if stored_value: click.echo(stored_value) else: exit(1)
def set(ctx: click.Context, key: Any, value: Any) -> None: '''Store the given key/value.''' file = ctx.obj['FILE'] quote = ctx.obj['QUOTE'] export = ctx.obj['EXPORT'] success, key, value = set_key(file, key, value, quote, export) if success: click.echo('%s=%s' % (key, value)) else: exit(1)
def lock(ctx, state, **kwargs): """Generates Pipfile.lock.""" from ..core import do_init, do_lock, ensure_project # Ensure that virtualenv is available. # Note that we don't pass clear on to ensure_project as it is also # handled in do_lock ensure_project( state.project, three=state.three, python=state.python, pypi_mirror=state.pypi_mirror, warn=(not state.quiet), site_packages=state.site_packages, ) emit_requirements = state.lockoptions.emit_requirements dev = state.installstate.dev dev_only = state.lockoptions.dev_only pre = state.installstate.pre if emit_requirements: # Emit requirements file header (unless turned off with --no-header) if state.lockoptions.emit_requirements_header: header_options = ["--requirements"] if dev_only: header_options.append("--dev-only") elif dev: header_options.append("--dev") echo(LOCK_HEADER.format(options=" ".join(header_options))) # TODO: Emit pip-compile style header if dev and not dev_only: echo(LOCK_DEV_NOTE) # Setting "emit_requirements=True" means do_init() just emits the # install requirements file to stdout, it doesn't install anything do_init( state.project, dev=dev, dev_only=dev_only, emit_requirements=emit_requirements, pypi_mirror=state.pypi_mirror, pre=pre, ) elif state.lockoptions.dev_only: raise PipenvOptionsError( "--dev-only", "--dev-only is only permitted in combination with --requirements. " "Aborting.") do_lock( state.project, ctx=ctx, clear=state.clear, pre=pre, keep_outdated=state.installstate.keep_outdated, pypi_mirror=state.pypi_mirror, write=not state.quiet, )
def show(self, file=None): if file is None: file = vistir.misc.get_text_stderr() if self.extra: if isinstance(self.extra, str): self.extra = [self.extra] for extra in self.extra: extra = "[pipenv.exceptions.{!s}]: {}".format( self.__class__.__name__, extra ) click.echo(extra, file=file) click.echo(f"{self.message}", file=file)
def run(ctx: click.Context, override: bool, commandline: List[str]) -> None: """Run command with environment variables present.""" file = ctx.obj['FILE'] if not os.path.isfile(file): raise click.BadParameter( 'Invalid value for \'-f\' "%s" does not exist.' % (file), ctx=ctx) dotenv_as_dict = { k: v for (k, v) in dotenv_values(file).items() if v is not None and (override or k not in os.environ) } if not commandline: click.echo('No command given.') exit(1) ret = run_command(commandline, dotenv_as_dict) exit(ret)
def scripts(state): """Lists scripts in current environment config.""" if not state.project.pipfile_exists: echo("No Pipfile present at project home.", err=True) sys.exit(1) scripts = state.project.parsed_pipfile.get("scripts", {}) first_column_width = max(len(word) for word in ["Command"] + list(scripts)) second_column_width = max( len(word) for word in ["Script"] + list(scripts.values())) lines = [ "{0:<{width}} Script".format("Command", width=first_column_width) ] lines.append("{} {}".format("-" * first_column_width, "-" * second_column_width)) lines.extend( "{0:<{width}} {1}".format(name, script, width=first_column_width) for name, script in scripts.items()) echo("\n".join(fix_utf8(line) for line in lines))
def get_paths(self): # type: () -> Optional[Dict[str, str]] """ Get the paths for the environment by running a subcommand :return: The python paths for the environment :rtype: Dict[str, str] """ tmpfile = vistir.path.create_tracked_tempfile(suffix=".json") tmpfile.close() tmpfile_path = make_posix(tmpfile.name) py_command = self.build_command(python_lib=True, python_inc=True, scripts=True, py_version=True) command = [self.python, "-c", py_command.format(tmpfile_path)] c = subprocess_run(command) if c.returncode == 0: paths = {} with open(tmpfile_path, "r", encoding="utf-8") as fh: paths = json.load(fh) if "purelib" in paths: paths["libdir"] = paths["purelib"] = make_posix( paths["purelib"]) for key in ( "platlib", "scripts", "platstdlib", "stdlib", "include", "platinclude", ): if key in paths: paths[key] = make_posix(paths[key]) return paths else: click.echo(f"Failed to load paths: {c.stderr}", fg="yellow") click.echo(f"Output: {c.stdout}", fg="yellow") return None
def shell( state, fancy=False, shell_args=None, anyway=False, ): """Spawns a shell within the virtualenv.""" from ..core import do_shell, load_dot_env # Prevent user from activating nested environments. if "PIPENV_ACTIVE" in os.environ: # If PIPENV_ACTIVE is set, VIRTUAL_ENV should always be set too. venv_name = os.environ.get("VIRTUAL_ENV", "UNKNOWN_VIRTUAL_ENVIRONMENT") if not anyway: echo( "{} {} {}\nNo action taken to avoid nested environments.". format( crayons.normal("Shell for"), crayons.green(venv_name, bold=True), crayons.normal("already activated.", bold=True), ), err=True, ) sys.exit(1) # Load .env file. load_dot_env(state.project) # Use fancy mode for Windows. if os.name == "nt": fancy = True do_shell( state.project, three=state.three, python=state.python, fancy=fancy, shell_args=shell_args, pypi_mirror=state.pypi_mirror, )
def show(self, file=None): if file is None: file = vistir.misc.get_text_stderr() click.echo( "{} {}".format( click.style("Error running command: ", fg="red"), click.style(f"$ {self.cmd}", bold=True), ), err=True, file=file, ) if self.out: click.echo( "{} {}".format("OUTPUT: ", self.out), file=file, err=True, ) if self.err: click_echo( "{} {}".format("STDERR: ", self.err), file=file, err=True, )
def verify(state): """Verify the hash in Pipfile.lock is up-to-date.""" if not state.project.pipfile_exists: echo("No Pipfile present at project home.", err=True) sys.exit(1) if state.project.get_lockfile_hash( ) != state.project.calculate_pipfile_hash(): echo( "Pipfile.lock is out-of-date. Run {} to update.".format( crayons.yellow("$ pipenv lock", bold=True)), err=True, ) sys.exit(1) echo(crayons.green("Pipfile.lock is up-to-date.")) sys.exit(0)
def show(self, file=None): if file is None: file = vistir.misc.get_text_stderr() color = None if self.ctx is not None: color = self.ctx.color if self.extra: if isinstance(self.extra, str): self.extra = [self.extra] for extra in self.extra: if color: extra = click.style(extra, fg=color) click.echo(extra, file=file) hint = "" if self.cmd is not None and self.cmd.get_help_option(self.ctx) is not None: hint = 'Try "%s %s" for help.\n' % ( self.ctx.command_path, self.ctx.help_option_names[0], ) if self.ctx is not None: click.echo(self.ctx.get_usage() + "\n%s" % hint, file=file, color=color) click.echo(self.message, file=file)
def update(ctx, state, bare=False, dry_run=None, outdated=False, **kwargs): """Runs lock, then sync.""" from ..core import do_lock, do_outdated, do_sync, ensure_project ensure_project( state.project, three=state.three, python=state.python, pypi_mirror=state.pypi_mirror, warn=(not state.quiet), site_packages=state.site_packages, clear=state.clear, ) if not outdated: outdated = bool(dry_run) if outdated: do_outdated( state.project, clear=state.clear, pre=state.installstate.pre, pypi_mirror=state.pypi_mirror, ) packages = [p for p in state.installstate.packages if p] editable = [p for p in state.installstate.editables if p] if not packages: echo("{} {} {} {}{}".format( crayons.normal("Running", bold=True), crayons.yellow("$ pipenv lock", bold=True), crayons.normal("then", bold=True), crayons.yellow("$ pipenv sync", bold=True), crayons.normal(".", bold=True), )) else: for package in packages + editable: if package not in state.project.all_packages: echo( "{}: {} was not found in your Pipfile! Aborting." "".format( crayons.red("Warning", bold=True), crayons.green(package, bold=True), ), err=True, ) ctx.abort() do_lock( state.project, ctx=ctx, clear=state.clear, pre=state.installstate.pre, keep_outdated=state.installstate.keep_outdated, pypi_mirror=state.pypi_mirror, write=not state.quiet, ) do_sync( state.project, dev=state.installstate.dev, three=state.three, python=state.python, bare=bare, dont_upgrade=not state.installstate.keep_outdated, user=False, clear=state.clear, unused=False, sequential=state.installstate.sequential, pypi_mirror=state.pypi_mirror, )
def cli( ctx, state, where=False, venv=False, py=False, envs=False, rm=False, bare=False, man=False, support=None, help=False, site_packages=None, **kwargs, ): from pipenv.utils.spinner import create_spinner from ..core import ( cleanup_virtualenv, do_clear, do_py, do_where, ensure_project, format_help, system_which, warn_in_virtualenv, ) if man: if system_which("man"): path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "pipenv.1") os.execle(system_which("man"), "man", path, os.environ) return 0 else: secho( "man does not appear to be available on your system.", fg="yellow", bold=True, err=True, ) return 1 if envs: echo( "The following environment variables can be set, to do various things:\n" ) for key in state.project.__dict__: if key.startswith("PIPENV"): echo(f" - {crayons.normal(key, bold=True)}") echo("\nYou can learn more at:\n {}".format( crayons.green( "https://pipenv.pypa.io/en/latest/advanced/#configuration-with-environment-variables" ))) return 0 warn_in_virtualenv(state.project) if ctx.invoked_subcommand is None: # --where was passed... if where: do_where(state.project, bare=True) return 0 elif py: do_py(state.project, ctx=ctx) return 0 # --support was passed... elif support: from ..help import get_pipenv_diagnostics get_pipenv_diagnostics(state.project) return 0 # --clear was passed... elif state.clear: do_clear(state.project) return 0 # --venv was passed... elif venv: # There is no virtualenv yet. if not state.project.virtualenv_exists: echo( "{}({}){}".format( crayons.red( "No virtualenv has been created for this project"), crayons.normal(state.project.project_directory, bold=True), crayons.red(" yet!"), ), err=True, ) ctx.abort() else: echo(state.project.virtualenv_location) return 0 # --rm was passed... elif rm: # Abort if --system (or running in a virtualenv). if state.project.s.PIPENV_USE_SYSTEM or environments.is_in_virtualenv( ): echo( crayons.red( "You are attempting to remove a virtualenv that " "Pipenv did not create. Aborting.")) ctx.abort() if state.project.virtualenv_exists: loc = state.project.virtualenv_location echo( crayons.normal("{} ({})...".format( crayons.normal("Removing virtualenv", bold=True), crayons.green(loc), ))) with create_spinner(text="Running...", setting=state.project.s): # Remove the virtualenv. cleanup_virtualenv(state.project, bare=True) return 0 else: echo( crayons.red( "No virtualenv has been created for this project yet!", bold=True, ), err=True, ) ctx.abort() # --python or --three was passed... if (state.python or state.three is not None) or state.site_packages: ensure_project( state.project, three=state.three, python=state.python, warn=True, site_packages=state.site_packages, pypi_mirror=state.pypi_mirror, clear=state.clear, ) # Check this again before exiting for empty ``pipenv`` command. elif ctx.invoked_subcommand is None: # Display help to user, if no commands were passed. echo(format_help(ctx.get_help()))
def lock(ctx, state, **kwargs): """Generates Pipfile.lock.""" from ..core import do_init, do_lock, ensure_project # Ensure that virtualenv is available. # Note that we don't pass clear on to ensure_project as it is also # handled in do_lock ensure_project( state.project, three=state.three, python=state.python, pypi_mirror=state.pypi_mirror, warn=(not state.quiet), site_packages=state.site_packages, ) emit_requirements = state.lockoptions.emit_requirements dev = state.installstate.dev dev_only = state.lockoptions.dev_only pre = state.installstate.pre if emit_requirements: secho( "Warning: The lock flag -r/--requirements will be deprecated in a future version\n" "of pipenv in favor of the new requirements command. For more info see\n" "https://pipenv.pypa.io/en/latest/advanced/#generating-a-requirements-txt\n" "NOTE: the requirements command parses Pipfile.lock directly without performing any\n" "locking operations. Updating packages should be done by running pipenv lock.", fg="yellow", err=True, ) # Emit requirements file header (unless turned off with --no-header) if state.lockoptions.emit_requirements_header: header_options = ["--requirements"] if dev_only: header_options.append("--dev-only") elif dev: header_options.append("--dev") echo(LOCK_HEADER.format(options=" ".join(header_options))) # TODO: Emit pip-compile style header if dev and not dev_only: echo(LOCK_DEV_NOTE) # Setting "emit_requirements=True" means do_init() just emits the # install requirements file to stdout, it doesn't install anything do_init( state.project, dev=dev, dev_only=dev_only, emit_requirements=emit_requirements, pypi_mirror=state.pypi_mirror, pre=pre, ) elif state.lockoptions.dev_only: raise PipenvOptionsError( "--dev-only", "--dev-only is only permitted in combination with --requirements. " "Aborting.", ) do_lock( state.project, ctx=ctx, clear=state.clear, pre=pre, keep_outdated=state.installstate.keep_outdated, pypi_mirror=state.pypi_mirror, write=not state.quiet, )
def cli(ctx, find=False, which=False, findall=False, version=False, ignore_unsupported=True): if version: click.echo("{0} version {1}".format( click.style("PythonFinder", fg="white", bold=True), click.style(str(__version__), fg="yellow"))) ctx.exit() finder = Finder(ignore_unsupported=ignore_unsupported) if findall: versions = [v for v in finder.find_all_python_versions()] if versions: click.secho("Found python at the following locations:", fg="green") for v in versions: py = v.py_version comes_from = getattr(py, "comes_from", None) if comes_from is not None: comes_from_path = getattr(comes_from, "path", v.path) else: comes_from_path = v.path click.secho( "{py.name!s}: {py.version!s} ({py.architecture!s}) @ {comes_from!s}" .format(py=py, comes_from=comes_from_path), fg="yellow", ) ctx.exit() else: click.secho( "ERROR: No valid python versions found! Check your path and try again.", fg="red", ) if find: click.secho("Searching for python: {0!s}".format(find.strip()), fg="yellow") found = finder.find_python_version(find.strip()) if found: py = found.py_version comes_from = getattr(py, "comes_from", None) if comes_from is not None: comes_from_path = getattr(comes_from, "path", found.path) else: comes_from_path = found.path arch = getattr(py, "architecture", None) click.secho("Found python at the following locations:", fg="green") click.secho( "{py.name!s}: {py.version!s} ({py.architecture!s}) @ {comes_from!s}" .format(py=py, comes_from=comes_from_path), fg="yellow", ) ctx.exit() else: click.secho("Failed to find matching executable...", fg="yellow") ctx.exit(1) elif which: found = finder.system_path.which(which.strip()) if found: click.secho("Found Executable: {0}".format(found), fg="white") ctx.exit() else: click.secho("Failed to find matching executable...", fg="yellow") ctx.exit(1) else: click.echo("Please provide a command", color="red") ctx.exit(1) ctx.exit()
def patched_cli(ctx, working_dir, python): if working_dir: if not os.path.isdir(working_dir): working_dir = os.path.dirname(working_dir) os.environ["PIPENV_PIPFILE"] = os.path.join(working_dir, "Pipfile") # we need to import environments and modify PIPENV_PIPFILE # to ensure that Project is imported with the right value from pipenv import environments environments.PIPENV_PIPFILE = os.environ.get("PIPENV_PIPFILE") from pipenv.project import Project if PYENV_INSTALLED: workon = None venv_name = None if python and python.startswith(PYENV_ROOT) and "bin/python" in python: workon = os.path.dirname(os.path.dirname(python)) workon = os.path.join(workon, "envs") try: venv_name = Project().virtualenv_name except AttributeError: # AttributeError is raised when pipenv does not find a valid # Pipfile and attempts spliting None pass if not workon and venv_name: versions = delegator.run("pyenv versions").out.splitlines( keepends=False) for v in versions: v = v.split() v = v[0] if v[0] != "*" else v[1] if "/envs/" in v: if v.endswith(venv_name): workon = os.path.join(PYENV_ROOT, "versions", os.path.dirname(v.strip())) break if not workon: c = delegator.run("pyenv which python") c.block() workon = os.path.dirname(os.path.dirname(c.out.strip())) workon = os.path.join(workon, "envs") os.environ["WORKON_HOME"] = workon ctx.call_on_close(venv_symlink(workon, venv_name)) if python: ctx.args = ["--python", python] + ctx.args try: venv_exists = Project().virtualenv_exists except: venv_exists = False if not ("install" in ctx.args or venv_exists): click.echo( crayons.red( "No virtualenv has been created for this project yet!"), err=True, ) ctx.abort() ctx.invoke(cli, ctx.args)