From 9bd49f97597199aa082f438768a434d8ed0b0536 Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Tue, 10 Jul 2018 17:58:31 +0800 Subject: [PATCH 1/2] Automatically generate environment variable docs Default values are added to docstrings so they appear in the docs. This should help maintainers to keep them up-to-date. Fix #2547. --- docs/_static/custom.css | 7 ++ docs/advanced.rst | 36 +----- docs/conf.py | 10 +- docs/diagnose.rst | 2 +- pipenv/environments.py | 257 ++++++++++++++++++++++++++++++---------- pipenv/shells.py | 2 +- 6 files changed, 214 insertions(+), 100 deletions(-) create mode 100644 docs/_static/custom.css diff --git a/docs/_static/custom.css b/docs/_static/custom.css new file mode 100644 index 00000000..8ada6183 --- /dev/null +++ b/docs/_static/custom.css @@ -0,0 +1,7 @@ +/* Hide module name and default value for environment variable section */ +div[id$='environment-variables'] code.descclassname { + display: none; +} +div[id$='environment-variables'] em.property { + display: none; +} diff --git a/docs/advanced.rst b/docs/advanced.rst index 7e5cbc05..306ba10d 100644 --- a/docs/advanced.rst +++ b/docs/advanced.rst @@ -377,40 +377,8 @@ Pipenv comes with a handful of options that can be enabled via shell environment variables. To activate them, simply create the variable in your shell and pipenv will detect it. - - ``PIPENV_DEFAULT_PYTHON_VERSION`` — Use this version of Python when creating new virtual environments, by default (e.g. ``3.6``). - - - ``PIPENV_SHELL_FANCY`` — Always use fancy mode when invoking ``pipenv shell``. - - - ``PIPENV_VENV_IN_PROJECT`` — If set, use ``.venv`` in your project directory - instead of a global location. - - - ``PIPENV_COLORBLIND`` — Disable terminal colors, for some reason. - - - ``PIPENV_NOSPIN`` — Disable terminal spinner, for cleaner logs. Automatically set in CI environments. - - - ``PIPENV_MAX_DEPTH`` — Set to an integer for the maximum number of directories to recursively - search for a Pipfile. - - - ``PIPENV_TIMEOUT`` — Set to an integer for the max number of seconds Pipenv will - wait for virtualenv creation to complete. Defaults to 120 seconds. - - - ``PIPENV_INSTALL_TIMEOUT`` — Set to an integer for the max number of seconds Pipenv will wait - for package installation before timing out. Defaults to 900 seconds. - - - ``PIPENV_IGNORE_VIRTUALENVS`` — Set to disable automatically using an activated virtualenv over - the current project's own virtual environment. - - - ``PIPENV_PIPFILE`` — When running pipenv from a $PWD other than the same - directory where the Pipfile is located, instruct pipenv to find the - Pipfile in the location specified by this environment variable. - - - ``PIPENV_CACHE_DIR`` — Location for Pipenv to store it's package cache. - - - ``PIPENV_HIDE_EMOJIS`` — Disable emojis in output. - - - ``PIPENV_DOTENV_LOCATION`` — Location for Pipenv to load your project's .env. - - - ``PIPENV_DONT_LOAD_ENV`` — Tell Pipenv not to load the .env files automatically. +.. automodule:: pipenv.environments + :members: If you'd like to set these environment variables on a per-project basis, I recommend utilizing the fantastic `direnv `_ project, in order to do so. diff --git a/docs/conf.py b/docs/conf.py index cf62f99e..d3e5c222 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -35,11 +35,13 @@ with open(os.path.join(here, "..", "pipenv", "__version__.py")) as f: # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['sphinx.ext.autodoc', +extensions = [ + 'sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.viewcode', - 'sphinx_click.ext'] + 'sphinx_click.ext', +] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -119,6 +121,10 @@ html_sidebars = { html_static_path = ['_static'] +def setup(app): + app.add_stylesheet('custom.css') + + # -- Options for HTMLHelp output ------------------------------------------ # Output file base name for HTML help builder. diff --git a/docs/diagnose.rst b/docs/diagnose.rst index 88407099..650e70a1 100644 --- a/docs/diagnose.rst +++ b/docs/diagnose.rst @@ -18,7 +18,7 @@ below and see if they resolve your problem. Make sure your dependencies actually *do* resolve. If you’re confident they are, you may need to clear your resolver cache. Run the following command:: - pipenv run pipenv-resolver --clear + pipenv lock --clear and try again. diff --git a/pipenv/environments.py b/pipenv/environments.py index ac30fc16..63792746 100644 --- a/pipenv/environments.py +++ b/pipenv/environments.py @@ -2,79 +2,212 @@ import os import sys from appdirs import user_cache_dir + +# HACK: avoid resolver.py uses the wrong byte code files. +# I hope I can remove this one day. os.environ["PYTHONDONTWRITEBYTECODE"] = "1" -# Prevent invalid shebangs with Homebrew-installed Python: +# HACK: Prevent invalid shebangs with Homebrew-installed Python: # https://bugs.python.org/issue22490 os.environ.pop("__PYVENV_LAUNCHER__", None) -# Shell compatibility mode, for mis-configured shells. -PIPENV_SHELL_FANCY = bool(os.environ.get("PIPENV_SHELL_FANCY")) -# Support for both Python 2 and Python 3 at the same time. -PIPENV_PYTHON = os.environ.get("PIPENV_PYTHON") -# Create the virtualenv in the project, instead of in WORKON_HOME. -PIPENV_VENV_IN_PROJECT = bool(os.environ.get("PIPENV_VENV_IN_PROJECT")) -# Overwrite all index funcitonality. -PIPENV_TEST_INDEX = os.environ.get("PIPENV_TEST_INDEX") -# No color mode, for unfun people. + + +PIPENV_CACHE_DIR = os.environ.get("PIPENV_CACHE_DIR", user_cache_dir("pipenv")) +"""Location for Pipenv to store it's package cache. + +Default is to use appdir's user cache directory. +""" + PIPENV_COLORBLIND = bool(os.environ.get("PIPENV_COLORBLIND")) -# Disable spinner for better test and deploy logs (for the unworthy). -PIPENV_NOSPIN = bool(os.environ.get("PIPENV_NOSPIN")) -# Tells Pipenv how many rounds of resolving to do for Pip-Tools. -PIPENV_MAX_ROUNDS = int(os.environ.get("PIPENV_MAX_ROUNDS", "16")) -# Specify how many retries Pipenv should attempt for network requests. -default_retries = "1" if "CI" in os.environ else "0" -PIPENV_MAX_RETRIES = int(os.environ.get("PIPENV_MAX_RETRIES", default_retries)) -# Specify a custom Pipfile location. -PIPENV_PIPFILE = os.environ.get("PIPENV_PIPFILE") +"""If set, disable terminal colors. + +Some people don't like colors in their terminals, for some reason. Default is +to show colors. +""" + # Tells Pipenv which Python to default to, when none is provided. PIPENV_DEFAULT_PYTHON_VERSION = os.environ.get("PIPENV_DEFAULT_PYTHON_VERSION") -# Tells Pipenv to not load .env files. +"""Use this Python version when creating new virtual environments by default. + +This can be set to a version string, e.g. ``3.6``, or a path. Default is to use +whatever Python Pipenv is installed under (i.e. ``sys.executable``). Command +line flags (e.g. ``--python``, ``--three``, and ``--two``) are prioritized over +this configuration. +""" + PIPENV_DONT_LOAD_ENV = bool(os.environ.get("PIPENV_DONT_LOAD_ENV")) -# Tell Pipenv to default to yes at all prompts. -PIPENV_YES = bool(os.environ.get("PIPENV_YES")) -# Tells Pipenv how many subprocesses to use when installing. -PIPENV_MAX_SUBPROCESS = int(os.environ.get("PIPENV_MAX_SUBPROCESS", "16")) -# User-configurable max-depth for Pipfile searching. -# Note: +1 because of a temporary bug in Pipenv. -PIPENV_MAX_DEPTH = int(os.environ.get("PIPENV_MAX_DEPTH", "3")) + 1 -# Tell Pipenv not to inherit parent directories (for development, mostly). -PIPENV_NO_INHERIT = "PIPENV_NO_INHERIT" in os.environ -if PIPENV_NO_INHERIT: - PIPENV_MAX_DEPTH = 2 -# Tells Pipenv to use the virtualenv-provided pip instead. -PIPENV_VIRTUALENV = None -PIPENV_USE_SYSTEM = False -if "PIPENV_ACTIVE" not in os.environ: - if "PIPENV_IGNORE_VIRTUALENVS" not in os.environ: - PIPENV_VIRTUALENV = os.environ.get("VIRTUAL_ENV") - PIPENV_USE_SYSTEM = bool(os.environ.get("VIRTUAL_ENV")) -# Tells Pipenv to use hashing mode. -PIPENV_USE_HASHES = True -# Tells Pipenv to skip case-checking (slow internet connections). -PIPENV_SKIP_VALIDATION = True -# Tells Pipenv where to load .env from. +"""If set, Pipenv does not load the ``.env`` file. + +Default is to load ``.env`` for ``run`` and ``shell`` commands. +""" + +PIPENV_DONT_USE_PYENV = bool(os.environ.get("PIPENV_DONT_USE_PYENV")) +"""If set, Pipenv does not attempt to install Python with pyenv. + +Default is to install Python automatically via pyenv when needed, if possible. +""" + PIPENV_DOTENV_LOCATION = os.environ.get("PIPENV_DOTENV_LOCATION") -# Disable spinner on Windows. -if os.name == "nt": - PIPENV_NOSPIN = True -# Disable the spinner on Travis-Ci (and friends). -if "CI" in os.environ: - PIPENV_NOSPIN = True +"""If set, Pipenv loads the ``.env`` file at the specified location. + +Default is to load ``.env`` from the project root, if found. +""" + +PIPENV_EMULATOR = os.environ.get("PIPENV_EMULATOR") +"""If set, the terminal emulator's name for ``pipenv shell`` to use. + +Default is to detect emulators automatically. This should be set if your +emulator, e.g. Cmder, cannot be detected correctly. +""" + PIPENV_HIDE_EMOJIS = bool(os.environ.get("PIPENV_HIDE_EMOJIS")) +"""Disable emojis in output. + +Default is to show emojis. This is automatically set on Windows. +""" if os.name == "nt": PIPENV_HIDE_EMOJIS = True -# Tells Pipenv how long to wait for virtualenvs to be created in seconds. -PIPENV_TIMEOUT = int(os.environ.get("PIPENV_TIMEOUT", 120)) + +PIPENV_IGNORE_VIRTUALENVS = bool(os.environ.get("PIPENV_IGNORE_VIRTUALENVS")) +"""If set, Pipenv will always assign a virtual environment for this project. + +By default, Pipenv tries to detect whether it is run inside a virtual +environment, and reuses it if possible. This is usually the desired behavior, +and enables the user to use any user-built environments with Pipenv. +""" + PIPENV_INSTALL_TIMEOUT = 60 * 15 -PIPENV_DONT_USE_PYENV = os.environ.get("PIPENV_DONT_USE_PYENV") -PYENV_ROOT = os.environ.get("PYENV_ROOT", os.path.expanduser("~/.pyenv")) -PYENV_INSTALLED = bool(os.environ.get("PYENV_SHELL")) or bool( - os.environ.get("PYENV_ROOT") -) -SESSION_IS_INTERACTIVE = bool(os.isatty(sys.stdout.fileno())) -PIPENV_SHELL_EXPLICIT = os.environ.get("PIPENV_SHELL") -PIPENV_SHELL = os.environ.get("SHELL") or os.environ.get("PYENV_SHELL") -PIPENV_EMULATOR = os.environ.get("PIPENV_EMULATOR") -PIPENV_CACHE_DIR = os.environ.get("PIPENV_CACHE_DIR", user_cache_dir("pipenv")) -# Tells pipenv to override PyPI index urls with a mirror. +"""Max number of seconds to wait for package installation. + +Defaults to 900 (15 minutes), a very long arbitrary time. +""" + +# NOTE: +1 because of a temporary bug in Pipenv. +PIPENV_MAX_DEPTH = int(os.environ.get("PIPENV_MAX_DEPTH", "3")) + 1 +"""Maximum number of directories to recursively search for a Pipfile. + +Default is 3. See also ``PIPENV_NO_INHERIT``. +""" + +PIPENV_MAX_RETRIES = int(os.environ.get( + "PIPENV_MAX_RETRIES", + "1" if "CI" in os.environ else "0", +)) +"""Specify how many retries Pipenv should attempt for network requests. + +Default is 0. Aautomatically set to 1 on CI environments for robust testing. +""" + +PIPENV_MAX_ROUNDS = int(os.environ.get("PIPENV_MAX_ROUNDS", "16")) +"""Tells Pipenv how many rounds of resolving to do for Pip-Tools. + +Default is 16, an arbitrary number that works most of the time. +""" + +PIPENV_MAX_SUBPROCESS = int(os.environ.get("PIPENV_MAX_SUBPROCESS", "16")) +"""How many subprocesses should Pipenv use when installing. + +Default is 16, an arbitrary number that seems to work. +""" + +PIPENV_NO_INHERIT = "PIPENV_NO_INHERIT" in os.environ +"""Tell Pipenv not to inherit parent directories. + +This is useful for deployment to avoid using the wrong current directory. +Overwrites ``PIPENV_MAX_DEPTH``. +""" +if PIPENV_NO_INHERIT: + PIPENV_MAX_DEPTH = 2 + +PIPENV_NOSPIN = bool(os.environ.get("PIPENV_NOSPIN")) +"""If set, disable terminal spinner. + +This can make the logs cleaner. Automatically set on Windows, and in CI +environments. +""" +if os.name == "nt" or "CI" in os.environ: + PIPENV_NOSPIN = True + +PIPENV_PIPFILE = os.environ.get("PIPENV_PIPFILE") +"""If set, this specifies a custom Pipfile location. + +When running pipenv from a location other than the same directory where the +Pipfile is located, instruct pipenv to find the Pipfile in the location +specified by this environment variable. + +Default is to find Pipfile automatically in the current and parent directories. +See also ``PIPENV_MAX_DEPTH``. +""" + PIPENV_PYPI_MIRROR = os.environ.get("PIPENV_PYPI_MIRROR") +"""If set, tells pipenv to override PyPI index urls with a mirror. + +Default is to not mirror PyPI, i.e. use the real one, pypi.org. The +``--pypi-mirror`` command line flag overwrites this. +""" + +PIPENV_SHELL = os.environ.get("PIPENV_SHELL") +"""An absolute path to the preferred shell for ``pipenv shell``. + +Default is to detect automatically what shell is currently in use. +""" +# Hack because PIPENV_SHELL is actually something else. Internally this +# variable is called PIPENV_SHELL_EXPLICIT instead. +PIPENV_SHELL_EXPLICIT = PIPENV_SHELL +del PIPENV_SHELL + +PIPENV_SHELL_FANCY = bool(os.environ.get("PIPENV_SHELL_FANCY")) +"""If set, always use fancy mode when invoking ``pipenv shell``. + +Default is to use the compatibility shell if possible. +""" + +PIPENV_TIMEOUT = int(os.environ.get("PIPENV_TIMEOUT", 120)) +"""Max number of seconds Pipenv will wait for virtualenv creation to complete. + +Default is 120 seconds, an arbitrary number that seems to work. +""" + +PIPENV_VENV_IN_PROJECT = bool(os.environ.get("PIPENV_VENV_IN_PROJECT")) +"""If set, creates ``.venv`` in your project directory. + +Default is to create new virtual environments in a global location. +""" + +PIPENV_YES = bool(os.environ.get("PIPENV_YES")) +"""If set, Pipenv automatically assumes "yes" at all prompts. + +Default is to prompt the user for an answer if the current command line session +if interactive. +""" + + +# Internal, support running in a different Python from sys.executable. +PIPENV_PYTHON = os.environ.get("PIPENV_PYTHON") + +# Internal, overwrite all index funcitonality. +PIPENV_TEST_INDEX = os.environ.get("PIPENV_TEST_INDEX") + +# Internal, tells Pipenv about the surrounding environment. +PIPENV_USE_SYSTEM = False +PIPENV_VIRTUALENV = None +if "PIPENV_ACTIVE" not in os.environ and not PIPENV_IGNORE_VIRTUALENVS: + PIPENV_VIRTUALENV = os.environ.get("VIRTUAL_ENV") + PIPENV_USE_SYSTEM = bool(PIPENV_VIRTUALENV) + +# Internal, tells Pipenv to skip case-checking (slow internet connections). +# This is currently always set to True for performance reasons. +PIPENV_SKIP_VALIDATION = True + +# Internal, the default shell to use if shell detection fails. +PIPENV_SHELL = os.environ.get("SHELL") or os.environ.get("PYENV_SHELL") + +# Internal, to tell if pyenv is installed. +PYENV_ROOT = os.environ.get("PYENV_ROOT", os.path.expanduser("~/.pyenv")) +PYENV_INSTALLED = ( + bool(os.environ.get("PYENV_SHELL")) or + bool(os.environ.get("PYENV_ROOT")) +) + +# Internal, to tell whether the command line session is interactive. +SESSION_IS_INTERACTIVE = bool(os.isatty(sys.stdout.fileno())) diff --git a/pipenv/shells.py b/pipenv/shells.py index 0081ef5d..02c9d951 100644 --- a/pipenv/shells.py +++ b/pipenv/shells.py @@ -210,6 +210,6 @@ def _detect_emulator(): def choose_shell(): - emulator = PIPENV_EMULATOR or _detect_emulator() + emulator = PIPENV_EMULATOR.lower() or _detect_emulator() type_, command = detect_info() return SHELL_LOOKUP[type_][emulator](command) From 46876159b299d04de9b3f939bfe719d8c46d4683 Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Tue, 10 Jul 2018 19:51:54 +0800 Subject: [PATCH 2/2] Type is important --- pipenv/environments.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipenv/environments.py b/pipenv/environments.py index 63792746..f241172a 100644 --- a/pipenv/environments.py +++ b/pipenv/environments.py @@ -53,7 +53,7 @@ PIPENV_DOTENV_LOCATION = os.environ.get("PIPENV_DOTENV_LOCATION") Default is to load ``.env`` from the project root, if found. """ -PIPENV_EMULATOR = os.environ.get("PIPENV_EMULATOR") +PIPENV_EMULATOR = os.environ.get("PIPENV_EMULATOR", "") """If set, the terminal emulator's name for ``pipenv shell`` to use. Default is to detect emulators automatically. This should be set if your