We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`pip search` doesn't work in narrow terminals
- Pip version: 8.1.1 (also happens in at least 8.1.0)
- Python version: 2.7.9
- Operating System: xenial
### Description:

`pip search` can't print results to narrow terminal windows
### What I've run:

`pip search [something with results]` in a 63-column urxvt instance:

```
Exception:
Traceback (most recent call last):
  File "/home/tinruufu/.virtualenvs/tinruufu/local/lib/python2.7/site-packages/pip/basecommand.py", line 209, in main
    status = self.run(options, args)
  File "/home/tinruufu/.virtualenvs/tinruufu/local/lib/python2.7/site-packages/pip/commands/search.py", line 50, in run
    print_results(hits, terminal_width=terminal_width)
  File "/home/tinruufu/.virtualenvs/tinruufu/local/lib/python2.7/site-packages/pip/commands/search.py", line 122, in print_results
    terminal_width - name_column_width - 5,
  File "/usr/lib/python2.7/textwrap.py", line 354, in wrap
    return w.wrap(text)
  File "/usr/lib/python2.7/textwrap.py", line 329, in wrap
    return self._wrap_chunks(chunks)
  File "/usr/lib/python2.7/textwrap.py", line 258, in _wrap_chunks
    raise ValueError("invalid width %r (must be > 0)" % self.width)
ValueError: invalid width -14 (must be > 0)
```

```
$ tput cols
63
```

as an aside, it's a bummer that the download progress bars don't get narrow in such windows and instead vomits hundreds of lines of rectangles; `progressbar` handles this fine. this is the first time i've found something that just straight-up doesn't work at all though


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pip/commands/search.py`
Content:
```
1 from __future__ import absolute_import
2 
3 import logging
4 import sys
5 import textwrap
6 
7 from pip.basecommand import Command, SUCCESS
8 from pip.download import PipXmlrpcTransport
9 from pip.models import PyPI
10 from pip.utils import get_terminal_size
11 from pip.utils.logging import indent_log
12 from pip.exceptions import CommandError
13 from pip.status_codes import NO_MATCHES_FOUND
14 from pip._vendor import pkg_resources
15 from pip._vendor.six.moves import xmlrpc_client
16 
17 
18 logger = logging.getLogger(__name__)
19 
20 
21 class SearchCommand(Command):
22     """Search for PyPI packages whose name or summary contains <query>."""
23     name = 'search'
24     usage = """
25       %prog [options] <query>"""
26     summary = 'Search PyPI for packages.'
27 
28     def __init__(self, *args, **kw):
29         super(SearchCommand, self).__init__(*args, **kw)
30         self.cmd_opts.add_option(
31             '--index',
32             dest='index',
33             metavar='URL',
34             default=PyPI.pypi_url,
35             help='Base URL of Python Package Index (default %default)')
36 
37         self.parser.insert_option_group(0, self.cmd_opts)
38 
39     def run(self, options, args):
40         if not args:
41             raise CommandError('Missing required argument (search query).')
42         query = args
43         pypi_hits = self.search(query, options)
44         hits = transform_hits(pypi_hits)
45 
46         terminal_width = None
47         if sys.stdout.isatty():
48             terminal_width = get_terminal_size()[0]
49 
50         print_results(hits, terminal_width=terminal_width)
51         if pypi_hits:
52             return SUCCESS
53         return NO_MATCHES_FOUND
54 
55     def search(self, query, options):
56         index_url = options.index
57         with self._build_session(options) as session:
58             transport = PipXmlrpcTransport(index_url, session)
59             pypi = xmlrpc_client.ServerProxy(index_url, transport)
60             hits = pypi.search({'name': query, 'summary': query}, 'or')
61             return hits
62 
63 
64 def transform_hits(hits):
65     """
66     The list from pypi is really a list of versions. We want a list of
67     packages with the list of versions stored inline. This converts the
68     list from pypi into one we can use.
69     """
70     packages = {}
71     for hit in hits:
72         name = hit['name']
73         summary = hit['summary']
74         version = hit['version']
75         score = hit['_pypi_ordering']
76         if score is None:
77             score = 0
78 
79         if name not in packages.keys():
80             packages[name] = {
81                 'name': name,
82                 'summary': summary,
83                 'versions': [version],
84                 'score': score,
85             }
86         else:
87             packages[name]['versions'].append(version)
88 
89             # if this is the highest version, replace summary and score
90             if version == highest_version(packages[name]['versions']):
91                 packages[name]['summary'] = summary
92                 packages[name]['score'] = score
93 
94     # each record has a unique name now, so we will convert the dict into a
95     # list sorted by score
96     package_list = sorted(
97         packages.values(),
98         key=lambda x: x['score'],
99         reverse=True,
100     )
101     return package_list
102 
103 
104 def print_results(hits, name_column_width=None, terminal_width=None):
105     if not hits:
106         return
107     if name_column_width is None:
108         name_column_width = max([
109             len(hit['name']) + len(hit.get('versions', ['-'])[-1])
110             for hit in hits
111         ]) + 4
112 
113     installed_packages = [p.project_name for p in pkg_resources.working_set]
114     for hit in hits:
115         name = hit['name']
116         summary = hit['summary'] or ''
117         version = hit.get('versions', ['-'])[-1]
118         if terminal_width is not None:
119             # wrap and indent summary to fit terminal
120             summary = textwrap.wrap(
121                 summary,
122                 terminal_width - name_column_width - 5,
123             )
124             summary = ('\n' + ' ' * (name_column_width + 3)).join(summary)
125 
126         line = '%-*s - %s' % (name_column_width,
127                               '%s (%s)' % (name, version), summary)
128         try:
129             logger.info(line)
130             if name in installed_packages:
131                 dist = pkg_resources.get_distribution(name)
132                 with indent_log():
133                     latest = highest_version(hit['versions'])
134                     if dist.version == latest:
135                         logger.info('INSTALLED: %s (latest)', dist.version)
136                     else:
137                         logger.info('INSTALLED: %s', dist.version)
138                         logger.info('LATEST:    %s', latest)
139         except UnicodeEncodeError:
140             pass
141 
142 
143 def highest_version(versions):
144     return next(iter(
145         sorted(versions, key=pkg_resources.parse_version, reverse=True)
146     ))
147
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pip/commands/search.py b/pip/commands/search.py
--- a/pip/commands/search.py
+++ b/pip/commands/search.py
@@ -116,12 +116,11 @@
         summary = hit['summary'] or ''
         version = hit.get('versions', ['-'])[-1]
         if terminal_width is not None:
-            # wrap and indent summary to fit terminal
-            summary = textwrap.wrap(
-                summary,
-                terminal_width - name_column_width - 5,
-            )
-            summary = ('\n' + ' ' * (name_column_width + 3)).join(summary)
+            target_width = terminal_width - name_column_width - 5
+            if target_width > 10:
+                # wrap and indent summary to fit terminal
+                summary = textwrap.wrap(summary, target_width)
+                summary = ('\n' + ' ' * (name_column_width + 3)).join(summary)
 
         line = '%-*s - %s' % (name_column_width,
                               '%s (%s)' % (name, version), summary)

{"golden_diff": "diff --git a/pip/commands/search.py b/pip/commands/search.py\n--- a/pip/commands/search.py\n+++ b/pip/commands/search.py\n@@ -116,12 +116,11 @@\n         summary = hit['summary'] or ''\n         version = hit.get('versions', ['-'])[-1]\n         if terminal_width is not None:\n-            # wrap and indent summary to fit terminal\n-            summary = textwrap.wrap(\n-                summary,\n-                terminal_width - name_column_width - 5,\n-            )\n-            summary = ('\\n' + ' ' * (name_column_width + 3)).join(summary)\n+            target_width = terminal_width - name_column_width - 5\n+            if target_width > 10:\n+                # wrap and indent summary to fit terminal\n+                summary = textwrap.wrap(summary, target_width)\n+                summary = ('\\n' + ' ' * (name_column_width + 3)).join(summary)\n \n         line = '%-*s - %s' % (name_column_width,\n                               '%s (%s)' % (name, version), summary)\n", "issue": "`pip search` doesn't work in narrow terminals\n- Pip version: 8.1.1 (also happens in at least 8.1.0)\n- Python version: 2.7.9\n- Operating System: xenial\n### Description:\n\n`pip search` can't print results to narrow terminal windows\n### What I've run:\n\n`pip search [something with results]` in a 63-column urxvt instance:\n\n```\nException:\nTraceback (most recent call last):\n  File \"/home/tinruufu/.virtualenvs/tinruufu/local/lib/python2.7/site-packages/pip/basecommand.py\", line 209, in main\n    status = self.run(options, args)\n  File \"/home/tinruufu/.virtualenvs/tinruufu/local/lib/python2.7/site-packages/pip/commands/search.py\", line 50, in run\n    print_results(hits, terminal_width=terminal_width)\n  File \"/home/tinruufu/.virtualenvs/tinruufu/local/lib/python2.7/site-packages/pip/commands/search.py\", line 122, in print_results\n    terminal_width - name_column_width - 5,\n  File \"/usr/lib/python2.7/textwrap.py\", line 354, in wrap\n    return w.wrap(text)\n  File \"/usr/lib/python2.7/textwrap.py\", line 329, in wrap\n    return self._wrap_chunks(chunks)\n  File \"/usr/lib/python2.7/textwrap.py\", line 258, in _wrap_chunks\n    raise ValueError(\"invalid width %r (must be > 0)\" % self.width)\nValueError: invalid width -14 (must be > 0)\n```\n\n```\n$ tput cols\n63\n```\n\nas an aside, it's a bummer that the download progress bars don't get narrow in such windows and instead vomits hundreds of lines of rectangles; `progressbar` handles this fine. this is the first time i've found something that just straight-up doesn't work at all though\n\n", "before_files": [{"content": "from __future__ import absolute_import\n\nimport logging\nimport sys\nimport textwrap\n\nfrom pip.basecommand import Command, SUCCESS\nfrom pip.download import PipXmlrpcTransport\nfrom pip.models import PyPI\nfrom pip.utils import get_terminal_size\nfrom pip.utils.logging import indent_log\nfrom pip.exceptions import CommandError\nfrom pip.status_codes import NO_MATCHES_FOUND\nfrom pip._vendor import pkg_resources\nfrom pip._vendor.six.moves import xmlrpc_client\n\n\nlogger = logging.getLogger(__name__)\n\n\nclass SearchCommand(Command):\n    \"\"\"Search for PyPI packages whose name or summary contains <query>.\"\"\"\n    name = 'search'\n    usage = \"\"\"\n      %prog [options] <query>\"\"\"\n    summary = 'Search PyPI for packages.'\n\n    def __init__(self, *args, **kw):\n        super(SearchCommand, self).__init__(*args, **kw)\n        self.cmd_opts.add_option(\n            '--index',\n            dest='index',\n            metavar='URL',\n            default=PyPI.pypi_url,\n            help='Base URL of Python Package Index (default %default)')\n\n        self.parser.insert_option_group(0, self.cmd_opts)\n\n    def run(self, options, args):\n        if not args:\n            raise CommandError('Missing required argument (search query).')\n        query = args\n        pypi_hits = self.search(query, options)\n        hits = transform_hits(pypi_hits)\n\n        terminal_width = None\n        if sys.stdout.isatty():\n            terminal_width = get_terminal_size()[0]\n\n        print_results(hits, terminal_width=terminal_width)\n        if pypi_hits:\n            return SUCCESS\n        return NO_MATCHES_FOUND\n\n    def search(self, query, options):\n        index_url = options.index\n        with self._build_session(options) as session:\n            transport = PipXmlrpcTransport(index_url, session)\n            pypi = xmlrpc_client.ServerProxy(index_url, transport)\n            hits = pypi.search({'name': query, 'summary': query}, 'or')\n            return hits\n\n\ndef transform_hits(hits):\n    \"\"\"\n    The list from pypi is really a list of versions. We want a list of\n    packages with the list of versions stored inline. This converts the\n    list from pypi into one we can use.\n    \"\"\"\n    packages = {}\n    for hit in hits:\n        name = hit['name']\n        summary = hit['summary']\n        version = hit['version']\n        score = hit['_pypi_ordering']\n        if score is None:\n            score = 0\n\n        if name not in packages.keys():\n            packages[name] = {\n                'name': name,\n                'summary': summary,\n                'versions': [version],\n                'score': score,\n            }\n        else:\n            packages[name]['versions'].append(version)\n\n            # if this is the highest version, replace summary and score\n            if version == highest_version(packages[name]['versions']):\n                packages[name]['summary'] = summary\n                packages[name]['score'] = score\n\n    # each record has a unique name now, so we will convert the dict into a\n    # list sorted by score\n    package_list = sorted(\n        packages.values(),\n        key=lambda x: x['score'],\n        reverse=True,\n    )\n    return package_list\n\n\ndef print_results(hits, name_column_width=None, terminal_width=None):\n    if not hits:\n        return\n    if name_column_width is None:\n        name_column_width = max([\n            len(hit['name']) + len(hit.get('versions', ['-'])[-1])\n            for hit in hits\n        ]) + 4\n\n    installed_packages = [p.project_name for p in pkg_resources.working_set]\n    for hit in hits:\n        name = hit['name']\n        summary = hit['summary'] or ''\n        version = hit.get('versions', ['-'])[-1]\n        if terminal_width is not None:\n            # wrap and indent summary to fit terminal\n            summary = textwrap.wrap(\n                summary,\n                terminal_width - name_column_width - 5,\n            )\n            summary = ('\\n' + ' ' * (name_column_width + 3)).join(summary)\n\n        line = '%-*s - %s' % (name_column_width,\n                              '%s (%s)' % (name, version), summary)\n        try:\n            logger.info(line)\n            if name in installed_packages:\n                dist = pkg_resources.get_distribution(name)\n                with indent_log():\n                    latest = highest_version(hit['versions'])\n                    if dist.version == latest:\n                        logger.info('INSTALLED: %s (latest)', dist.version)\n                    else:\n                        logger.info('INSTALLED: %s', dist.version)\n                        logger.info('LATEST:    %s', latest)\n        except UnicodeEncodeError:\n            pass\n\n\ndef highest_version(versions):\n    return next(iter(\n        sorted(versions, key=pkg_resources.parse_version, reverse=True)\n    ))\n", "path": "pip/commands/search.py"}], "after_files": [{"content": "from __future__ import absolute_import\n\nimport logging\nimport sys\nimport textwrap\n\nfrom pip.basecommand import Command, SUCCESS\nfrom pip.download import PipXmlrpcTransport\nfrom pip.models import PyPI\nfrom pip.utils import get_terminal_size\nfrom pip.utils.logging import indent_log\nfrom pip.exceptions import CommandError\nfrom pip.status_codes import NO_MATCHES_FOUND\nfrom pip._vendor import pkg_resources\nfrom pip._vendor.six.moves import xmlrpc_client\n\n\nlogger = logging.getLogger(__name__)\n\n\nclass SearchCommand(Command):\n    \"\"\"Search for PyPI packages whose name or summary contains <query>.\"\"\"\n    name = 'search'\n    usage = \"\"\"\n      %prog [options] <query>\"\"\"\n    summary = 'Search PyPI for packages.'\n\n    def __init__(self, *args, **kw):\n        super(SearchCommand, self).__init__(*args, **kw)\n        self.cmd_opts.add_option(\n            '--index',\n            dest='index',\n            metavar='URL',\n            default=PyPI.pypi_url,\n            help='Base URL of Python Package Index (default %default)')\n\n        self.parser.insert_option_group(0, self.cmd_opts)\n\n    def run(self, options, args):\n        if not args:\n            raise CommandError('Missing required argument (search query).')\n        query = args\n        pypi_hits = self.search(query, options)\n        hits = transform_hits(pypi_hits)\n\n        terminal_width = None\n        if sys.stdout.isatty():\n            terminal_width = get_terminal_size()[0]\n\n        print_results(hits, terminal_width=terminal_width)\n        if pypi_hits:\n            return SUCCESS\n        return NO_MATCHES_FOUND\n\n    def search(self, query, options):\n        index_url = options.index\n        with self._build_session(options) as session:\n            transport = PipXmlrpcTransport(index_url, session)\n            pypi = xmlrpc_client.ServerProxy(index_url, transport)\n            hits = pypi.search({'name': query, 'summary': query}, 'or')\n            return hits\n\n\ndef transform_hits(hits):\n    \"\"\"\n    The list from pypi is really a list of versions. We want a list of\n    packages with the list of versions stored inline. This converts the\n    list from pypi into one we can use.\n    \"\"\"\n    packages = {}\n    for hit in hits:\n        name = hit['name']\n        summary = hit['summary']\n        version = hit['version']\n        score = hit['_pypi_ordering']\n        if score is None:\n            score = 0\n\n        if name not in packages.keys():\n            packages[name] = {\n                'name': name,\n                'summary': summary,\n                'versions': [version],\n                'score': score,\n            }\n        else:\n            packages[name]['versions'].append(version)\n\n            # if this is the highest version, replace summary and score\n            if version == highest_version(packages[name]['versions']):\n                packages[name]['summary'] = summary\n                packages[name]['score'] = score\n\n    # each record has a unique name now, so we will convert the dict into a\n    # list sorted by score\n    package_list = sorted(\n        packages.values(),\n        key=lambda x: x['score'],\n        reverse=True,\n    )\n    return package_list\n\n\ndef print_results(hits, name_column_width=None, terminal_width=None):\n    if not hits:\n        return\n    if name_column_width is None:\n        name_column_width = max([\n            len(hit['name']) + len(hit.get('versions', ['-'])[-1])\n            for hit in hits\n        ]) + 4\n\n    installed_packages = [p.project_name for p in pkg_resources.working_set]\n    for hit in hits:\n        name = hit['name']\n        summary = hit['summary'] or ''\n        version = hit.get('versions', ['-'])[-1]\n        if terminal_width is not None:\n            target_width = terminal_width - name_column_width - 5\n            if target_width > 10:\n                # wrap and indent summary to fit terminal\n                summary = textwrap.wrap(summary, target_width)\n                summary = ('\\n' + ' ' * (name_column_width + 3)).join(summary)\n\n        line = '%-*s - %s' % (name_column_width,\n                              '%s (%s)' % (name, version), summary)\n        try:\n            logger.info(line)\n            if name in installed_packages:\n                dist = pkg_resources.get_distribution(name)\n                with indent_log():\n                    latest = highest_version(hit['versions'])\n                    if dist.version == latest:\n                        logger.info('INSTALLED: %s (latest)', dist.version)\n                    else:\n                        logger.info('INSTALLED: %s', dist.version)\n                        logger.info('LATEST:    %s', latest)\n        except UnicodeEncodeError:\n            pass\n\n\ndef highest_version(versions):\n    return next(iter(\n        sorted(versions, key=pkg_resources.parse_version, reverse=True)\n    ))\n", "path": "pip/commands/search.py"}]}