Esempio n. 1
0
    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
Esempio n. 2
0
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
Esempio n. 3
0
    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 {}
Esempio n. 4
0
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)
Esempio n. 5
0
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)
Esempio n. 6
0
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()
Esempio n. 7
0
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
Esempio n. 8
0
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()))
Esempio n. 9
0
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,
    )
Esempio n. 10
0
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)