mirror of
https://github.com/kennethreitz/pipenv.git
synced 2026-06-05 22:50:18 +00:00
Merge pull request #1917 from immerrr/make-costly-imports-lazy
Make costly imports lazy to optimize startup time
This commit is contained in:
+210
-182
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -17,8 +17,6 @@ import dotenv
|
||||
import delegator
|
||||
from .vendor import pexpect
|
||||
import pipfile
|
||||
import pipdeptree
|
||||
from .vendor.pipreqs import pipreqs
|
||||
from blindspin import spinner
|
||||
|
||||
from requests.packages import urllib3
|
||||
@@ -234,6 +232,7 @@ def ensure_environment():
|
||||
|
||||
|
||||
def import_from_code(path='.'):
|
||||
from pipreqs import pipreqs
|
||||
rs = []
|
||||
try:
|
||||
for r in pipreqs.get_all_imports(path):
|
||||
@@ -2341,6 +2340,7 @@ def do_check(three=None, python=False, system=False, unused=False, args=None):
|
||||
|
||||
|
||||
def do_graph(bare=False, json=False, reverse=False):
|
||||
import pipdeptree
|
||||
try:
|
||||
python_path = which('python')
|
||||
except AttributeError:
|
||||
|
||||
+2
-5
@@ -4,12 +4,10 @@ import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import shlex
|
||||
import base64
|
||||
import hashlib
|
||||
|
||||
import contoml
|
||||
import delegator
|
||||
import pipfile
|
||||
import pipfile.api
|
||||
import toml
|
||||
@@ -19,11 +17,9 @@ try:
|
||||
except ImportError:
|
||||
import pathlib2 as pathlib
|
||||
|
||||
from .vendor.pip9 import ConfigOptionParser
|
||||
from .cmdparse import Script
|
||||
from .utils import (
|
||||
mkdir_p,
|
||||
convert_deps_from_pip,
|
||||
pep423_name,
|
||||
proper_case,
|
||||
find_requirements,
|
||||
@@ -35,7 +31,6 @@ from .utils import (
|
||||
is_valid_url,
|
||||
normalize_drive,
|
||||
python_version,
|
||||
escape_grouped_arguments,
|
||||
)
|
||||
from .environments import (
|
||||
PIPENV_MAX_DEPTH,
|
||||
@@ -555,6 +550,7 @@ class Project(object):
|
||||
|
||||
def create_pipfile(self, python=None):
|
||||
"""Creates the Pipfile, filled with juicy defaults."""
|
||||
from .vendor.pip9 import ConfigOptionParser
|
||||
config_parser = ConfigOptionParser(name=self.name)
|
||||
install = dict(config_parser.get_config_section('install'))
|
||||
indexes = install.get('extra-index-url', '').lstrip('\n').split('\n')
|
||||
@@ -667,6 +663,7 @@ class Project(object):
|
||||
self.write_toml(p)
|
||||
|
||||
def add_package_to_pipfile(self, package_name, dev=False):
|
||||
from .utils import convert_deps_from_pip
|
||||
# Read and append Pipfile.
|
||||
p = self.parsed_pipfile
|
||||
# Don't re-capitalize file URLs or VCSs.
|
||||
|
||||
+36
-25
@@ -7,14 +7,12 @@ import tempfile
|
||||
import sys
|
||||
import shutil
|
||||
import logging
|
||||
import click
|
||||
import crayons
|
||||
import delegator
|
||||
import parse
|
||||
import requests
|
||||
import six
|
||||
import stat
|
||||
import warnings
|
||||
from click import echo as click_echo
|
||||
|
||||
try:
|
||||
from weakref import finalize
|
||||
@@ -45,16 +43,6 @@ except ImportError:
|
||||
pass
|
||||
from distutils.spawn import find_executable
|
||||
from contextlib import contextmanager
|
||||
from .patched.piptools.resolver import Resolver
|
||||
from .patched.piptools.repositories.pypi import PyPIRepository
|
||||
from .patched.piptools.scripts.compile import get_pip_command
|
||||
from .patched.piptools import logging as piptools_logging
|
||||
from .patched.piptools.exceptions import NoCandidateFound
|
||||
from .vendor.pip9.download import is_archive_file
|
||||
from .vendor.pip9.exceptions import DistributionNotFound
|
||||
from .vendor.pip9.index import Link
|
||||
from .vendor.pip9._vendor.requests.exceptions import HTTPError, ConnectionError
|
||||
|
||||
from .pep508checker import lookup
|
||||
from .environments import PIPENV_MAX_ROUNDS, PIPENV_CACHE_DIR
|
||||
|
||||
@@ -68,11 +56,22 @@ specifiers = [k for k in lookup.keys()]
|
||||
# List of version control systems we support.
|
||||
VCS_LIST = ('git', 'svn', 'hg', 'bzr')
|
||||
SCHEME_LIST = ('http://', 'https://', 'ftp://', 'ftps://', 'file://')
|
||||
requests = requests.Session()
|
||||
requests_session = None
|
||||
|
||||
|
||||
def _get_requests_session():
|
||||
"""Load requests lazily."""
|
||||
global requests_session
|
||||
if requests_session is not None:
|
||||
return requests_session
|
||||
import requests
|
||||
requests_session = requests.Session()
|
||||
return requests_session
|
||||
|
||||
|
||||
def get_requirement(dep):
|
||||
from .vendor.pip9.req.req_install import _strip_extras, Wheel
|
||||
from .vendor.pip9.index import Link
|
||||
from .vendor import requirements
|
||||
"""Pre-clean requirement strings passed to the requirements parser.
|
||||
|
||||
@@ -214,6 +213,7 @@ def parse_python_version(output):
|
||||
|
||||
|
||||
def python_version(path_to_python):
|
||||
import delegator
|
||||
if not path_to_python:
|
||||
return None
|
||||
try:
|
||||
@@ -298,6 +298,13 @@ def actually_resolve_reps(
|
||||
):
|
||||
from pip9 import basecommand, req
|
||||
from pip9._vendor import requests as pip_requests
|
||||
from pip9.exceptions import DistributionNotFound
|
||||
from pip9._vendor.requests.exceptions import HTTPError
|
||||
from pipenv.patched.piptools.resolver import Resolver
|
||||
from pipenv.patched.piptools.repositories.pypi import PyPIRepository
|
||||
from pipenv.patched.piptools.scripts.compile import get_pip_command
|
||||
from pipenv.patched.piptools import logging as piptools_logging
|
||||
from pipenv.patched.piptools.exceptions import NoCandidateFound
|
||||
|
||||
class PipCommand(basecommand.Command):
|
||||
"""Needed for pip-tools."""
|
||||
@@ -362,7 +369,7 @@ def actually_resolve_reps(
|
||||
try:
|
||||
resolved_tree.update(resolver.resolve(max_rounds=PIPENV_MAX_ROUNDS))
|
||||
except (NoCandidateFound, DistributionNotFound, HTTPError) as e:
|
||||
click.echo(
|
||||
click_echo(
|
||||
'{0}: Your dependencies could not be resolved. You likely have a mismatch in your sub-dependencies.\n '
|
||||
'You can use {1} to bypass this mechanism, then run {2} to inspect the situation.'
|
||||
''.format(
|
||||
@@ -372,9 +379,9 @@ def actually_resolve_reps(
|
||||
),
|
||||
err=True,
|
||||
)
|
||||
click.echo(crayons.blue(str(e)), err=True)
|
||||
click_echo(crayons.blue(str(e)), err=True)
|
||||
if 'no version found at all' in str(e):
|
||||
click.echo(
|
||||
click_echo(
|
||||
crayons.blue(
|
||||
'Please check your version specifier and version number. See PEP440 for more information.'
|
||||
)
|
||||
@@ -387,6 +394,7 @@ def actually_resolve_reps(
|
||||
def venv_resolve_deps(
|
||||
deps, which, project, pre=False, verbose=False, clear=False, allow_global=False
|
||||
):
|
||||
import delegator
|
||||
from . import resolver
|
||||
import json
|
||||
|
||||
@@ -406,13 +414,13 @@ def venv_resolve_deps(
|
||||
assert c.return_code == 0
|
||||
except AssertionError:
|
||||
if verbose:
|
||||
click.echo(c.out, err=True)
|
||||
click.echo(c.err, err=True)
|
||||
click_echo(c.out, err=True)
|
||||
click_echo(c.err, err=True)
|
||||
else:
|
||||
click.echo(c.err[int(len(c.err) / 2) - 1:], err=True)
|
||||
click_echo(c.err[int(len(c.err) / 2) - 1:], err=True)
|
||||
sys.exit(c.return_code)
|
||||
if verbose:
|
||||
click.echo(c.out.split('RESULTS:')[0], err=True)
|
||||
click_echo(c.out.split('RESULTS:')[0], err=True)
|
||||
try:
|
||||
return json.loads(c.out.split('RESULTS:')[1].strip())
|
||||
|
||||
@@ -434,6 +442,8 @@ def resolve_deps(
|
||||
"""Given a list of dependencies, return a resolved list of dependencies,
|
||||
using pip-tools -- and their hashes, using the warehouse API / pip9.
|
||||
"""
|
||||
from pip9._vendor.requests.exceptions import ConnectionError
|
||||
|
||||
index_lookup = {}
|
||||
markers_lookup = {}
|
||||
python_path = which('python', allow_global=allow_global)
|
||||
@@ -494,7 +504,7 @@ def resolve_deps(
|
||||
for source in sources):
|
||||
try:
|
||||
# Grab the hashes from the new warehouse API.
|
||||
r = requests.get(
|
||||
r = _get_requests_session().get(
|
||||
'https://pypi.org/pypi/{0}/json'.format(name),
|
||||
timeout=10,
|
||||
)
|
||||
@@ -511,7 +521,7 @@ def resolve_deps(
|
||||
]
|
||||
except (ValueError, KeyError, ConnectionError):
|
||||
if verbose:
|
||||
click.echo(
|
||||
click_echo(
|
||||
'{0}: Error generating hash for {1}'.format(
|
||||
crayons.red('Warning', bold=True), name
|
||||
)
|
||||
@@ -809,6 +819,7 @@ def is_installable_file(path):
|
||||
"""Determine if a path can potentially be installed"""
|
||||
from .vendor.pip9.utils import is_installable_dir
|
||||
from .vendor.pip9.utils.packaging import specifiers
|
||||
from .vendor.pip9.download import is_archive_file
|
||||
|
||||
if hasattr(path, 'keys') and any(
|
||||
key for key in path.keys() if key in ['file', 'path']
|
||||
@@ -878,7 +889,7 @@ def pep423_name(name):
|
||||
def proper_case(package_name):
|
||||
"""Properly case project name from pypi.org."""
|
||||
# Hit the simple API.
|
||||
r = requests.get(
|
||||
r = _get_requests_session().get(
|
||||
'https://pypi.org/pypi/{0}/json'.format(package_name),
|
||||
timeout=0.3,
|
||||
stream=True,
|
||||
@@ -1127,7 +1138,7 @@ def is_valid_url(url):
|
||||
|
||||
def download_file(url, filename):
|
||||
"""Downloads file from url to a path with filename"""
|
||||
r = requests.get(url, stream=True)
|
||||
r = _get_requests_session().get(url, stream=True)
|
||||
if not r.ok:
|
||||
raise IOError('Unable to download file')
|
||||
|
||||
|
||||
@@ -81,10 +81,10 @@ def test_editable_vcs_install(PipenvInstance, pip_src_dir, pypi):
|
||||
@pytest.mark.tablib
|
||||
@pytest.mark.needs_internet
|
||||
@flaky
|
||||
def test_install_editable_git_tag(PipenvInstance, pip_src_dir):
|
||||
def test_install_editable_git_tag(PipenvInstance, pip_src_dir, pypi):
|
||||
# This uses the real PyPI since we need Internet to access the Git
|
||||
# dependency anyway.
|
||||
with PipenvInstance() as p:
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
c = p.pipenv('install -e git+https://github.com/benjaminp/six.git@1.11.0#egg=six')
|
||||
assert c.return_code == 0
|
||||
assert 'six' in p.pipfile['packages']
|
||||
|
||||
Reference in New Issue
Block a user