diff --git a/pipenv/cli.py b/pipenv/cli.py index 6700925c..d989d267 100644 --- a/pipenv/cli.py +++ b/pipenv/cli.py @@ -135,6 +135,7 @@ def validate_pypi_mirror(ctx, param, value): is_flag=True, help="Output diagnostic information for use in Github issues.", ) +@option("--clear", is_flag=True, help="Clears caches (pipenv, pip, and pip-tools).") @version_option(prog_name=crayons.normal("pipenv", bold=True), version=__version__) @pass_context def cli( @@ -153,6 +154,7 @@ def cli( completion=False, pypi_mirror=None, support=None, + clear=False, ): # Handle this ASAP to make shell startup fast. if completion: @@ -180,6 +182,7 @@ def cli( cleanup_virtualenv, ensure_project, format_help, + do_clear, ) if man: @@ -203,19 +206,24 @@ def cli( sys.exit(0) warn_in_virtualenv() if ctx.invoked_subcommand is None: - # --where was passed... + # --where was passed… if where: do_where(bare=True) sys.exit(0) elif py: do_py() sys.exit() - # --support was passed... + # --support was passed… elif support: from .help import get_pipenv_diagnostics get_pipenv_diagnostics() sys.exit(0) + # --clear was passed… + elif clear: + do_clear() + sys.exit(0) + # --venv was passed... elif venv: # There is no virtualenv yet. @@ -270,6 +278,7 @@ def cli( warn=True, site_packages=site_packages, pypi_mirror=pypi_mirror, + clear=clear, ) # Check this again before exiting for empty ``pipenv`` command. elif ctx.invoked_subcommand is None: diff --git a/pipenv/core.py b/pipenv/core.py index 3838c7f8..6c943b91 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -122,6 +122,18 @@ def which(command, location=None, allow_global=False): project = Project(which=which) +def do_clear(): + click.echo(crayons.white("Clearing caches…", bold=True)) + import pip._internal.locations + import piptools + + try: + shutil.rmtree(PIPENV_CACHE_DIR) + shutil.rmtree(pip._internal.locations.USER_CACHE_DIR) + except FileNotFoundError: + pass + + def load_dot_env(): """Loads .env file into sys.environ.""" if not PIPENV_DONT_LOAD_ENV: @@ -582,10 +594,16 @@ def ensure_project( deploy=False, skip_requirements=False, pypi_mirror=None, + clear=False, ): """Ensures both Pipfile and virtualenv exist for the project.""" from .environments import PIPENV_USE_SYSTEM + # Clear the caches, if appropriate. + if clear: + print("clearing") + sys.exit(1) + # Automatically use an activated virtualenv. if PIPENV_USE_SYSTEM: system = True diff --git a/pipenv/patched/crayons.py b/pipenv/patched/crayons.py index 7c9ff0d2..a77886c5 100644 --- a/pipenv/patched/crayons.py +++ b/pipenv/patched/crayons.py @@ -12,21 +12,35 @@ import os import re import sys +import shellingham import colorama PY3 = sys.version_info[0] >= 3 __all__ = ( - 'red', 'green', 'yellow', 'blue', - 'black', 'magenta', 'cyan', 'white', 'normal', - 'clean', 'disable', + "red", + "green", + "yellow", + "blue", + "black", + "magenta", + "cyan", + "white", + "normal", + "clean", + "disable", ) COLORS = __all__[:-2] -if 'get_ipython' in dir(): - """ - when ipython is fired lot of variables like _oh, etc are used. +is_ipython = "get_ipython" in dir() +try: + is_powershell = "powershell" in shellingham.detect_shell()[0] +except shellingham.ShellDetectionFailure: + is_powershell = False + +if is_ipython or is_powershell: + """when ipython is fired lot of variables like _oh, etc are used. There are so many ways to find current python interpreter is ipython. get_ipython is easiest is most appealing for readers to understand. """ @@ -37,16 +51,17 @@ else: class ColoredString(object): """Enhanced string for __len__ operations on Colored output.""" + def __init__(self, color, s, always_color=False, bold=False): super(ColoredString, self).__init__() if not PY3 and isinstance(s, unicode): - self.s = s.encode('utf-8') + self.s = s.encode("utf-8") else: self.s = s self.color = color self.always_color = always_color self.bold = bold - if os.environ.get('PIPENV_FORCE_COLOR'): + if os.environ.get("PIPENV_FORCE_COLOR"): self.always_color = True def __getattr__(self, att): @@ -62,12 +77,19 @@ class ColoredString(object): return [self._new(x) for x in result] else: return result + return func_help @property def color_str(self): - style = 'BRIGHT' if self.bold else 'NORMAL' - c = '%s%s%s%s%s' % (getattr(colorama.Fore, self.color), getattr(colorama.Style, style), self.s, colorama.Fore.RESET, getattr(colorama.Style, 'NORMAL')) + style = "BRIGHT" if self.bold else "NORMAL" + c = "%s%s%s%s%s" % ( + getattr(colorama.Fore, self.color), + getattr(colorama.Style, style), + self.s, + colorama.Fore.RESET, + getattr(colorama.Style, "NORMAL"), + ) if self.always_color: return c @@ -85,12 +107,13 @@ class ColoredString(object): def __unicode__(self): value = self.color_str if isinstance(value, bytes): - return value.decode('utf8') + return value.decode("utf8") return value if PY3: __str__ = __unicode__ else: + def __str__(self): return self.color_str @@ -104,57 +127,59 @@ class ColoredString(object): return str(other) + str(self.color_str) def __mul__(self, other): - return (self.color_str * other) + return self.color_str * other def _new(self, s): return ColoredString(self.color, s) def clean(s): - strip = re.compile("([^-_a-zA-Z0-9!@#%&=,/'\";:~`\$\^\*\(\)\+\[\]\.\{\}\|\?\<\>\\]+|[^\s]+)") - txt = strip.sub('', str(s)) + strip = re.compile( + "([^-_a-zA-Z0-9!@#%&=,/'\";:~`\$\^\*\(\)\+\[\]\.\{\}\|\?\<\>\\]+|[^\s]+)" + ) + txt = strip.sub("", str(s)) - strip = re.compile(r'\[\d+m') - txt = strip.sub('', txt) + strip = re.compile(r"\[\d+m") + txt = strip.sub("", txt) return txt def normal(string, always=False, bold=False): - return ColoredString('RESET', string, always_color=always, bold=bold) + return ColoredString("RESET", string, always_color=always, bold=bold) def black(string, always=False, bold=False): - return ColoredString('BLACK', string, always_color=always, bold=bold) + return ColoredString("BLACK", string, always_color=always, bold=bold) def red(string, always=False, bold=False): - return ColoredString('RED', string, always_color=always, bold=bold) + return ColoredString("RED", string, always_color=always, bold=bold) def green(string, always=False, bold=False): - return ColoredString('GREEN', string, always_color=always, bold=bold) + return ColoredString("GREEN", string, always_color=always, bold=bold) def yellow(string, always=False, bold=False): - return ColoredString('YELLOW', string, always_color=always, bold=bold) + return ColoredString("YELLOW", string, always_color=always, bold=bold) def blue(string, always=False, bold=False): - return ColoredString('BLUE', string, always_color=always, bold=bold) + return ColoredString("BLUE", string, always_color=always, bold=bold) def magenta(string, always=False, bold=False): - return ColoredString('MAGENTA', string, always_color=always, bold=bold) + return ColoredString("MAGENTA", string, always_color=always, bold=bold) def cyan(string, always=False, bold=False): - return ColoredString('CYAN', string, always_color=always, bold=bold) + return ColoredString("CYAN", string, always_color=always, bold=bold) def white(string, always=False, bold=False): # This upsets people... - return ColoredString('WHITE', string, always_color=always, bold=bold) + return ColoredString("WHITE", string, always_color=always, bold=bold) def disable():