prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  After adding request flags subclasses of logformatter that rely on 'flags' format string are broken
  #2082 added flags to request but it also renamed formatting string key from flags to response_flags/request_flags
  ```
  CRAWLEDMSG = u"Crawled (%(status)s) %(request)s (referer: %(referer)s)%(flags)s"
   +CRAWLEDMSG = u"Crawled (%(status)s) %(request)s%(request_flags)s (referer: %(referer)s)%(response_flags)s" 
  ```
  
  Scrapy allows you to override logformatter and this is what I have in my project. I have logformatter looking rouhgly like this
  
  
  ```python
  # dirbot/logf.py
  from scrapy.logformatter import LogFormatter
  
  
  class CustomLogFormatter(LogFormatter):
      def crawled(self, request, response, spider):
          kwargs = super(CustomLogFormatter, self).crawled(
              request, response, spider)
          kwargs['msg'] = (
              u"Crawled (%(status)s) %(request)s "
              u"(referer: %(referer)s, latency: %(latency).2f s)%(flags)s"
          )
          kwargs['args']['latency'] = response.meta.get('download_latency', 0)
          return kwargs
  ```
  
  now if you enable it in settings `LOG_FORMATTER = 'dirbot.logf.CustomLogFormatter'
  ` and  try to run it with recent master you'll get KeyError
  
  ```
  2017-03-13 14:15:26 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023
  Traceback (most recent call last):
    File "/usr/lib/python2.7/logging/__init__.py", line 851, in emit
      msg = self.format(record)
    File "/usr/lib/python2.7/logging/__init__.py", line 724, in format
      return fmt.format(record)
    File "/usr/lib/python2.7/logging/__init__.py", line 464, in format
      record.message = record.getMessage()
    File "/usr/lib/python2.7/logging/__init__.py", line 328, in getMessage
      msg = msg % self.args
  KeyError: u'flags'
  Logged from file engine.py, line 238
  Traceback (most recent call last):
    File "/usr/lib/python2.7/logging/__init__.py", line 851, in emit
      msg = self.format(record)
    File "/usr/lib/python2.7/logging/__init__.py", line 724, in format
      return fmt.format(record)
    File "/usr/lib/python2.7/logging/__init__.py", line 464, in format
      record.message = record.getMessage()
    File "/usr/lib/python2.7/logging/__init__.py", line 328, in getMessage
      msg = msg % self.args
  KeyError: u'flags'
  Logged from file engine.py, line 238
  2017-03-13 14:15:27 [scrapy.core.scraper] DEBUG: Scraped from <200 http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/>
  ```
  
  So this change that renamed `flags` to `response_flags/request_flags` seems backward incompatible. 
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `scrapy/logformatter.py`
  Content:
  ```
  1 import os
  2 import logging
  3 
  4 from twisted.python.failure import Failure
  5 
  6 from scrapy.utils.request import referer_str
  7 
  8 SCRAPEDMSG = u"Scraped from %(src)s" + os.linesep + "%(item)s"
  9 DROPPEDMSG = u"Dropped: %(exception)s" + os.linesep + "%(item)s"
  10 CRAWLEDMSG = u"Crawled (%(status)s) %(request)s%(request_flags)s (referer: %(referer)s)%(response_flags)s"
  11 
  12 
  13 class LogFormatter(object):
  14     """Class for generating log messages for different actions.
  15 
  16     All methods must return a dictionary listing the parameters `level`, `msg`
  17     and `args` which are going to be used for constructing the log message when
  18     calling logging.log.
  19 
  20     Dictionary keys for the method outputs:
  21         * `level` should be the log level for that action, you can use those
  22         from the python logging library: logging.DEBUG, logging.INFO,
  23         logging.WARNING, logging.ERROR and logging.CRITICAL.
  24 
  25         * `msg` should be a string that can contain different formatting
  26         placeholders. This string, formatted with the provided `args`, is going
  27         to be the log message for that action.
  28 
  29         * `args` should be a tuple or dict with the formatting placeholders for
  30         `msg`.  The final log message is computed as output['msg'] %
  31         output['args'].
  32     """
  33 
  34     def crawled(self, request, response, spider):
  35         request_flags = ' %s' % str(request.flags) if request.flags else ''
  36         response_flags = ' %s' % str(response.flags) if response.flags else ''
  37         return {
  38             'level': logging.DEBUG,
  39             'msg': CRAWLEDMSG,
  40             'args': {
  41                 'status': response.status,
  42                 'request': request,
  43                 'request_flags' : request_flags,
  44                 'referer': referer_str(request),
  45                 'response_flags': response_flags,
  46             }
  47         }
  48 
  49     def scraped(self, item, response, spider):
  50         if isinstance(response, Failure):
  51             src = response.getErrorMessage()
  52         else:
  53             src = response
  54         return {
  55             'level': logging.DEBUG,
  56             'msg': SCRAPEDMSG,
  57             'args': {
  58                 'src': src,
  59                 'item': item,
  60             }
  61         }
  62 
  63     def dropped(self, item, exception, response, spider):
  64         return {
  65             'level': logging.WARNING,
  66             'msg': DROPPEDMSG,
  67             'args': {
  68                 'exception': exception,
  69                 'item': item,
  70             }
  71         }
  72 
  73     @classmethod
  74     def from_crawler(cls, crawler):
  75         return cls()
  76
  ```
  --- 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/scrapy/logformatter.py b/scrapy/logformatter.py
  --- a/scrapy/logformatter.py
  +++ b/scrapy/logformatter.py
  @@ -43,6 +43,8 @@
                   'request_flags' : request_flags,
                   'referer': referer_str(request),
                   'response_flags': response_flags,
  +                # backward compatibility with Scrapy logformatter below 1.4 version
  +                'flags': response_flags
               }
           }
  
verification_info: {"golden_diff": "diff --git a/scrapy/logformatter.py b/scrapy/logformatter.py\n--- a/scrapy/logformatter.py\n+++ b/scrapy/logformatter.py\n@@ -43,6 +43,8 @@\n                 'request_flags' : request_flags,\n                 'referer': referer_str(request),\n                 'response_flags': response_flags,\n+                # backward compatibility with Scrapy logformatter below 1.4 version\n+                'flags': response_flags\n             }\n         }\n", "issue": "After adding request flags subclasses of logformatter that rely on 'flags' format string are broken\n#2082 added flags to request but it also renamed formatting string key from flags to response_flags/request_flags\r\n```\r\nCRAWLEDMSG = u\"Crawled (%(status)s) %(request)s (referer: %(referer)s)%(flags)s\"\r\n +CRAWLEDMSG = u\"Crawled (%(status)s) %(request)s%(request_flags)s (referer: %(referer)s)%(response_flags)s\" \r\n```\r\n\r\nScrapy allows you to override logformatter and this is what I have in my project. I have logformatter looking rouhgly like this\r\n\r\n\r\n```python\r\n# dirbot/logf.py\r\nfrom scrapy.logformatter import LogFormatter\r\n\r\n\r\nclass CustomLogFormatter(LogFormatter):\r\n    def crawled(self, request, response, spider):\r\n        kwargs = super(CustomLogFormatter, self).crawled(\r\n            request, response, spider)\r\n        kwargs['msg'] = (\r\n            u\"Crawled (%(status)s) %(request)s \"\r\n            u\"(referer: %(referer)s, latency: %(latency).2f s)%(flags)s\"\r\n        )\r\n        kwargs['args']['latency'] = response.meta.get('download_latency', 0)\r\n        return kwargs\r\n```\r\n\r\nnow if you enable it in settings `LOG_FORMATTER = 'dirbot.logf.CustomLogFormatter'\r\n` and  try to run it with recent master you'll get KeyError\r\n\r\n```\r\n2017-03-13 14:15:26 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023\r\nTraceback (most recent call last):\r\n  File \"/usr/lib/python2.7/logging/__init__.py\", line 851, in emit\r\n    msg = self.format(record)\r\n  File \"/usr/lib/python2.7/logging/__init__.py\", line 724, in format\r\n    return fmt.format(record)\r\n  File \"/usr/lib/python2.7/logging/__init__.py\", line 464, in format\r\n    record.message = record.getMessage()\r\n  File \"/usr/lib/python2.7/logging/__init__.py\", line 328, in getMessage\r\n    msg = msg % self.args\r\nKeyError: u'flags'\r\nLogged from file engine.py, line 238\r\nTraceback (most recent call last):\r\n  File \"/usr/lib/python2.7/logging/__init__.py\", line 851, in emit\r\n    msg = self.format(record)\r\n  File \"/usr/lib/python2.7/logging/__init__.py\", line 724, in format\r\n    return fmt.format(record)\r\n  File \"/usr/lib/python2.7/logging/__init__.py\", line 464, in format\r\n    record.message = record.getMessage()\r\n  File \"/usr/lib/python2.7/logging/__init__.py\", line 328, in getMessage\r\n    msg = msg % self.args\r\nKeyError: u'flags'\r\nLogged from file engine.py, line 238\r\n2017-03-13 14:15:27 [scrapy.core.scraper] DEBUG: Scraped from <200 http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/>\r\n```\r\n\r\nSo this change that renamed `flags` to `response_flags/request_flags` seems backward incompatible. \n", "before_files": [{"content": "import os\nimport logging\n\nfrom twisted.python.failure import Failure\n\nfrom scrapy.utils.request import referer_str\n\nSCRAPEDMSG = u\"Scraped from %(src)s\" + os.linesep + \"%(item)s\"\nDROPPEDMSG = u\"Dropped: %(exception)s\" + os.linesep + \"%(item)s\"\nCRAWLEDMSG = u\"Crawled (%(status)s) %(request)s%(request_flags)s (referer: %(referer)s)%(response_flags)s\"\n\n\nclass LogFormatter(object):\n    \"\"\"Class for generating log messages for different actions.\n\n    All methods must return a dictionary listing the parameters `level`, `msg`\n    and `args` which are going to be used for constructing the log message when\n    calling logging.log.\n\n    Dictionary keys for the method outputs:\n        * `level` should be the log level for that action, you can use those\n        from the python logging library: logging.DEBUG, logging.INFO,\n        logging.WARNING, logging.ERROR and logging.CRITICAL.\n\n        * `msg` should be a string that can contain different formatting\n        placeholders. This string, formatted with the provided `args`, is going\n        to be the log message for that action.\n\n        * `args` should be a tuple or dict with the formatting placeholders for\n        `msg`.  The final log message is computed as output['msg'] %\n        output['args'].\n    \"\"\"\n\n    def crawled(self, request, response, spider):\n        request_flags = ' %s' % str(request.flags) if request.flags else ''\n        response_flags = ' %s' % str(response.flags) if response.flags else ''\n        return {\n            'level': logging.DEBUG,\n            'msg': CRAWLEDMSG,\n            'args': {\n                'status': response.status,\n                'request': request,\n                'request_flags' : request_flags,\n                'referer': referer_str(request),\n                'response_flags': response_flags,\n            }\n        }\n\n    def scraped(self, item, response, spider):\n        if isinstance(response, Failure):\n            src = response.getErrorMessage()\n        else:\n            src = response\n        return {\n            'level': logging.DEBUG,\n            'msg': SCRAPEDMSG,\n            'args': {\n                'src': src,\n                'item': item,\n            }\n        }\n\n    def dropped(self, item, exception, response, spider):\n        return {\n            'level': logging.WARNING,\n            'msg': DROPPEDMSG,\n            'args': {\n                'exception': exception,\n                'item': item,\n            }\n        }\n\n    @classmethod\n    def from_crawler(cls, crawler):\n        return cls()\n", "path": "scrapy/logformatter.py"}], "after_files": [{"content": "import os\nimport logging\n\nfrom twisted.python.failure import Failure\n\nfrom scrapy.utils.request import referer_str\n\nSCRAPEDMSG = u\"Scraped from %(src)s\" + os.linesep + \"%(item)s\"\nDROPPEDMSG = u\"Dropped: %(exception)s\" + os.linesep + \"%(item)s\"\nCRAWLEDMSG = u\"Crawled (%(status)s) %(request)s%(request_flags)s (referer: %(referer)s)%(response_flags)s\"\n\n\nclass LogFormatter(object):\n    \"\"\"Class for generating log messages for different actions.\n\n    All methods must return a dictionary listing the parameters `level`, `msg`\n    and `args` which are going to be used for constructing the log message when\n    calling logging.log.\n\n    Dictionary keys for the method outputs:\n        * `level` should be the log level for that action, you can use those\n        from the python logging library: logging.DEBUG, logging.INFO,\n        logging.WARNING, logging.ERROR and logging.CRITICAL.\n\n        * `msg` should be a string that can contain different formatting\n        placeholders. This string, formatted with the provided `args`, is going\n        to be the log message for that action.\n\n        * `args` should be a tuple or dict with the formatting placeholders for\n        `msg`.  The final log message is computed as output['msg'] %\n        output['args'].\n    \"\"\"\n\n    def crawled(self, request, response, spider):\n        request_flags = ' %s' % str(request.flags) if request.flags else ''\n        response_flags = ' %s' % str(response.flags) if response.flags else ''\n        return {\n            'level': logging.DEBUG,\n            'msg': CRAWLEDMSG,\n            'args': {\n                'status': response.status,\n                'request': request,\n                'request_flags' : request_flags,\n                'referer': referer_str(request),\n                'response_flags': response_flags,\n                # backward compatibility with Scrapy logformatter below 1.4 version\n                'flags': response_flags\n            }\n        }\n\n    def scraped(self, item, response, spider):\n        if isinstance(response, Failure):\n            src = response.getErrorMessage()\n        else:\n            src = response\n        return {\n            'level': logging.DEBUG,\n            'msg': SCRAPEDMSG,\n            'args': {\n                'src': src,\n                'item': item,\n            }\n        }\n\n    def dropped(self, item, exception, response, spider):\n        return {\n            'level': logging.WARNING,\n            'msg': DROPPEDMSG,\n            'args': {\n                'exception': exception,\n                'item': item,\n            }\n        }\n\n    @classmethod\n    def from_crawler(cls, crawler):\n        return cls()\n", "path": "scrapy/logformatter.py"}]}