Repository: pypa/pipenv

Issue:
pipenv clean is not working
Be sure to check the existing issues (both open and closed!), and make sure you are running the latest version of Pipenv.

Check the [diagnose documentation](https://docs.pipenv.org/diagnose/) for common issues before posting! We may close your issue if it is very similar to one of them. Please be considerate, or be on your way.

Make sure to mention your debugging experience if the documented solution failed.


### Issue description

Run pipenv clean on a project with deps not specified in Pipfile.lock, nothing happens

### Expected result

The dependencies should be removed from virtualenv

### Actual result

Nothing happens

### Steps to replicate

Provide the steps to replicate (which usually at least includes the commands and the Pipfile).

```
$ pipenv install requests
$ pipenv run pip install flake8    # flake8 is not included in Pipfile
$ pipenv clean
# No output
$ pipenv graph
flake8==3.6.0
  - mccabe [required: >=0.6.0,<0.7.0, installed: 0.6.1]
  - pycodestyle [required: >=2.4.0,<2.5.0, installed: 2.4.0]
  - pyflakes [required: >=2.0.0,<2.1.0, installed: 2.0.0]
  - setuptools [required: >=30, installed: 40.4.3]
requests==2.20.0
  - certifi [required: >=2017.4.17, installed: 2018.10.15]
  - chardet [required: >=3.0.2,<3.1.0, installed: 3.0.4]
  - idna [required: >=2.5,<2.8, installed: 2.7]
  - urllib3 [required: >=1.21.1,<1.25, installed: 1.24]
```

-------------------------------------------------------------------------------

Please run `$ pipenv --support`, and paste the results here. Don't put backticks (`` ` ``) around it! The output already contains Markdown formatting.

If you're on macOS, run the following:

    $ pipenv --support | pbcopy

If you're on Windows, run the following:

    > pipenv --support | clip

If you're on Linux, run the following:

    $ pipenv --support | xclip

<details><summary>$ pipenv --support</summary>

Pipenv version: `'2018.10.13'`

Pipenv location: `'c:\\users\\frostming\\.local\\venvs\\pipenv\\lib\\site-packages\\pipenv'`

Python location: `'c:\\users\\frostming\\.local\\venvs\\pipenv\\scripts\\python.exe'`

Python installations found:

  - `3.7.0`: `D:\Programs\Python\Python37-32\python.exe`
  - `2.7`: `D:\Programs\Python\Python27\python.exe`

PEP 508 Information:

```
{'implementation_name': 'cpython',
 'implementation_version': '3.7.0',
 'os_name': 'nt',
 'platform_machine': 'AMD64',
 'platform_python_implementation': 'CPython',
 'platform_release': '10',
 'platform_system': 'Windows',
 'platform_version': '10.0.15063',
 'python_full_version': '3.7.0',
 'python_version': '3.7',
 'sys_platform': 'win32'}
```

System environment variables:

  - `ALLUSERSPROFILE`
  - `APPDATA`
  - `COMMONPROGRAMFILES`
  - `COMMONPROGRAMFILES(X86)`
  - `COMMONPROGRAMW6432`
  - `COMPUTERNAME`
  - `COMSPEC`
  - `HOMEDRIVE`
  - `HOMEPATH`
  - `HTTPS_PROXY`
  - `JAVA_HOME`
  - `LOCALAPPDATA`
  - `LOGONSERVER`
  - `NUMBER_OF_PROCESSORS`
  - `ONEDRIVE`
  - `OS`
  - `PATH`
  - `PATHEXT`
  - `PROCESSOR_ARCHITECTURE`
  - `PROCESSOR_ARCHITEW6432`
  - `PROCESSOR_IDENTIFIER`
  - `PROCESSOR_LEVEL`
  - `PROCESSOR_REVISION`
  - `PROGRAMDATA`
  - `PROGRAMFILES`
  - `PROGRAMFILES(X86)`
  - `PROGRAMW6432`
  - `PROMPT`
  - `PSMODULEPATH`
  - `PUBLIC`
  - `SESSIONNAME`
  - `SYSTEMDRIVE`
  - `SYSTEMROOT`
  - `TEMP`
  - `TMP`
  - `USERDNSDOMAIN`
  - `USERDOMAIN`
  - `USERDOMAIN_ROAMINGPROFILE`
  - `USERNAME`
  - `USERPROFILE`
  - `WINDIR`
  - `LANG`
  - `TERM`
  - `COLORTERM`
  - `TERM_PROGRAM`
  - `TERM_PROGRAM_VERSION`
  - `PYTHONDONTWRITEBYTECODE`
  - `PIP_SHIMS_BASE_MODULE`
  - `PIP_PYTHON_PATH`

Pipenv–specific environment variables:


Debug–specific environment variables:

  - `PATH`: `C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;D:\Programs\Git\cmd;D:\Programs\TortoiseSVN\bin;D:\Programs\Gpg4win\..\GnuPG\bin;D:\Programs\nodejs\;D:\Programs\Python\Python37-32\Scripts\;D:\Programs\Python\Python37-32\;C:\Users\frostming\AppData\Local\Microsoft\WindowsApps;C:\Users\frostming\.local\bin;D:\Programs\Microsoft VS Code\bin;C:\Users\frostming\AppData\Roaming\npm;C:\Users\frostming\AppData\Local\Yarn\bin;D:\Programs\GnuWin32\bin;D:\Programs\heroku\bin;C:\Users\frostming\AppData\Local\hyper\app-2.0.0\resources\bin;D:\Programs\Java\apache-maven-3.2.5\bin;`
  - `LANG`: `zh_CN.UTF-8`


---------------------------

Contents of `Pipfile` ('D:\\Workspace\\tempenv\\Pipfile'):

```toml
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
requests = "*"

[dev-packages]

```


Contents of `Pipfile.lock` ('D:\\Workspace\\tempenv\\Pipfile.lock'):

```json
{
    "_meta": {
        "hash": {
            "sha256": "70e8bf6bc774f5ca177467cab4e67d4264d0536857993326abc13ff43063bec0"
        },
        "pipfile-spec": 6,
        "requires": {},
        "sources": [
            {
                "name": "pypi",
                "url": "https://pypi.org/simple",
                "verify_ssl": true
            }
        ]
    },
    "default": {
        "certifi": {
            "hashes": [
                "sha256:339dc09518b07e2fa7eda5450740925974815557727d6bd35d319c1524a04a4c",
                "sha256:6d58c986d22b038c8c0df30d639f23a3e6d172a05c3583e766f4c0b785c0986a"
            ],
            "version": "==2018.10.15"
        },
        "chardet": {
            "hashes": [
                "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
                "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
            ],
            "version": "==3.0.4"
        },
        "idna": {
            "hashes": [
                "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e",
                "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16"
            ],
            "version": "==2.7"
        },
        "requests": {
            "hashes": [
                "sha256:99dcfdaaeb17caf6e526f32b6a7b780461512ab3f1d992187801694cba42770c",
                "sha256:a84b8c9ab6239b578f22d1c21d51b696dcfe004032bb80ea832398d6909d7279"
            ],
            "index": "pypi",
            "version": "==2.20.0"
        },
        "urllib3": {
            "hashes": [
                "sha256:41c3db2fc01e5b907288010dec72f9d0a74e37d6994e6eb56849f59fea2265ae",
                "sha256:8819bba37a02d143296a4d032373c4dd4aca11f6d4c9973335ca75f9c8475f59"
            ],
            "version": "==1.24"
        }
    },
    "develop": {}
}

```
</details>



Discussion:
No sure if it is only me that has this issue, I will go deep into the source code later today.
It's related to Windows path normalization.

Can we convert the path all lowercased for Windows? Any concern?

Resolving patch:
diff --git a/pipenv/project.py b/pipenv/project.py
--- a/pipenv/project.py
+++ b/pipenv/project.py
@@ -4,6 +4,7 @@
 import os
 import re
 import sys
+import glob
 import base64
 import itertools
 import fnmatch
@@ -53,14 +54,18 @@ def _normalized(p):
     if p is None:
         return None
     loc = vistir.compat.Path(p)
-    if loc.is_absolute():
-        return normalize_drive(str(loc))
-    else:
+    if not loc.is_absolute():
         try:
             loc = loc.resolve()
         except OSError:
             loc = loc.absolute()
-        return normalize_drive(str(loc))
+    # Recase the path properly on Windows. From https://stackoverflow.com/a/35229734/5043728
+    if os.name == 'nt':
+        matches = glob.glob(re.sub(r'([^:/\\])(?=[/\\]|$)', r'[\1]', str(loc)))
+        path_str = matches and matches[0] or str(loc)
+    else:
+        path_str = str(loc)
+    return normalize_drive(path_str)
 
 
 DEFAULT_NEWLINES = u"\n"


Test patch:
diff --git a/tests/integration/test_windows.py b/tests/integration/test_windows.py
--- a/tests/integration/test_windows.py
+++ b/tests/integration/test_windows.py
@@ -65,3 +65,16 @@ def test_local_path_windows_forward_slash(PipenvInstance, pypi):
     with PipenvInstance(pypi=pypi, chdir=True) as p:
         c = p.pipenv('install "{0}"'.format(whl.as_posix()))
         assert c.return_code == 0
+
+
+@pytest.mark.cli
+def test_pipenv_clean_windows(PipenvInstance, pypi):
+    with PipenvInstance(pypi=pypi, chdir=True) as p:
+        c = p.pipenv('install requests')
+        assert c.return_code == 0
+        c = p.pipenv('run pip install click')
+        assert c.return_code == 0
+
+        c = p.pipenv('clean --dry-run')
+        assert c.return_code == 0
+        assert 'click' in c.out.strip()