We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
VIMPAGER error
I realize that it is a bit of an aside, but it would be great to support alternative pagers.

```
~ $ echo $MANPAGER
/bin/sh -c "col -bx | vim -c 'set ft=man' -"
~ $ python --version                                                                                                                    1
Python 2.7.5
~ $ pip --version
pip 1.4.1 from /Users/carl/.virtualenv/lib/python2.7/site-packages (python 2.7)
~ $ aws --version
aws-cli/1.1.0 Python/2.7.5 Darwin/12.5.0
~ $ aws help
-bx: -c: line 0: unexpected EOF while looking for matching `"'
-bx: -c: line 1: syntax error: unexpected end of file
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `awscli/help.py`
Content:
```
1 # Copyright 2012-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"). You
4 # may not use this file except in compliance with the License. A copy of
5 # the License is located at
6 #
7 #     http://aws.amazon.com/apache2.0/
8 #
9 # or in the "license" file accompanying this file. This file is
10 # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11 # ANY KIND, either express or implied. See the License for the specific
12 # language governing permissions and limitations under the License.
13 import sys
14 import logging
15 import os
16 import platform
17 from subprocess import Popen, PIPE
18 
19 from docutils.core import publish_string
20 from docutils.writers import manpage
21 import bcdoc
22 from bcdoc.clidocs import ReSTDocument
23 from bcdoc.clidocs import ProviderDocumentEventHandler
24 from bcdoc.clidocs import ServiceDocumentEventHandler
25 from bcdoc.clidocs import OperationDocumentEventHandler
26 import bcdoc.clidocevents
27 from bcdoc.textwriter import TextWriter
28 
29 from awscli.argprocess import ParamShorthand
30 
31 
32 LOG = logging.getLogger('awscli.help')
33 
34 
35 class ExecutableNotFoundError(Exception):
36     def __init__(self, executable_name):
37         super(ExecutableNotFoundError, self).__init__(
38             'Could not find executable named "%s"' % executable_name)
39 
40 
41 def get_renderer():
42     """
43     Return the appropriate HelpRenderer implementation for the
44     current platform.
45     """
46     if platform.system() == 'Windows':
47         return WindowsHelpRenderer()
48     else:
49         return PosixHelpRenderer()
50 
51 
52 class HelpRenderer(object):
53     """
54     Interface for a help renderer.
55 
56     The renderer is responsible for displaying the help content on
57     a particular platform.
58     """
59 
60     def render(self, contents):
61         """
62         Each implementation of HelpRenderer must implement this
63         render method.
64         """
65         pass
66 
67 
68 class PosixHelpRenderer(HelpRenderer):
69     """
70     Render help content on a Posix-like system.  This includes
71     Linux and MacOS X.
72     """
73 
74     PAGER = 'less -R'
75 
76     def get_pager_cmdline(self):
77         pager = self.PAGER
78         if 'MANPAGER' in os.environ:
79             pager = os.environ['MANPAGER']
80         elif 'PAGER' in os.environ:
81             pager = os.environ['PAGER']
82         return pager.split()
83 
84     def render(self, contents):
85         man_contents = publish_string(contents, writer=manpage.Writer())
86         if not self._exists_on_path('groff'):
87             raise ExecutableNotFoundError('groff')
88         cmdline = ['groff', '-man', '-T', 'ascii']
89         LOG.debug("Running command: %s", cmdline)
90         p3 = self._popen(cmdline, stdin=PIPE, stdout=PIPE)
91         groff_output = p3.communicate(input=man_contents)[0]
92         cmdline = self.get_pager_cmdline()
93         LOG.debug("Running command: %s", cmdline)
94         p4 = self._popen(cmdline, stdin=PIPE)
95         p4.communicate(input=groff_output)
96         sys.exit(1)
97 
98     def _get_rst2man_name(self):
99         if self._exists_on_path('rst2man.py'):
100             return 'rst2man.py'
101         elif self._exists_on_path('rst2man'):
102             # Some distros like ubuntu will rename rst2man.py to rst2man
103             # if you install their version (i.e. "apt-get install
104             # python-docutils").  Though they could technically rename
105             # this to anything we'll support it renamed to 'rst2man' by
106             # explicitly checking for this case ourself.
107             return 'rst2man'
108         else:
109             # Give them the original name as set from docutils.
110             raise ExecutableNotFoundError('rst2man.py')
111 
112     def _exists_on_path(self, name):
113         # Since we're only dealing with POSIX systems, we can
114         # ignore things like PATHEXT.
115         return any([os.path.exists(os.path.join(p, name))
116                     for p in os.environ.get('PATH', []).split(os.pathsep)])
117 
118     def _popen(self, *args, **kwargs):
119         return Popen(*args, **kwargs)
120 
121 
122 class WindowsHelpRenderer(HelpRenderer):
123     """
124     Render help content on a Windows platform.
125     """
126 
127     def render(self, contents):
128         text_output = publish_string(contents,
129                                      writer=TextWriter())
130         sys.stdout.write(text_output.decode('utf-8'))
131         sys.exit(1)
132 
133 
134 class RawRenderer(HelpRenderer):
135     """
136     Render help as the raw ReST document.
137     """
138 
139     def render(self, contents):
140         sys.stdout.write(contents)
141         sys.exit(1)
142 
143 
144 class HelpCommand(object):
145     """
146     HelpCommand Interface
147     ---------------------
148     A HelpCommand object acts as the interface between objects in the
149     CLI (e.g. Providers, Services, Operations, etc.) and the documentation
150     system (bcdoc).
151 
152     A HelpCommand object wraps the object from the CLI space and provides
153     a consistent interface to critical information needed by the
154     documentation pipeline such as the object's name, description, etc.
155 
156     The HelpCommand object is passed to the component of the
157     documentation pipeline that fires documentation events.  It is
158     then passed on to each document event handler that has registered
159     for the events.
160 
161     All HelpCommand objects contain the following attributes:
162 
163         + ``session`` - A ``botocore`` ``Session`` object.
164         + ``obj`` - The object that is being documented.
165         + ``command_table`` - A dict mapping command names to
166               callable objects.
167         + ``arg_table`` - A dict mapping argument names to callable objects.
168         + ``doc`` - A ``Document`` object that is used to collect the
169               generated documentation.
170 
171     In addition, please note the `properties` defined below which are
172     required to allow the object to be used in the document pipeline.
173 
174     Implementations of HelpCommand are provided here for Provider,
175     Service and Operation objects.  Other implementations for other
176     types of objects might be needed for customization in plugins.
177     As long as the implementations conform to this basic interface
178     it should be possible to pass them to the documentation system
179     and generate interactive and static help files.
180     """
181 
182     EventHandlerClass = None
183     """
184     Each subclass should define this class variable to point to the
185     EventHandler class used by this HelpCommand.
186     """
187 
188     def __init__(self, session, obj, command_table, arg_table):
189         self.session = session
190         self.obj = obj
191         self.command_table = command_table
192         self.arg_table = arg_table
193         self.renderer = get_renderer()
194         self.doc = ReSTDocument(target='man')
195 
196     @property
197     def event_class(self):
198         """
199         Return the ``event_class`` for this object.
200 
201         The ``event_class`` is used by the documentation pipeline
202         when generating documentation events.  For the event below::
203 
204             doc-title.<event_class>.<name>
205 
206         The document pipeline would use this property to determine
207         the ``event_class`` value.
208         """
209         pass
210 
211     @property
212     def name(self):
213         """
214         Return the name of the wrapped object.
215 
216         This would be called by the document pipeline to determine
217         the ``name`` to be inserted into the event, as shown above.
218         """
219         pass
220 
221     def __call__(self, args, parsed_globals):
222         # Create an event handler for a Provider Document
223         instance = self.EventHandlerClass(self)
224         # Now generate all of the events for a Provider document.
225         # We pass ourselves along so that we can, in turn, get passed
226         # to all event handlers.
227         bcdoc.clidocevents.generate_events(self.session, self)
228         self.renderer.render(self.doc.getvalue())
229         instance.unregister()
230 
231 
232 class ProviderHelpCommand(HelpCommand):
233     """Implements top level help command.
234 
235     This is what is called when ``aws help`` is run.
236 
237     """
238     EventHandlerClass = ProviderDocumentEventHandler
239 
240     def __init__(self, session, command_table, arg_table,
241                  description, synopsis, usage):
242         HelpCommand.__init__(self, session, session.provider,
243                              command_table, arg_table)
244         self.description = description
245         self.synopsis = synopsis
246         self.help_usage = usage
247 
248     @property
249     def event_class(self):
250         return 'Provider'
251 
252     @property
253     def name(self):
254         return self.obj.name
255 
256 
257 class ServiceHelpCommand(HelpCommand):
258     """Implements service level help.
259 
260     This is the object invoked whenever a service command
261     help is implemented, e.g. ``aws ec2 help``.
262 
263     """
264 
265     EventHandlerClass = ServiceDocumentEventHandler
266 
267     def __init__(self, session, obj, command_table, arg_table, name,
268                  event_class):
269         super(ServiceHelpCommand, self).__init__(session, obj, command_table,
270                                                  arg_table)
271         self._name = name
272         self._event_class = event_class
273 
274     @property
275     def event_class(self):
276         return self._event_class
277 
278     @property
279     def name(self):
280         return self._name
281 
282 
283 class OperationHelpCommand(HelpCommand):
284     """Implements operation level help.
285 
286     This is the object invoked whenever help for a service is requested,
287     e.g. ``aws ec2 describe-instances help``.
288 
289     """
290     EventHandlerClass = OperationDocumentEventHandler
291 
292     def __init__(self, session, service, operation, arg_table, name,
293                  event_class):
294         HelpCommand.__init__(self, session, operation, None, arg_table)
295         self.service = service
296         self.param_shorthand = ParamShorthand()
297         self._name = name
298         self._event_class = event_class
299 
300     @property
301     def event_class(self):
302         return self._event_class
303 
304     @property
305     def name(self):
306         return self._name
307
```
--- 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/awscli/help.py b/awscli/help.py
--- a/awscli/help.py
+++ b/awscli/help.py
@@ -14,6 +14,7 @@
 import logging
 import os
 import platform
+import shlex
 from subprocess import Popen, PIPE
 
 from docutils.core import publish_string
@@ -79,7 +80,7 @@
             pager = os.environ['MANPAGER']
         elif 'PAGER' in os.environ:
             pager = os.environ['PAGER']
-        return pager.split()
+        return shlex.split(pager)
 
     def render(self, contents):
         man_contents = publish_string(contents, writer=manpage.Writer())

{"golden_diff": "diff --git a/awscli/help.py b/awscli/help.py\n--- a/awscli/help.py\n+++ b/awscli/help.py\n@@ -14,6 +14,7 @@\n import logging\n import os\n import platform\n+import shlex\n from subprocess import Popen, PIPE\n \n from docutils.core import publish_string\n@@ -79,7 +80,7 @@\n             pager = os.environ['MANPAGER']\n         elif 'PAGER' in os.environ:\n             pager = os.environ['PAGER']\n-        return pager.split()\n+        return shlex.split(pager)\n \n     def render(self, contents):\n         man_contents = publish_string(contents, writer=manpage.Writer())\n", "issue": "VIMPAGER error\nI realize that it is a bit of an aside, but it would be great to support alternative pagers.\n\n```\n~ $ echo $MANPAGER\n/bin/sh -c \"col -bx | vim -c 'set ft=man' -\"\n~ $ python --version                                                                                                                    1\nPython 2.7.5\n~ $ pip --version\npip 1.4.1 from /Users/carl/.virtualenv/lib/python2.7/site-packages (python 2.7)\n~ $ aws --version\naws-cli/1.1.0 Python/2.7.5 Darwin/12.5.0\n~ $ aws help\n-bx: -c: line 0: unexpected EOF while looking for matching `\"'\n-bx: -c: line 1: syntax error: unexpected end of file\n```\n\n", "before_files": [{"content": "# Copyright 2012-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"). You\n# may not use this file except in compliance with the License. A copy of\n# the License is located at\n#\n#     http://aws.amazon.com/apache2.0/\n#\n# or in the \"license\" file accompanying this file. This file is\n# distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n# ANY KIND, either express or implied. See the License for the specific\n# language governing permissions and limitations under the License.\nimport sys\nimport logging\nimport os\nimport platform\nfrom subprocess import Popen, PIPE\n\nfrom docutils.core import publish_string\nfrom docutils.writers import manpage\nimport bcdoc\nfrom bcdoc.clidocs import ReSTDocument\nfrom bcdoc.clidocs import ProviderDocumentEventHandler\nfrom bcdoc.clidocs import ServiceDocumentEventHandler\nfrom bcdoc.clidocs import OperationDocumentEventHandler\nimport bcdoc.clidocevents\nfrom bcdoc.textwriter import TextWriter\n\nfrom awscli.argprocess import ParamShorthand\n\n\nLOG = logging.getLogger('awscli.help')\n\n\nclass ExecutableNotFoundError(Exception):\n    def __init__(self, executable_name):\n        super(ExecutableNotFoundError, self).__init__(\n            'Could not find executable named \"%s\"' % executable_name)\n\n\ndef get_renderer():\n    \"\"\"\n    Return the appropriate HelpRenderer implementation for the\n    current platform.\n    \"\"\"\n    if platform.system() == 'Windows':\n        return WindowsHelpRenderer()\n    else:\n        return PosixHelpRenderer()\n\n\nclass HelpRenderer(object):\n    \"\"\"\n    Interface for a help renderer.\n\n    The renderer is responsible for displaying the help content on\n    a particular platform.\n    \"\"\"\n\n    def render(self, contents):\n        \"\"\"\n        Each implementation of HelpRenderer must implement this\n        render method.\n        \"\"\"\n        pass\n\n\nclass PosixHelpRenderer(HelpRenderer):\n    \"\"\"\n    Render help content on a Posix-like system.  This includes\n    Linux and MacOS X.\n    \"\"\"\n\n    PAGER = 'less -R'\n\n    def get_pager_cmdline(self):\n        pager = self.PAGER\n        if 'MANPAGER' in os.environ:\n            pager = os.environ['MANPAGER']\n        elif 'PAGER' in os.environ:\n            pager = os.environ['PAGER']\n        return pager.split()\n\n    def render(self, contents):\n        man_contents = publish_string(contents, writer=manpage.Writer())\n        if not self._exists_on_path('groff'):\n            raise ExecutableNotFoundError('groff')\n        cmdline = ['groff', '-man', '-T', 'ascii']\n        LOG.debug(\"Running command: %s\", cmdline)\n        p3 = self._popen(cmdline, stdin=PIPE, stdout=PIPE)\n        groff_output = p3.communicate(input=man_contents)[0]\n        cmdline = self.get_pager_cmdline()\n        LOG.debug(\"Running command: %s\", cmdline)\n        p4 = self._popen(cmdline, stdin=PIPE)\n        p4.communicate(input=groff_output)\n        sys.exit(1)\n\n    def _get_rst2man_name(self):\n        if self._exists_on_path('rst2man.py'):\n            return 'rst2man.py'\n        elif self._exists_on_path('rst2man'):\n            # Some distros like ubuntu will rename rst2man.py to rst2man\n            # if you install their version (i.e. \"apt-get install\n            # python-docutils\").  Though they could technically rename\n            # this to anything we'll support it renamed to 'rst2man' by\n            # explicitly checking for this case ourself.\n            return 'rst2man'\n        else:\n            # Give them the original name as set from docutils.\n            raise ExecutableNotFoundError('rst2man.py')\n\n    def _exists_on_path(self, name):\n        # Since we're only dealing with POSIX systems, we can\n        # ignore things like PATHEXT.\n        return any([os.path.exists(os.path.join(p, name))\n                    for p in os.environ.get('PATH', []).split(os.pathsep)])\n\n    def _popen(self, *args, **kwargs):\n        return Popen(*args, **kwargs)\n\n\nclass WindowsHelpRenderer(HelpRenderer):\n    \"\"\"\n    Render help content on a Windows platform.\n    \"\"\"\n\n    def render(self, contents):\n        text_output = publish_string(contents,\n                                     writer=TextWriter())\n        sys.stdout.write(text_output.decode('utf-8'))\n        sys.exit(1)\n\n\nclass RawRenderer(HelpRenderer):\n    \"\"\"\n    Render help as the raw ReST document.\n    \"\"\"\n\n    def render(self, contents):\n        sys.stdout.write(contents)\n        sys.exit(1)\n\n\nclass HelpCommand(object):\n    \"\"\"\n    HelpCommand Interface\n    ---------------------\n    A HelpCommand object acts as the interface between objects in the\n    CLI (e.g. Providers, Services, Operations, etc.) and the documentation\n    system (bcdoc).\n\n    A HelpCommand object wraps the object from the CLI space and provides\n    a consistent interface to critical information needed by the\n    documentation pipeline such as the object's name, description, etc.\n\n    The HelpCommand object is passed to the component of the\n    documentation pipeline that fires documentation events.  It is\n    then passed on to each document event handler that has registered\n    for the events.\n\n    All HelpCommand objects contain the following attributes:\n\n        + ``session`` - A ``botocore`` ``Session`` object.\n        + ``obj`` - The object that is being documented.\n        + ``command_table`` - A dict mapping command names to\n              callable objects.\n        + ``arg_table`` - A dict mapping argument names to callable objects.\n        + ``doc`` - A ``Document`` object that is used to collect the\n              generated documentation.\n\n    In addition, please note the `properties` defined below which are\n    required to allow the object to be used in the document pipeline.\n\n    Implementations of HelpCommand are provided here for Provider,\n    Service and Operation objects.  Other implementations for other\n    types of objects might be needed for customization in plugins.\n    As long as the implementations conform to this basic interface\n    it should be possible to pass them to the documentation system\n    and generate interactive and static help files.\n    \"\"\"\n\n    EventHandlerClass = None\n    \"\"\"\n    Each subclass should define this class variable to point to the\n    EventHandler class used by this HelpCommand.\n    \"\"\"\n\n    def __init__(self, session, obj, command_table, arg_table):\n        self.session = session\n        self.obj = obj\n        self.command_table = command_table\n        self.arg_table = arg_table\n        self.renderer = get_renderer()\n        self.doc = ReSTDocument(target='man')\n\n    @property\n    def event_class(self):\n        \"\"\"\n        Return the ``event_class`` for this object.\n\n        The ``event_class`` is used by the documentation pipeline\n        when generating documentation events.  For the event below::\n\n            doc-title.<event_class>.<name>\n\n        The document pipeline would use this property to determine\n        the ``event_class`` value.\n        \"\"\"\n        pass\n\n    @property\n    def name(self):\n        \"\"\"\n        Return the name of the wrapped object.\n\n        This would be called by the document pipeline to determine\n        the ``name`` to be inserted into the event, as shown above.\n        \"\"\"\n        pass\n\n    def __call__(self, args, parsed_globals):\n        # Create an event handler for a Provider Document\n        instance = self.EventHandlerClass(self)\n        # Now generate all of the events for a Provider document.\n        # We pass ourselves along so that we can, in turn, get passed\n        # to all event handlers.\n        bcdoc.clidocevents.generate_events(self.session, self)\n        self.renderer.render(self.doc.getvalue())\n        instance.unregister()\n\n\nclass ProviderHelpCommand(HelpCommand):\n    \"\"\"Implements top level help command.\n\n    This is what is called when ``aws help`` is run.\n\n    \"\"\"\n    EventHandlerClass = ProviderDocumentEventHandler\n\n    def __init__(self, session, command_table, arg_table,\n                 description, synopsis, usage):\n        HelpCommand.__init__(self, session, session.provider,\n                             command_table, arg_table)\n        self.description = description\n        self.synopsis = synopsis\n        self.help_usage = usage\n\n    @property\n    def event_class(self):\n        return 'Provider'\n\n    @property\n    def name(self):\n        return self.obj.name\n\n\nclass ServiceHelpCommand(HelpCommand):\n    \"\"\"Implements service level help.\n\n    This is the object invoked whenever a service command\n    help is implemented, e.g. ``aws ec2 help``.\n\n    \"\"\"\n\n    EventHandlerClass = ServiceDocumentEventHandler\n\n    def __init__(self, session, obj, command_table, arg_table, name,\n                 event_class):\n        super(ServiceHelpCommand, self).__init__(session, obj, command_table,\n                                                 arg_table)\n        self._name = name\n        self._event_class = event_class\n\n    @property\n    def event_class(self):\n        return self._event_class\n\n    @property\n    def name(self):\n        return self._name\n\n\nclass OperationHelpCommand(HelpCommand):\n    \"\"\"Implements operation level help.\n\n    This is the object invoked whenever help for a service is requested,\n    e.g. ``aws ec2 describe-instances help``.\n\n    \"\"\"\n    EventHandlerClass = OperationDocumentEventHandler\n\n    def __init__(self, session, service, operation, arg_table, name,\n                 event_class):\n        HelpCommand.__init__(self, session, operation, None, arg_table)\n        self.service = service\n        self.param_shorthand = ParamShorthand()\n        self._name = name\n        self._event_class = event_class\n\n    @property\n    def event_class(self):\n        return self._event_class\n\n    @property\n    def name(self):\n        return self._name\n", "path": "awscli/help.py"}], "after_files": [{"content": "# Copyright 2012-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"). You\n# may not use this file except in compliance with the License. A copy of\n# the License is located at\n#\n#     http://aws.amazon.com/apache2.0/\n#\n# or in the \"license\" file accompanying this file. This file is\n# distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n# ANY KIND, either express or implied. See the License for the specific\n# language governing permissions and limitations under the License.\nimport sys\nimport logging\nimport os\nimport platform\nimport shlex\nfrom subprocess import Popen, PIPE\n\nfrom docutils.core import publish_string\nfrom docutils.writers import manpage\nimport bcdoc\nfrom bcdoc.clidocs import ReSTDocument\nfrom bcdoc.clidocs import ProviderDocumentEventHandler\nfrom bcdoc.clidocs import ServiceDocumentEventHandler\nfrom bcdoc.clidocs import OperationDocumentEventHandler\nimport bcdoc.clidocevents\nfrom bcdoc.textwriter import TextWriter\n\nfrom awscli.argprocess import ParamShorthand\n\n\nLOG = logging.getLogger('awscli.help')\n\n\nclass ExecutableNotFoundError(Exception):\n    def __init__(self, executable_name):\n        super(ExecutableNotFoundError, self).__init__(\n            'Could not find executable named \"%s\"' % executable_name)\n\n\ndef get_renderer():\n    \"\"\"\n    Return the appropriate HelpRenderer implementation for the\n    current platform.\n    \"\"\"\n    if platform.system() == 'Windows':\n        return WindowsHelpRenderer()\n    else:\n        return PosixHelpRenderer()\n\n\nclass HelpRenderer(object):\n    \"\"\"\n    Interface for a help renderer.\n\n    The renderer is responsible for displaying the help content on\n    a particular platform.\n    \"\"\"\n\n    def render(self, contents):\n        \"\"\"\n        Each implementation of HelpRenderer must implement this\n        render method.\n        \"\"\"\n        pass\n\n\nclass PosixHelpRenderer(HelpRenderer):\n    \"\"\"\n    Render help content on a Posix-like system.  This includes\n    Linux and MacOS X.\n    \"\"\"\n\n    PAGER = 'less -R'\n\n    def get_pager_cmdline(self):\n        pager = self.PAGER\n        if 'MANPAGER' in os.environ:\n            pager = os.environ['MANPAGER']\n        elif 'PAGER' in os.environ:\n            pager = os.environ['PAGER']\n        return shlex.split(pager)\n\n    def render(self, contents):\n        man_contents = publish_string(contents, writer=manpage.Writer())\n        if not self._exists_on_path('groff'):\n            raise ExecutableNotFoundError('groff')\n        cmdline = ['groff', '-man', '-T', 'ascii']\n        LOG.debug(\"Running command: %s\", cmdline)\n        p3 = self._popen(cmdline, stdin=PIPE, stdout=PIPE)\n        groff_output = p3.communicate(input=man_contents)[0]\n        cmdline = self.get_pager_cmdline()\n        LOG.debug(\"Running command: %s\", cmdline)\n        p4 = self._popen(cmdline, stdin=PIPE)\n        p4.communicate(input=groff_output)\n        sys.exit(1)\n\n    def _get_rst2man_name(self):\n        if self._exists_on_path('rst2man.py'):\n            return 'rst2man.py'\n        elif self._exists_on_path('rst2man'):\n            # Some distros like ubuntu will rename rst2man.py to rst2man\n            # if you install their version (i.e. \"apt-get install\n            # python-docutils\").  Though they could technically rename\n            # this to anything we'll support it renamed to 'rst2man' by\n            # explicitly checking for this case ourself.\n            return 'rst2man'\n        else:\n            # Give them the original name as set from docutils.\n            raise ExecutableNotFoundError('rst2man.py')\n\n    def _exists_on_path(self, name):\n        # Since we're only dealing with POSIX systems, we can\n        # ignore things like PATHEXT.\n        return any([os.path.exists(os.path.join(p, name))\n                    for p in os.environ.get('PATH', []).split(os.pathsep)])\n\n    def _popen(self, *args, **kwargs):\n        return Popen(*args, **kwargs)\n\n\nclass WindowsHelpRenderer(HelpRenderer):\n    \"\"\"\n    Render help content on a Windows platform.\n    \"\"\"\n\n    def render(self, contents):\n        text_output = publish_string(contents,\n                                     writer=TextWriter())\n        sys.stdout.write(text_output.decode('utf-8'))\n        sys.exit(1)\n\n\nclass RawRenderer(HelpRenderer):\n    \"\"\"\n    Render help as the raw ReST document.\n    \"\"\"\n\n    def render(self, contents):\n        sys.stdout.write(contents)\n        sys.exit(1)\n\n\nclass HelpCommand(object):\n    \"\"\"\n    HelpCommand Interface\n    ---------------------\n    A HelpCommand object acts as the interface between objects in the\n    CLI (e.g. Providers, Services, Operations, etc.) and the documentation\n    system (bcdoc).\n\n    A HelpCommand object wraps the object from the CLI space and provides\n    a consistent interface to critical information needed by the\n    documentation pipeline such as the object's name, description, etc.\n\n    The HelpCommand object is passed to the component of the\n    documentation pipeline that fires documentation events.  It is\n    then passed on to each document event handler that has registered\n    for the events.\n\n    All HelpCommand objects contain the following attributes:\n\n        + ``session`` - A ``botocore`` ``Session`` object.\n        + ``obj`` - The object that is being documented.\n        + ``command_table`` - A dict mapping command names to\n              callable objects.\n        + ``arg_table`` - A dict mapping argument names to callable objects.\n        + ``doc`` - A ``Document`` object that is used to collect the\n              generated documentation.\n\n    In addition, please note the `properties` defined below which are\n    required to allow the object to be used in the document pipeline.\n\n    Implementations of HelpCommand are provided here for Provider,\n    Service and Operation objects.  Other implementations for other\n    types of objects might be needed for customization in plugins.\n    As long as the implementations conform to this basic interface\n    it should be possible to pass them to the documentation system\n    and generate interactive and static help files.\n    \"\"\"\n\n    EventHandlerClass = None\n    \"\"\"\n    Each subclass should define this class variable to point to the\n    EventHandler class used by this HelpCommand.\n    \"\"\"\n\n    def __init__(self, session, obj, command_table, arg_table):\n        self.session = session\n        self.obj = obj\n        self.command_table = command_table\n        self.arg_table = arg_table\n        self.renderer = get_renderer()\n        self.doc = ReSTDocument(target='man')\n\n    @property\n    def event_class(self):\n        \"\"\"\n        Return the ``event_class`` for this object.\n\n        The ``event_class`` is used by the documentation pipeline\n        when generating documentation events.  For the event below::\n\n            doc-title.<event_class>.<name>\n\n        The document pipeline would use this property to determine\n        the ``event_class`` value.\n        \"\"\"\n        pass\n\n    @property\n    def name(self):\n        \"\"\"\n        Return the name of the wrapped object.\n\n        This would be called by the document pipeline to determine\n        the ``name`` to be inserted into the event, as shown above.\n        \"\"\"\n        pass\n\n    def __call__(self, args, parsed_globals):\n        # Create an event handler for a Provider Document\n        instance = self.EventHandlerClass(self)\n        # Now generate all of the events for a Provider document.\n        # We pass ourselves along so that we can, in turn, get passed\n        # to all event handlers.\n        bcdoc.clidocevents.generate_events(self.session, self)\n        self.renderer.render(self.doc.getvalue())\n        instance.unregister()\n\n\nclass ProviderHelpCommand(HelpCommand):\n    \"\"\"Implements top level help command.\n\n    This is what is called when ``aws help`` is run.\n\n    \"\"\"\n    EventHandlerClass = ProviderDocumentEventHandler\n\n    def __init__(self, session, command_table, arg_table,\n                 description, synopsis, usage):\n        HelpCommand.__init__(self, session, session.provider,\n                             command_table, arg_table)\n        self.description = description\n        self.synopsis = synopsis\n        self.help_usage = usage\n\n    @property\n    def event_class(self):\n        return 'Provider'\n\n    @property\n    def name(self):\n        return self.obj.name\n\n\nclass ServiceHelpCommand(HelpCommand):\n    \"\"\"Implements service level help.\n\n    This is the object invoked whenever a service command\n    help is implemented, e.g. ``aws ec2 help``.\n\n    \"\"\"\n\n    EventHandlerClass = ServiceDocumentEventHandler\n\n    def __init__(self, session, obj, command_table, arg_table, name,\n                 event_class):\n        super(ServiceHelpCommand, self).__init__(session, obj, command_table,\n                                                 arg_table)\n        self._name = name\n        self._event_class = event_class\n\n    @property\n    def event_class(self):\n        return self._event_class\n\n    @property\n    def name(self):\n        return self._name\n\n\nclass OperationHelpCommand(HelpCommand):\n    \"\"\"Implements operation level help.\n\n    This is the object invoked whenever help for a service is requested,\n    e.g. ``aws ec2 describe-instances help``.\n\n    \"\"\"\n    EventHandlerClass = OperationDocumentEventHandler\n\n    def __init__(self, session, service, operation, arg_table, name,\n                 event_class):\n        HelpCommand.__init__(self, session, operation, None, arg_table)\n        self.service = service\n        self.param_shorthand = ParamShorthand()\n        self._name = name\n        self._event_class = event_class\n\n    @property\n    def event_class(self):\n        return self._event_class\n\n    @property\n    def name(self):\n        return self._name\n", "path": "awscli/help.py"}]}