prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  prequest does not support PUT
  Title says it all.  Give me the green light and I can whip up a patch (no pun intended).
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `pyramid/scripts/prequest.py`
  Content:
  ```
  1 import optparse
  2 import sys
  3 import textwrap
  4 
  5 from pyramid.compat import url_unquote
  6 from pyramid.request import Request
  7 from pyramid.paster import get_app
  8 from pyramid.scripts.common import parse_vars
  9 
  10 def main(argv=sys.argv, quiet=False):
  11     command = PRequestCommand(argv, quiet)
  12     return command.run()
  13 
  14 class PRequestCommand(object):
  15     description = """\
  16     Run a request for the described application.
  17 
  18     This command makes an artifical request to a web application that uses a
  19     PasteDeploy (.ini) configuration file for the server and application.
  20 
  21     Use "prequest config.ini /path" to request "/path".  Use "prequest
  22     --method=POST config.ini /path < data" to do a POST with the given
  23     request body.
  24 
  25     If the path is relative (doesn't begin with "/") it is interpreted as
  26     relative to "/".  The path passed to this script should be URL-quoted.
  27     The path can be succeeded with a query string (e.g. `/path?a=1&=b2').
  28 
  29     The variable "environ['paste.command_request']" will be set to "True" in
  30     the request's WSGI environment, so your application can distinguish these
  31     calls from normal requests.
  32     """
  33     usage = "usage: %prog config_uri path_info [args/options]"
  34     parser = optparse.OptionParser(
  35         usage=usage,
  36         description=textwrap.dedent(description)
  37         )
  38     parser.add_option(
  39         '-n', '--app-name',
  40         dest='app_name',
  41         metavar= 'NAME',
  42         help="Load the named application from the config file (default 'main')",
  43         type="string",
  44         )
  45     parser.add_option(
  46         '--header',
  47         dest='headers',
  48         metavar='NAME:VALUE',
  49         type='string',
  50         action='append',
  51         help="Header to add to request (you can use this option multiple times)"
  52         )
  53     parser.add_option(
  54         '-d', '--display-headers',
  55         dest='display_headers',
  56         action='store_true',
  57         help='Display status and headers before the response body'
  58         )
  59     parser.add_option(
  60         '-m', '--method',
  61         dest='method',
  62         choices=['GET', 'HEAD', 'POST', 'DELETE'],
  63         type='choice',
  64         help='Request method type (GET, POST, DELETE)',
  65         )
  66 
  67     get_app = staticmethod(get_app)
  68     stdin = sys.stdin
  69 
  70     def __init__(self, argv, quiet=False):
  71         self.quiet = quiet
  72         self.options, self.args = self.parser.parse_args(argv[1:])
  73 
  74     def out(self, msg): # pragma: no cover
  75         if not self.quiet:
  76             print(msg)
  77 
  78     def run(self):
  79         if not len(self.args) >= 2:
  80             self.out('You must provide at least two arguments')
  81             return 2
  82         app_spec = self.args[0]
  83         path = self.args[1]
  84         if not path.startswith('/'):
  85             path = '/' + path
  86 
  87         try:
  88             path, qs = path.split('?', 1)
  89         except ValueError:
  90             qs = ''
  91 
  92         path = url_unquote(path)
  93 
  94         headers = {}
  95         if self.options.headers:
  96             for item in self.options.headers:
  97                 if ':' not in item:
  98                     self.out(
  99                         "Bad --header=%s option, value must be in the form "
  100                         "'name:value'" % item)
  101                     return 2
  102                 name, value = item.split(':', 1)
  103                 headers[name] = value.strip()
  104 
  105         app = self.get_app(app_spec, self.options.app_name,
  106                 options=parse_vars(self.args[2:]))
  107 
  108         request_method = (self.options.method or 'GET').upper()
  109 
  110         environ = {
  111             'REQUEST_METHOD': request_method,
  112             'SCRIPT_NAME': '',           # may be empty if app is at the root
  113             'PATH_INFO': path,           
  114             'SERVER_NAME': 'localhost',  # always mandatory
  115             'SERVER_PORT': '80',         # always mandatory 
  116             'SERVER_PROTOCOL': 'HTTP/1.0',
  117             'CONTENT_TYPE': 'text/plain',
  118             'REMOTE_ADDR':'127.0.0.1',
  119             'wsgi.run_once': True,
  120             'wsgi.multithread': False,
  121             'wsgi.multiprocess': False,
  122             'wsgi.errors': sys.stderr,
  123             'wsgi.url_scheme': 'http',
  124             'wsgi.version': (1, 0),
  125             'QUERY_STRING': qs,
  126             'HTTP_ACCEPT': 'text/plain;q=1.0, */*;q=0.1',
  127             'paste.command_request': True,
  128             }
  129 
  130         if request_method == 'POST':
  131             environ['wsgi.input'] = self.stdin
  132             environ['CONTENT_LENGTH'] = '-1'
  133 
  134         for name, value in headers.items():
  135             if name.lower() == 'content-type':
  136                 name = 'CONTENT_TYPE'
  137             else:
  138                 name = 'HTTP_'+name.upper().replace('-', '_')
  139             environ[name] = value
  140 
  141         request = Request.blank(path, environ=environ)
  142         response = request.get_response(app)
  143         if self.options.display_headers:
  144             self.out(response.status)
  145             for name, value in response.headerlist:
  146                 self.out('%s: %s' % (name, value))
  147         if response.charset:
  148             self.out(response.ubody)
  149         else:
  150             self.out(response.body)
  151         return 0
  152
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/pyramid/scripts/prequest.py b/pyramid/scripts/prequest.py
  --- a/pyramid/scripts/prequest.py
  +++ b/pyramid/scripts/prequest.py
  @@ -59,9 +59,9 @@
       parser.add_option(
           '-m', '--method',
           dest='method',
  -        choices=['GET', 'HEAD', 'POST', 'DELETE'],
  +        choices=['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE'],
           type='choice',
  -        help='Request method type (GET, POST, DELETE)',
  +        help='Request method type',
           )
   
       get_app = staticmethod(get_app)
  @@ -127,7 +127,7 @@
               'paste.command_request': True,
               }
   
  -        if request_method == 'POST':
  +        if request_method in ('POST', 'PUT', 'PATCH'):
               environ['wsgi.input'] = self.stdin
               environ['CONTENT_LENGTH'] = '-1'
  
verification_info: {"golden_diff": "diff --git a/pyramid/scripts/prequest.py b/pyramid/scripts/prequest.py\n--- a/pyramid/scripts/prequest.py\n+++ b/pyramid/scripts/prequest.py\n@@ -59,9 +59,9 @@\n     parser.add_option(\n         '-m', '--method',\n         dest='method',\n-        choices=['GET', 'HEAD', 'POST', 'DELETE'],\n+        choices=['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE'],\n         type='choice',\n-        help='Request method type (GET, POST, DELETE)',\n+        help='Request method type',\n         )\n \n     get_app = staticmethod(get_app)\n@@ -127,7 +127,7 @@\n             'paste.command_request': True,\n             }\n \n-        if request_method == 'POST':\n+        if request_method in ('POST', 'PUT', 'PATCH'):\n             environ['wsgi.input'] = self.stdin\n             environ['CONTENT_LENGTH'] = '-1'\n", "issue": "prequest does not support PUT\nTitle says it all.  Give me the green light and I can whip up a patch (no pun intended).\n\n", "before_files": [{"content": "import optparse\nimport sys\nimport textwrap\n\nfrom pyramid.compat import url_unquote\nfrom pyramid.request import Request\nfrom pyramid.paster import get_app\nfrom pyramid.scripts.common import parse_vars\n\ndef main(argv=sys.argv, quiet=False):\n    command = PRequestCommand(argv, quiet)\n    return command.run()\n\nclass PRequestCommand(object):\n    description = \"\"\"\\\n    Run a request for the described application.\n\n    This command makes an artifical request to a web application that uses a\n    PasteDeploy (.ini) configuration file for the server and application.\n\n    Use \"prequest config.ini /path\" to request \"/path\".  Use \"prequest\n    --method=POST config.ini /path < data\" to do a POST with the given\n    request body.\n\n    If the path is relative (doesn't begin with \"/\") it is interpreted as\n    relative to \"/\".  The path passed to this script should be URL-quoted.\n    The path can be succeeded with a query string (e.g. `/path?a=1&=b2').\n\n    The variable \"environ['paste.command_request']\" will be set to \"True\" in\n    the request's WSGI environment, so your application can distinguish these\n    calls from normal requests.\n    \"\"\"\n    usage = \"usage: %prog config_uri path_info [args/options]\"\n    parser = optparse.OptionParser(\n        usage=usage,\n        description=textwrap.dedent(description)\n        )\n    parser.add_option(\n        '-n', '--app-name',\n        dest='app_name',\n        metavar= 'NAME',\n        help=\"Load the named application from the config file (default 'main')\",\n        type=\"string\",\n        )\n    parser.add_option(\n        '--header',\n        dest='headers',\n        metavar='NAME:VALUE',\n        type='string',\n        action='append',\n        help=\"Header to add to request (you can use this option multiple times)\"\n        )\n    parser.add_option(\n        '-d', '--display-headers',\n        dest='display_headers',\n        action='store_true',\n        help='Display status and headers before the response body'\n        )\n    parser.add_option(\n        '-m', '--method',\n        dest='method',\n        choices=['GET', 'HEAD', 'POST', 'DELETE'],\n        type='choice',\n        help='Request method type (GET, POST, DELETE)',\n        )\n\n    get_app = staticmethod(get_app)\n    stdin = sys.stdin\n\n    def __init__(self, argv, quiet=False):\n        self.quiet = quiet\n        self.options, self.args = self.parser.parse_args(argv[1:])\n\n    def out(self, msg): # pragma: no cover\n        if not self.quiet:\n            print(msg)\n\n    def run(self):\n        if not len(self.args) >= 2:\n            self.out('You must provide at least two arguments')\n            return 2\n        app_spec = self.args[0]\n        path = self.args[1]\n        if not path.startswith('/'):\n            path = '/' + path\n\n        try:\n            path, qs = path.split('?', 1)\n        except ValueError:\n            qs = ''\n\n        path = url_unquote(path)\n\n        headers = {}\n        if self.options.headers:\n            for item in self.options.headers:\n                if ':' not in item:\n                    self.out(\n                        \"Bad --header=%s option, value must be in the form \"\n                        \"'name:value'\" % item)\n                    return 2\n                name, value = item.split(':', 1)\n                headers[name] = value.strip()\n\n        app = self.get_app(app_spec, self.options.app_name,\n                options=parse_vars(self.args[2:]))\n\n        request_method = (self.options.method or 'GET').upper()\n\n        environ = {\n            'REQUEST_METHOD': request_method,\n            'SCRIPT_NAME': '',           # may be empty if app is at the root\n            'PATH_INFO': path,           \n            'SERVER_NAME': 'localhost',  # always mandatory\n            'SERVER_PORT': '80',         # always mandatory \n            'SERVER_PROTOCOL': 'HTTP/1.0',\n            'CONTENT_TYPE': 'text/plain',\n            'REMOTE_ADDR':'127.0.0.1',\n            'wsgi.run_once': True,\n            'wsgi.multithread': False,\n            'wsgi.multiprocess': False,\n            'wsgi.errors': sys.stderr,\n            'wsgi.url_scheme': 'http',\n            'wsgi.version': (1, 0),\n            'QUERY_STRING': qs,\n            'HTTP_ACCEPT': 'text/plain;q=1.0, */*;q=0.1',\n            'paste.command_request': True,\n            }\n\n        if request_method == 'POST':\n            environ['wsgi.input'] = self.stdin\n            environ['CONTENT_LENGTH'] = '-1'\n\n        for name, value in headers.items():\n            if name.lower() == 'content-type':\n                name = 'CONTENT_TYPE'\n            else:\n                name = 'HTTP_'+name.upper().replace('-', '_')\n            environ[name] = value\n\n        request = Request.blank(path, environ=environ)\n        response = request.get_response(app)\n        if self.options.display_headers:\n            self.out(response.status)\n            for name, value in response.headerlist:\n                self.out('%s: %s' % (name, value))\n        if response.charset:\n            self.out(response.ubody)\n        else:\n            self.out(response.body)\n        return 0\n", "path": "pyramid/scripts/prequest.py"}], "after_files": [{"content": "import optparse\nimport sys\nimport textwrap\n\nfrom pyramid.compat import url_unquote\nfrom pyramid.request import Request\nfrom pyramid.paster import get_app\nfrom pyramid.scripts.common import parse_vars\n\ndef main(argv=sys.argv, quiet=False):\n    command = PRequestCommand(argv, quiet)\n    return command.run()\n\nclass PRequestCommand(object):\n    description = \"\"\"\\\n    Run a request for the described application.\n\n    This command makes an artifical request to a web application that uses a\n    PasteDeploy (.ini) configuration file for the server and application.\n\n    Use \"prequest config.ini /path\" to request \"/path\".  Use \"prequest\n    --method=POST config.ini /path < data\" to do a POST with the given\n    request body.\n\n    If the path is relative (doesn't begin with \"/\") it is interpreted as\n    relative to \"/\".  The path passed to this script should be URL-quoted.\n    The path can be succeeded with a query string (e.g. `/path?a=1&=b2').\n\n    The variable \"environ['paste.command_request']\" will be set to \"True\" in\n    the request's WSGI environment, so your application can distinguish these\n    calls from normal requests.\n    \"\"\"\n    usage = \"usage: %prog config_uri path_info [args/options]\"\n    parser = optparse.OptionParser(\n        usage=usage,\n        description=textwrap.dedent(description)\n        )\n    parser.add_option(\n        '-n', '--app-name',\n        dest='app_name',\n        metavar= 'NAME',\n        help=\"Load the named application from the config file (default 'main')\",\n        type=\"string\",\n        )\n    parser.add_option(\n        '--header',\n        dest='headers',\n        metavar='NAME:VALUE',\n        type='string',\n        action='append',\n        help=\"Header to add to request (you can use this option multiple times)\"\n        )\n    parser.add_option(\n        '-d', '--display-headers',\n        dest='display_headers',\n        action='store_true',\n        help='Display status and headers before the response body'\n        )\n    parser.add_option(\n        '-m', '--method',\n        dest='method',\n        choices=['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE'],\n        type='choice',\n        help='Request method type',\n        )\n\n    get_app = staticmethod(get_app)\n    stdin = sys.stdin\n\n    def __init__(self, argv, quiet=False):\n        self.quiet = quiet\n        self.options, self.args = self.parser.parse_args(argv[1:])\n\n    def out(self, msg): # pragma: no cover\n        if not self.quiet:\n            print(msg)\n\n    def run(self):\n        if not len(self.args) >= 2:\n            self.out('You must provide at least two arguments')\n            return 2\n        app_spec = self.args[0]\n        path = self.args[1]\n        if not path.startswith('/'):\n            path = '/' + path\n\n        try:\n            path, qs = path.split('?', 1)\n        except ValueError:\n            qs = ''\n\n        path = url_unquote(path)\n\n        headers = {}\n        if self.options.headers:\n            for item in self.options.headers:\n                if ':' not in item:\n                    self.out(\n                        \"Bad --header=%s option, value must be in the form \"\n                        \"'name:value'\" % item)\n                    return 2\n                name, value = item.split(':', 1)\n                headers[name] = value.strip()\n\n        app = self.get_app(app_spec, self.options.app_name,\n                options=parse_vars(self.args[2:]))\n\n        request_method = (self.options.method or 'GET').upper()\n\n        environ = {\n            'REQUEST_METHOD': request_method,\n            'SCRIPT_NAME': '',           # may be empty if app is at the root\n            'PATH_INFO': path,           \n            'SERVER_NAME': 'localhost',  # always mandatory\n            'SERVER_PORT': '80',         # always mandatory \n            'SERVER_PROTOCOL': 'HTTP/1.0',\n            'CONTENT_TYPE': 'text/plain',\n            'REMOTE_ADDR':'127.0.0.1',\n            'wsgi.run_once': True,\n            'wsgi.multithread': False,\n            'wsgi.multiprocess': False,\n            'wsgi.errors': sys.stderr,\n            'wsgi.url_scheme': 'http',\n            'wsgi.version': (1, 0),\n            'QUERY_STRING': qs,\n            'HTTP_ACCEPT': 'text/plain;q=1.0, */*;q=0.1',\n            'paste.command_request': True,\n            }\n\n        if request_method in ('POST', 'PUT', 'PATCH'):\n            environ['wsgi.input'] = self.stdin\n            environ['CONTENT_LENGTH'] = '-1'\n\n        for name, value in headers.items():\n            if name.lower() == 'content-type':\n                name = 'CONTENT_TYPE'\n            else:\n                name = 'HTTP_'+name.upper().replace('-', '_')\n            environ[name] = value\n\n        request = Request.blank(path, environ=environ)\n        response = request.get_response(app)\n        if self.options.display_headers:\n            self.out(response.status)\n            for name, value in response.headerlist:\n                self.out('%s: %s' % (name, value))\n        if response.charset:\n            self.out(response.ubody)\n        else:\n            self.out(response.body)\n        return 0\n", "path": "pyramid/scripts/prequest.py"}]}