def get_include_path(self): # type: () -> Optional[Dict[str, str]] """Get the include path for the environment :return: The python include path 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 = ( "import distutils.sysconfig, io, json, sys; paths = {{u'include': " "u'{{0}}'.format(distutils.sysconfig.get_python_inc(plat_specific=0)), " "u'platinclude': u'{{0}}'.format(distutils.sysconfig.get_python_inc(" "plat_specific=1)) }}; value = u'{{0}}'.format(json.dumps(paths));" "fh = io.open('{0}', 'w'); fh.write(value); fh.close()") 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) for key in ("include", "platinclude"): if key in paths: paths[key] = make_posix(paths[key]) return paths else: click.secho(f"Failed to load paths: {c.stderr}", fg="yellow") click.secho(f"Output: {c.stdout}", fg="yellow") return None
def get_proxy_dict(proxyprotocol, proxyhost, proxyport): proxy_dictionary = {} if proxyhost is not None: if proxyprotocol in ["http", "https"]: proxy_dictionary = { proxyprotocol: "{0}://{1}:{2}".format(proxyprotocol, proxyhost, str(proxyport)) } else: click.secho("Proxy Protocol should be http or https only.", fg="red") sys.exit(-1) return proxy_dictionary
def get_lib_paths(self): # type: () -> Dict[str, str] """Get the include path for the environment :return: The python include path 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) command = [self.python, "-c", py_command.format(tmpfile_path)] c = subprocess_run(command) paths = None 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", "platstdlib", "stdlib"): if key in paths: paths[key] = make_posix(paths[key]) return paths else: click.secho(f"Failed to load paths: {c.stderr}", fg="yellow") click.secho(f"Output: {c.stdout}", fg="yellow") if not paths: if not self.prefix.joinpath("lib").exists(): return {} stdlib_path = next( iter([ p for p in self.prefix.joinpath("lib").iterdir() if p.name.startswith("python") ]), None, ) lib_path = None if stdlib_path: lib_path = next( iter([ p.as_posix() for p in stdlib_path.iterdir() if p.name == "site-packages" ])) paths = {"stdlib": stdlib_path.as_posix()} if lib_path: paths["purelib"] = lib_path return paths return {}
def license(key, db, json, bare, cache, files, proxyprotocol, proxyhost, proxyport): if files: packages = list( itertools.chain.from_iterable( read_requirements(f, resolve=True) for f in files)) else: import pkg_resources packages = [ d for d in pkg_resources.working_set if d.key not in {"python", "wsgiref", "argparse"} ] proxy_dictionary = get_proxy_dict(proxyprotocol, proxyhost, proxyport) try: licenses_db = safety.get_licenses(key, db, cache, proxy_dictionary) except InvalidKeyError as invalid_key_error: if str(invalid_key_error): message = str(invalid_key_error) else: message = "Your API Key '{key}' is invalid. See {link}".format( key=key, link='https://goo.gl/O7Y1rS') click.secho(message, fg="red", file=sys.stderr) sys.exit(-1) except DatabaseFileNotFoundError: click.secho("Unable to load licenses database from {db}".format(db=db), fg="red", file=sys.stderr) sys.exit(-1) except TooManyRequestsError: click.secho( "Unable to load licenses database (Too many requests, please wait before another request)", fg="red", file=sys.stderr) sys.exit(-1) except DatabaseFetchError: click.secho("Unable to load licenses database", fg="red", file=sys.stderr) sys.exit(-1) filtered_packages_licenses = get_packages_licenses(packages, licenses_db) output_report = license_report(packages=packages, licenses=filtered_packages_licenses, json_report=json, bare_report=bare) click.secho(output_report, nl=True)
def review(full_report, bare, file): if full_report and bare: click.secho( "Can't choose both --bare and --full-report/--short-report", fg="red") sys.exit(-1) try: input_vulns = read_vulnerabilities(file) except JSONDecodeError: click.secho("Not a valid JSON file", fg="red") sys.exit(-1) vulns = safety.review(input_vulns) output_report = report(vulns=vulns, full=full_report, bare_report=bare) click.secho(output_report, nl=False if bare and not vulns else True)
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 read_requirements(fh, resolve=False): """ Reads requirements from a file like object and (optionally) from referenced files. :param fh: file like object to read from :param resolve: boolean. resolves referenced files. :return: generator """ is_temp_file = not hasattr(fh, 'name') for num, line in enumerate(iter_lines(fh)): line = line.strip() if not line: # skip empty lines continue if line.startswith('#') or \ line.startswith('-i') or \ line.startswith('--index-url') or \ line.startswith('--extra-index-url') or \ line.startswith('-f') or line.startswith('--find-links') or \ line.startswith('--no-index') or line.startswith('--allow-external') or \ line.startswith('--allow-unverified') or line.startswith('-Z') or \ line.startswith('--always-unzip'): # skip unsupported lines continue elif line.startswith('-r') or line.startswith('--requirement'): # got a referenced file here, try to resolve the path # if this is a tempfile, skip if is_temp_file: continue # strip away the recursive flag prefixes = ["-r", "--requirement"] filename = line.strip() for prefix in prefixes: if filename.startswith(prefix): filename = filename[len(prefix):].strip() # if there is a comment, remove it if " #" in filename: filename = filename.split(" #")[0].strip() req_file_path = os.path.join(os.path.dirname(fh.name), filename) if resolve: # recursively yield the resolved requirements if os.path.exists(req_file_path): with open(req_file_path) as _fh: for req in read_requirements(_fh, resolve=True): yield req else: yield RequirementFile(path=req_file_path) else: try: parseable_line = line # multiline requirements are not parseable if "\\" in line: parseable_line = line.replace("\\", "") for next_line in iter_lines(fh, num + 1): parseable_line += next_line.strip().replace("\\", "") line += "\n" + next_line if "\\" in next_line: continue break req, = parse_line(parseable_line) if len(req.specifier._specs) == 1 and \ next(iter(req.specifier._specs))._spec[0] == "==": yield Package(key=req.name, version=next(iter( req.specifier._specs))._spec[1]) else: try: fname = fh.name except AttributeError: fname = line click.secho( "Warning: unpinned requirement '{req}' found in {fname}, " "unable to check.".format(req=req.name, fname=fname), fg="yellow", file=sys.stderr) except ValueError: continue
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 check(key, db, json, full_report, bare, stdin, files, cache, ignore, output, proxyprotocol, proxyhost, proxyport): if files and stdin: click.secho( "Can't read from --stdin and --file at the same time, exiting", fg="red", file=sys.stderr) sys.exit(-1) if files: packages = list( itertools.chain.from_iterable( read_requirements(f, resolve=True) for f in files)) elif stdin: packages = list(read_requirements(sys.stdin)) else: import pkg_resources packages = [ d for d in pkg_resources.working_set if d.key not in {"python", "wsgiref", "argparse"} ] proxy_dictionary = get_proxy_dict(proxyprotocol, proxyhost, proxyport) try: vulns = safety.check(packages=packages, key=key, db_mirror=db, cached=cache, ignore_ids=ignore, proxy=proxy_dictionary) output_report = report(vulns=vulns, full=full_report, json_report=json, bare_report=bare, checked_packages=len(packages), db=db, key=key) if output: with open(output, 'w+') as output_file: output_file.write(output_report) else: click.secho(output_report, nl=False if bare and not vulns else True) sys.exit(-1 if vulns else 0) except InvalidKeyError: click.secho("Your API Key '{key}' is invalid. See {link}".format( key=key, link='https://goo.gl/O7Y1rS'), fg="red", file=sys.stderr) sys.exit(-1) except DatabaseFileNotFoundError: click.secho( "Unable to load vulnerability database from {db}".format(db=db), fg="red", file=sys.stderr) sys.exit(-1) except DatabaseFetchError: click.secho("Unable to load vulnerability database", fg="red", file=sys.stderr) sys.exit(-1)