From c9041b8edbfed1abfbdf927476366994f3ef1095 Mon Sep 17 00:00:00 2001 From: Frost Ming Date: Wed, 19 Dec 2018 10:26:20 +0800 Subject: [PATCH 1/4] Decouple project from the existence of Pipfile. --- news/3386.trivial.rst | 1 + pipenv/cli/command.py | 6 +++++- pipenv/core.py | 27 ++++++++++++++++----------- pipenv/project.py | 23 +++++++---------------- 4 files changed, 29 insertions(+), 28 deletions(-) create mode 100644 news/3386.trivial.rst diff --git a/news/3386.trivial.rst b/news/3386.trivial.rst new file mode 100644 index 00000000..632b8153 --- /dev/null +++ b/news/3386.trivial.rst @@ -0,0 +1 @@ +Decouple project from the existence of Pipfile. diff --git a/pipenv/cli/command.py b/pipenv/cli/command.py index ec1bef61..84dd0c21 100644 --- a/pipenv/cli/command.py +++ b/pipenv/cli/command.py @@ -154,7 +154,11 @@ def cli( # There is no virtualenv yet. if not project.virtualenv_exists: echo( - crayons.red("No virtualenv has been created for this project yet!"), + "{}({}){}".format( + crayons.red("No virtualenv has been created for this project"), + crayons.white(project.project_directory, bold=True), + crayons.red(" yet!") + ), err=True, ) ctx.abort() diff --git a/pipenv/core.py b/pipenv/core.py index 4fb7939e..c6d76f1c 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -540,11 +540,16 @@ def ensure_project( # Automatically use an activated virtualenv. if PIPENV_USE_SYSTEM: system = True - if not project.pipfile_exists: - if deploy is True: - raise exceptions.PipfileNotFound - else: - project.touch_pipfile() + if not project.pipfile_exists and deploy: + raise exceptions.PipfileNotFound + # Fail if working under / + if not project.name: + click.echo( + "{0}: Pipenv is not intended to work under the root directory, " + "please choose another path.".format(crayons.red("ERROR")), + err=True + ) + sys.exit(1) # Skip virtualenv creation when --system was used. if not system: ensure_virtualenv( @@ -607,24 +612,24 @@ def shorten_path(location, bold=False): def do_where(virtualenv=False, bare=True): """Executes the where functionality.""" if not virtualenv: - location = project.pipfile_location - # Shorten the virtual display of the path to the virtualenv. - if not bare: - location = shorten_path(location) - if not location: + if not project.pipfile_exists: click.echo( "No Pipfile present at project home. Consider running " "{0} first to automatically generate a Pipfile for you." "".format(crayons.green("`pipenv install`")), err=True, ) + return + location = project.pipfile_location + # Shorten the virtual display of the path to the virtualenv. + if not bare: + location = shorten_path(location) elif not bare: click.echo( "Pipfile found at {0}.\n Considering this to be the project home." "".format(crayons.green(location)), err=True, ) - pass else: click.echo(project.project_directory) else: diff --git a/pipenv/project.py b/pipenv/project.py index e8550a04..aeb7a40f 100644 --- a/pipenv/project.py +++ b/pipenv/project.py @@ -222,7 +222,7 @@ class Project(object): @property def pipfile_exists(self): - return bool(self.pipfile_location) + return os.path.isfile(self.pipfile_location) @property def required_python_version(self): @@ -237,11 +237,7 @@ class Project(object): @property def project_directory(self): - if self.pipfile_location is not None: - return os.path.abspath(os.path.join(self.pipfile_location, os.pardir)) - - else: - return None + return os.path.abspath(os.path.join(self.pipfile_location, os.pardir)) @property def requirements_exists(self): @@ -255,8 +251,7 @@ class Project(object): @property def virtualenv_exists(self): - # TODO: Decouple project from existence of Pipfile. - if self.pipfile_exists and os.path.exists(self.virtualenv_location): + if os.path.exists(self.virtualenv_location): if os.name == "nt": extra = ["Scripts", "activate.bat"] else: @@ -470,7 +465,7 @@ class Project(object): try: loc = pipfile.Pipfile.find(max_depth=PIPENV_MAX_DEPTH) except RuntimeError: - loc = None + loc = "Pipfile" self._pipfile_location = _normalized(loc) return self._pipfile_location @@ -499,6 +494,8 @@ class Project(object): def read_pipfile(self): # Open the pipfile, read it into memory. + if not self.pipfile_exists: + return "" with io.open(self.pipfile_location) as f: contents = f.read() self._pipfile_newlines = preferred_newlines(f) @@ -659,11 +656,6 @@ class Project(object): """Returns a list of dev-packages, for pip-tools to consume.""" return self._build_package_list("dev-packages") - def touch_pipfile(self): - """Simply touches the Pipfile, for later use.""" - with open("Pipfile", "a"): - os.utime("Pipfile", None) - @property def pipfile_is_empty(self): if not self.pipfile_exists: @@ -680,7 +672,6 @@ class Project(object): ConfigOptionParser, make_option_group, index_group ) - name = self.name if self.name is not None else "Pipfile" config_parser = ConfigOptionParser(name=self.name) config_parser.add_option_group(make_option_group(index_group, config_parser)) install = config_parser.option_groups[0] @@ -834,7 +825,7 @@ class Project(object): @property def pipfile_sources(self): - if "source" not in self.parsed_pipfile: + if self.pipfile_is_empty or "source" not in self.parsed_pipfile: return [DEFAULT_SOURCE] # We need to make copies of the source info so we don't # accidentally modify the cache. See #2100 where values are From c17f36f9b2c912edecd1b1b4387d97f1d3917441 Mon Sep 17 00:00:00 2001 From: Frost Ming Date: Wed, 19 Dec 2018 11:09:05 +0800 Subject: [PATCH 2/4] make path absolute --- pipenv/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipenv/project.py b/pipenv/project.py index aeb7a40f..64ef6a29 100644 --- a/pipenv/project.py +++ b/pipenv/project.py @@ -53,7 +53,7 @@ def _normalized(p): path_str = matches and matches[0] or str(loc) else: path_str = str(loc) - return normalize_drive(path_str) + return normalize_drive(os.path.abspath(path_str)) DEFAULT_NEWLINES = u"\n" From 0efa7e9fca195352f1e011c646dcf0df3446fe0c Mon Sep 17 00:00:00 2001 From: Frost Ming Date: Wed, 19 Dec 2018 15:36:04 +0800 Subject: [PATCH 3/4] remove redundant branch --- pipenv/core.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pipenv/core.py b/pipenv/core.py index c6d76f1c..bd8c5fc1 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -624,7 +624,6 @@ def do_where(virtualenv=False, bare=True): # Shorten the virtual display of the path to the virtualenv. if not bare: location = shorten_path(location) - elif not bare: click.echo( "Pipfile found at {0}.\n Considering this to be the project home." "".format(crayons.green(location)), From 09e1d55beea4d840e62a4f633a72e17b5dfb2193 Mon Sep 17 00:00:00 2001 From: frostming Date: Mon, 1 Apr 2019 12:58:29 +0800 Subject: [PATCH 4/4] Refine the news entry --- news/3386.behavior.rst | 1 + news/3386.trivial.rst | 1 - news/3434.trivial.rst | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 news/3386.behavior.rst delete mode 100644 news/3386.trivial.rst create mode 100644 news/3434.trivial.rst diff --git a/news/3386.behavior.rst b/news/3386.behavior.rst new file mode 100644 index 00000000..8ddc27c6 --- /dev/null +++ b/news/3386.behavior.rst @@ -0,0 +1 @@ +Do not touch Pipfile early and rely on it so that one can do ``pipenv sync`` without a Pipfile. diff --git a/news/3386.trivial.rst b/news/3386.trivial.rst deleted file mode 100644 index 632b8153..00000000 --- a/news/3386.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -Decouple project from the existence of Pipfile. diff --git a/news/3434.trivial.rst b/news/3434.trivial.rst new file mode 100644 index 00000000..622b52db --- /dev/null +++ b/news/3434.trivial.rst @@ -0,0 +1 @@ +Improve the error message when one tries to initialize a Pipenv project under ``/``.