Repository: pypa/pip

Issue:
Different results between `pip list` and `python -m pip list`
**Environment**

* pip version: 19.0 or later (I didn’t test earlier versions)
* Python version: any
* OS: any

**Description**

From pipxproject/pipx#365. The result `list` would either include the package in the working directory or not, depending on how pip is invoked.

* `pip list` would not contain the package in cwd.
* `python -m pip list` would contain the package in cwd.

**Expected behavior**

The behaviour should be the same no matter how pip is invoked. Ideally the package in cwd should not be included (unless the package is also in `sys.path` other than `.`).

**How to Reproduce**

Create package metadata in cwd:

```
mkdir foo
cd foo
echo "from setuptools import setup; setup(name='foo', version='1.0.0')" > setup.py
python setup.py egg_info
```

**Output**

```
$ pip list
Package    Version
---------- -------
pip        19.0.3 
setuptools 40.8.0

$ python -m pip list
Package    Version
---------- -------
foo        1.0.0  
pip        19.0.3 
setuptools 40.8.0
```


Discussion:
From Python's official documentation for [`-m` option](https://docs.python.org/2/using/cmdline.html#cmdoption-m)
 >  As with the `-c` option, the current directory will be added to the start of sys.path

But won't this behaviour need to be changed for every command pip invokes? If we could somehow skip the package if it is present in the cwd at the start of getting packages. Then, the packages provided to each of these commands would be just those which are not present in cwd.

I am not too familiar with `pip`'s source code, I am diving into it to know more. Any kind of pointer will help.
On reading through the code, I found that all the commands that requires a list of installed distributions, calls the `get_installed_distribution` function in https://github.com/pypa/pip/blob/master/src/pip/_internal/utils/misc.py#L400, which in turn fetches the list from here https://github.com/pypa/pip/blob/master/src/pip/_vendor/pkg_resources/__init__.py#L553.

What I thought was to add a check like 
```
if entries[0] == '':
    entries.pop(0)
```
after the line https://github.com/pypa/pip/blob/master/src/pip/_vendor/pkg_resources/__init__.py#L564, ie when `entries` is assigned `sys.path`. We can remove `''` from the list of directories.

This works locally i.e. it does not consider the current directory. But I am unable to write a test for it as of now.
The resolution for this would likely look very similar to my suggestion for fixing a similar issue in `pip freeze` https://github.com/pypa/pip/pull/7810#issuecomment-599191405.
Hi @pradyunsg,

Can I take up this PR and try out the fix you mentioned in the comment above?

Resolving patch:
diff --git a/src/pip/__main__.py b/src/pip/__main__.py
--- a/src/pip/__main__.py
+++ b/src/pip/__main__.py
@@ -3,6 +3,13 @@
 import os
 import sys
 
+# Remove '' and current working directory from the first entry
+# of sys.path, if present to avoid using current directory
+# in pip commands check, freeze, install, list and show,
+# when invoked as python -m pip <command>
+if sys.path[0] in ('', os.getcwd()):
+    sys.path.pop(0)
+
 # If we are running from a wheel, add the wheel to sys.path
 # This allows the usage python pip-*.whl/pip install pip-*.whl
 if __package__ == '':


Test patch:
diff --git a/tests/functional/test_list.py b/tests/functional/test_list.py
--- a/tests/functional/test_list.py
+++ b/tests/functional/test_list.py
@@ -3,6 +3,7 @@
 
 import pytest
 
+from tests.lib import create_test_package_with_setup
 from tests.lib.path import Path
 
 
@@ -543,3 +544,44 @@ def test_list_path_multiple(tmpdir, script, data):
     json_result = json.loads(result.stdout)
     assert {'name': 'simple', 'version': '2.0'} in json_result
     assert {'name': 'simple2', 'version': '3.0'} in json_result
+
+
+def test_list_skip_work_dir_pkg(script):
+    """
+    Test that list should not include package in working directory
+    """
+
+    # Create a test package and create .egg-info dir
+    pkg_path = create_test_package_with_setup(script,
+                                              name='simple',
+                                              version='1.0')
+    script.run('python', 'setup.py', 'egg_info',
+               expect_stderr=True, cwd=pkg_path)
+
+    # List should not include package simple when run from package directory
+    result = script.pip('list', '--format=json', cwd=pkg_path)
+    json_result = json.loads(result.stdout)
+    assert {'name': 'simple', 'version': '1.0'} not in json_result
+
+
+def test_list_include_work_dir_pkg(script):
+    """
+    Test that list should include package in working directory
+    if working directory is added in sys.path
+    """
+
+    # Create a test package and create .egg-info dir
+    pkg_path = create_test_package_with_setup(script,
+                                              name='simple',
+                                              version='1.0')
+
+    script.run('python', 'setup.py', 'egg_info',
+               expect_stderr=True, cwd=pkg_path)
+
+    # Add PYTHONPATH env variable
+    script.environ.update({'PYTHONPATH': pkg_path})
+
+    # List should include package simple when run from package directory
+    result = script.pip('list', '--format=json', cwd=pkg_path)
+    json_result = json.loads(result.stdout)
+    assert {'name': 'simple', 'version': '1.0'} in json_result