Repository: pypa/pipenv

Issue:
pipenv graph is blank
I'm using pipenv at commit e41c0659 (I need recent bugfixes), and the `pipenv graph` command seems to output nothing.

<details><summary>$ python -m pipenv.help output</summary>

Pipenv version: `'2018.05.18'`

Pipenv location: `'/home/user/.local/lib/python2.7/site-packages/pipenv'`

Python location: `'/usr/bin/python'`

Other Python installations in `PATH`:

  - `2.7`: `/usr/bin/python2.7`
  - `2.7`: `/usr/bin/python2.7`
  - `3.6`: `/usr/bin/python3.6m`
  - `3.6`: `/usr/bin/python3.6`

  - `2.7.15`: `/usr/bin/python`
  - `2.7.15`: `/usr/bin/python2`
  - `3.6.5`: `/usr/bin/python3`

PEP 508 Information:

```
{'implementation_name': 'cpython',
 'implementation_version': '0',
 'os_name': 'posix',
 'platform_machine': 'x86_64',
 'platform_python_implementation': 'CPython',
 'platform_release': '4.15.17-300.fc27.x86_64',
 'platform_system': 'Linux',
 'platform_version': '#1 SMP Thu Apr 12 18:19:17 UTC 2018',
 'python_full_version': '2.7.15',
 'python_version': '2.7',
 'sys_platform': 'linux2'}
```

System environment variables:

  - `PYTHONDONTWRITEBYTECODE`
  - `PIP_PYTHON_PATH`

Pipenv–specific environment variables:


Debug–specific environment variables:

  - `PATH`: `/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/home/user/.local/bin:/home/user/bin`
  - `SHELL`: `/bin/bash`
  - `LANG`: `en_US.UTF-8`
  - `PWD`: `/home/user/project`


---------------------------

Contents of `Pipfile` ('/home/user/project/Pipfile'):

```toml
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[dev-packages]

[packages]
requests = "*"

[requires]
python_version = "2.7"

```


Contents of `Pipfile.lock` ('/home/user/project/Pipfile.lock'):

```json
{
    "_meta": {
        "hash": {
            "sha256": "9838c8bf3aa442453b393e09e534ba7e1666aab4da1b9b408ecdf3ae58ab273c"
        },
        "pipfile-spec": 6,
        "requires": {
            "python_version": "2.7"
        },
        "sources": [
            {
                "name": "pypi",
                "url": "https://pypi.org/simple",
                "verify_ssl": true
            }
        ]
    },
    "default": {
        "certifi": {
            "hashes": [
                "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7",
                "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0"
            ],
            "version": "==2018.4.16"
        },
        "chardet": {
            "hashes": [
                "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
                "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
            ],
            "version": "==3.0.4"
        },
        "idna": {
            "hashes": [
                "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f",
                "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4"
            ],
            "version": "==2.6"
        },
        "requests": {
            "hashes": [
                "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b",
                "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e"
            ],
            "index": "pypi",
            "version": "==2.18.4"
        },
        "urllib3": {
            "hashes": [
                "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b",
                "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f"
            ],
            "version": "==1.22"
        }
    },
    "develop": {}
}

```
</details>


------------

##### Expected result

a dependency graph

##### Actual result

a newline or two

##### Steps to replicate

```
@lbenezriravin:~/project $ pipenv install requests > /dev/null 2>&1; pipenv graph

@lbenezriravin:~/project $ 
```

Thanks for everything you all do here! I'm extremely happy that this project exists and that maintainers are so active!


Discussion:
Can confirm. I did some bisecting and it seems this was introduced during pip upgrade, between 46a0e79 and 81ae262. /cc @techalchemy 

Resolving patch:
diff --git a/pipenv/core.py b/pipenv/core.py
--- a/pipenv/core.py
+++ b/pipenv/core.py
@@ -2510,6 +2510,14 @@ def traverse(obj):
                     click.echo(crayons.normal(line, bold=False))
     else:
         click.echo(c.out)
+    if c.return_code != 0:
+        click.echo(
+            '{0} {1}'.format(
+                crayons.red('ERROR: ', bold=True),
+                crayons.white('{0}'.format(c.err, bold=True)),
+            ),
+            err=True
+        )
     # Return its return code.
     sys.exit(c.return_code)
 
diff --git a/pipenv/vendor/pipdeptree.py b/pipenv/vendor/pipdeptree.py
--- a/pipenv/vendor/pipdeptree.py
+++ b/pipenv/vendor/pipdeptree.py
@@ -14,10 +14,10 @@
     from ordereddict import OrderedDict
 
 try:
-    from pipenv.patched.notpip._internal import get_installed_distributions
-    from pipenv.patched.notpip._internal.operations.freeze import FrozenRequirement
+    from pip._internal import get_installed_distributions
+    from pip._internal.operations.freeze import FrozenRequirement
 except ImportError:
-    from pipenv.patched.notpip import get_installed_distributions, FrozenRequirement
+    from pip import get_installed_distributions, FrozenRequirement
 
 import pkg_resources
 # inline:
@@ -237,7 +237,7 @@ def __init__(self, obj, dist=None):
 
     @property
     def version_spec(self):
-        specs = self._obj.specs
+        specs = sorted(self._obj.specs, reverse=True)  # `reverse` makes '>' prior to '<'
         return ','.join([''.join(sp) for sp in specs]) if specs else None
 
     @property
@@ -280,8 +280,8 @@ def as_dict(self):
                 'required_version': self.version_spec}
 
 
-def render_tree(tree, list_all=True, show_only=None, frozen=False):
-    """Convert to tree to string representation
+def render_tree(tree, list_all=True, show_only=None, frozen=False, exclude=None):
+    """Convert tree to string representation
 
     :param dict tree: the package tree
     :param bool list_all: whether to list all the pgks at the root
@@ -291,6 +291,8 @@ def render_tree(tree, list_all=True, show_only=None, frozen=False):
                           output. This is optional arg, default: None.
     :param bool frozen: whether or not show the names of the pkgs in
                         the output that's favourable to pip --freeze
+    :param set exclude: set of select packages to be excluded from the
+                          output. This is optional arg, default: None.
     :returns: string representation of the tree
     :rtype: str
 
@@ -310,6 +312,8 @@ def render_tree(tree, list_all=True, show_only=None, frozen=False):
         nodes = [p for p in nodes if p.key not in branch_keys]
 
     def aux(node, parent=None, indent=0, chain=None):
+        if exclude and (node.key in exclude or node.project_name in exclude):
+            return []
         if chain is None:
             chain = [node.project_name]
         node_str = node.render(parent, frozen)
@@ -527,6 +531,11 @@ def get_parser():
                             'Comma separated list of select packages to show '
                             'in the output. If set, --all will be ignored.'
                         ))
+    parser.add_argument('-e', '--exclude',
+                        help=(
+                            'Comma separated list of select packages to exclude '
+                            'from the output. If set, --all will be ignored.'
+                        ), metavar='PACKAGES')
     parser.add_argument('-j', '--json', action='store_true', default=False,
                         help=(
                             'Display dependency tree as json. This will yield '
@@ -548,10 +557,13 @@ def get_parser():
     return parser
 
 
-def main():
+def _get_args():
     parser = get_parser()
-    args = parser.parse_args()
+    return parser.parse_args()
+
 
+def main():
+    args = _get_args()
     pkgs = get_installed_distributions(local_only=args.local_only,
                                            user_only=args.user_only)
 
@@ -600,10 +612,15 @@ def main():
             return_code = 1
 
     show_only = set(args.packages.split(',')) if args.packages else None
+    exclude = set(args.exclude.split(',')) if args.exclude else None
+
+    if show_only and exclude and (show_only & exclude):
+        print('Conflicting packages found in --packages and --exclude lists.', file=sys.stderr)
+        sys.exit(1)
 
     tree = render_tree(tree if not args.reverse else reverse_tree(tree),
                        list_all=args.all, show_only=show_only,
-                       frozen=args.freeze)
+                       frozen=args.freeze, exclude=exclude)
     print(tree)
     return return_code
 


Test patch: