prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  BrowserLikeContextFactory not available in some conditions
  While tracing the error that lead to #2555 I tried the workaround [mentioned in the documentation](https://doc.scrapy.org/en/latest/topics/settings.html#downloader-clientcontextfactory) without success.
  
  This code lives [incontextfactory.py](https://github.com/scrapy/scrapy/blob/c3411373e8a8ee2786588bdad7be469c69a25e2a/scrapy/core/downloader/contextfactory.py#L63) but was not reachable as the import was failing on my system due to #2555.
  
  This file is a large `try/except` block with many potential points of failure and it's likely to trip other users in the future.
  That said, could this be refactored to provide a fallback for `BrowserLikeContextFactory` or otherwise reduce the scope of the `try/except` to avoid breaking the API?
  
  </issue>
  <code>
  [start of scrapy/core/downloader/contextfactory.py]
  1 from OpenSSL import SSL
  2 from twisted.internet.ssl import ClientContextFactory
  3 
  4 try:
  5 
  6     from zope.interface.declarations import implementer
  7 
  8     # the following should be available from Twisted 14.0.0
  9     from twisted.internet.ssl import (optionsForClientTLS,
  10                                       CertificateOptions,
  11                                       platformTrust)
  12 
  13     from twisted.web.client import BrowserLikePolicyForHTTPS
  14     from twisted.web.iweb import IPolicyForHTTPS
  15 
  16     from scrapy.core.downloader.tls import ScrapyClientTLSOptions, DEFAULT_CIPHERS
  17 
  18 
  19     @implementer(IPolicyForHTTPS)
  20     class ScrapyClientContextFactory(BrowserLikePolicyForHTTPS):
  21         """
  22         Non-peer-certificate verifying HTTPS context factory
  23 
  24         Default OpenSSL method is TLS_METHOD (also called SSLv23_METHOD)
  25         which allows TLS protocol negotiation
  26 
  27         'A TLS/SSL connection established with [this method] may
  28          understand the SSLv3, TLSv1, TLSv1.1 and TLSv1.2 protocols.'
  29         """
  30 
  31         def __init__(self, method=SSL.SSLv23_METHOD, *args, **kwargs):
  32             super(ScrapyClientContextFactory, self).__init__(*args, **kwargs)
  33             self._ssl_method = method
  34 
  35         def getCertificateOptions(self):
  36             # setting verify=True will require you to provide CAs
  37             # to verify against; in other words: it's not that simple
  38 
  39             # backward-compatible SSL/TLS method:
  40             #
  41             # * this will respect `method` attribute in often recommended
  42             #   `ScrapyClientContextFactory` subclass
  43             #   (https://github.com/scrapy/scrapy/issues/1429#issuecomment-131782133)
  44             #
  45             # * getattr() for `_ssl_method` attribute for context factories
  46             #   not calling super(..., self).__init__
  47             return CertificateOptions(verify=False,
  48                         method=getattr(self, 'method',
  49                                        getattr(self, '_ssl_method', None)),
  50                         fixBrokenPeers=True,
  51                         acceptableCiphers=DEFAULT_CIPHERS)
  52 
  53         # kept for old-style HTTP/1.0 downloader context twisted calls,
  54         # e.g. connectSSL()
  55         def getContext(self, hostname=None, port=None):
  56             return self.getCertificateOptions().getContext()
  57 
  58         def creatorForNetloc(self, hostname, port):
  59             return ScrapyClientTLSOptions(hostname.decode("ascii"), self.getContext())
  60 
  61 
  62     @implementer(IPolicyForHTTPS)
  63     class BrowserLikeContextFactory(ScrapyClientContextFactory):
  64         """
  65         Twisted-recommended context factory for web clients.
  66 
  67         Quoting http://twistedmatrix.com/documents/current/api/twisted.web.client.Agent.html:
  68         "The default is to use a BrowserLikePolicyForHTTPS,
  69         so unless you have special requirements you can leave this as-is."
  70 
  71         creatorForNetloc() is the same as BrowserLikePolicyForHTTPS
  72         except this context factory allows setting the TLS/SSL method to use.
  73 
  74         Default OpenSSL method is TLS_METHOD (also called SSLv23_METHOD)
  75         which allows TLS protocol negotiation.
  76         """
  77         def creatorForNetloc(self, hostname, port):
  78 
  79             # trustRoot set to platformTrust() will use the platform's root CAs.
  80             #
  81             # This means that a website like https://www.cacert.org will be rejected
  82             # by default, since CAcert.org CA certificate is seldom shipped.
  83             return optionsForClientTLS(hostname.decode("ascii"),
  84                                        trustRoot=platformTrust(),
  85                                        extraCertificateOptions={
  86                                             'method': self._ssl_method,
  87                                        })
  88 
  89 except ImportError:
  90 
  91     class ScrapyClientContextFactory(ClientContextFactory):
  92         "A SSL context factory which is more permissive against SSL bugs."
  93         # see https://github.com/scrapy/scrapy/issues/82
  94         # and https://github.com/scrapy/scrapy/issues/26
  95         # and https://github.com/scrapy/scrapy/issues/981
  96 
  97         def __init__(self, method=SSL.SSLv23_METHOD):
  98             self.method = method
  99 
  100         def getContext(self, hostname=None, port=None):
  101             ctx = ClientContextFactory.getContext(self)
  102             # Enable all workarounds to SSL bugs as documented by
  103             # http://www.openssl.org/docs/ssl/SSL_CTX_set_options.html
  104             ctx.set_options(SSL.OP_ALL)
  105             return ctx
  106
  [end of scrapy/core/downloader/contextfactory.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/scrapy/core/downloader/contextfactory.py b/scrapy/core/downloader/contextfactory.py
  --- a/scrapy/core/downloader/contextfactory.py
  +++ b/scrapy/core/downloader/contextfactory.py
  @@ -1,15 +1,15 @@
   from OpenSSL import SSL
   from twisted.internet.ssl import ClientContextFactory
   
  -try:
  +from scrapy import twisted_version
  +
  +if twisted_version >= (14, 0, 0):
   
       from zope.interface.declarations import implementer
   
  -    # the following should be available from Twisted 14.0.0
       from twisted.internet.ssl import (optionsForClientTLS,
                                         CertificateOptions,
                                         platformTrust)
  -
       from twisted.web.client import BrowserLikePolicyForHTTPS
       from twisted.web.iweb import IPolicyForHTTPS
   
  @@ -86,7 +86,7 @@
                                               'method': self._ssl_method,
                                          })
   
  -except ImportError:
  +else:
   
       class ScrapyClientContextFactory(ClientContextFactory):
           "A SSL context factory which is more permissive against SSL bugs."
  
verification_info: {"golden_diff": "diff --git a/scrapy/core/downloader/contextfactory.py b/scrapy/core/downloader/contextfactory.py\n--- a/scrapy/core/downloader/contextfactory.py\n+++ b/scrapy/core/downloader/contextfactory.py\n@@ -1,15 +1,15 @@\n from OpenSSL import SSL\n from twisted.internet.ssl import ClientContextFactory\n \n-try:\n+from scrapy import twisted_version\n+\n+if twisted_version >= (14, 0, 0):\n \n     from zope.interface.declarations import implementer\n \n-    # the following should be available from Twisted 14.0.0\n     from twisted.internet.ssl import (optionsForClientTLS,\n                                       CertificateOptions,\n                                       platformTrust)\n-\n     from twisted.web.client import BrowserLikePolicyForHTTPS\n     from twisted.web.iweb import IPolicyForHTTPS\n \n@@ -86,7 +86,7 @@\n                                             'method': self._ssl_method,\n                                        })\n \n-except ImportError:\n+else:\n \n     class ScrapyClientContextFactory(ClientContextFactory):\n         \"A SSL context factory which is more permissive against SSL bugs.\"\n", "issue": "BrowserLikeContextFactory not available in some conditions\nWhile tracing the error that lead to #2555 I tried the workaround [mentioned in the documentation](https://doc.scrapy.org/en/latest/topics/settings.html#downloader-clientcontextfactory) without success.\r\n\r\nThis code lives [incontextfactory.py](https://github.com/scrapy/scrapy/blob/c3411373e8a8ee2786588bdad7be469c69a25e2a/scrapy/core/downloader/contextfactory.py#L63) but was not reachable as the import was failing on my system due to #2555.\r\n\r\nThis file is a large `try/except` block with many potential points of failure and it's likely to trip other users in the future.\r\nThat said, could this be refactored to provide a fallback for `BrowserLikeContextFactory` or otherwise reduce the scope of the `try/except` to avoid breaking the API?\n", "before_files": [{"content": "from OpenSSL import SSL\nfrom twisted.internet.ssl import ClientContextFactory\n\ntry:\n\n    from zope.interface.declarations import implementer\n\n    # the following should be available from Twisted 14.0.0\n    from twisted.internet.ssl import (optionsForClientTLS,\n                                      CertificateOptions,\n                                      platformTrust)\n\n    from twisted.web.client import BrowserLikePolicyForHTTPS\n    from twisted.web.iweb import IPolicyForHTTPS\n\n    from scrapy.core.downloader.tls import ScrapyClientTLSOptions, DEFAULT_CIPHERS\n\n\n    @implementer(IPolicyForHTTPS)\n    class ScrapyClientContextFactory(BrowserLikePolicyForHTTPS):\n        \"\"\"\n        Non-peer-certificate verifying HTTPS context factory\n\n        Default OpenSSL method is TLS_METHOD (also called SSLv23_METHOD)\n        which allows TLS protocol negotiation\n\n        'A TLS/SSL connection established with [this method] may\n         understand the SSLv3, TLSv1, TLSv1.1 and TLSv1.2 protocols.'\n        \"\"\"\n\n        def __init__(self, method=SSL.SSLv23_METHOD, *args, **kwargs):\n            super(ScrapyClientContextFactory, self).__init__(*args, **kwargs)\n            self._ssl_method = method\n\n        def getCertificateOptions(self):\n            # setting verify=True will require you to provide CAs\n            # to verify against; in other words: it's not that simple\n\n            # backward-compatible SSL/TLS method:\n            #\n            # * this will respect `method` attribute in often recommended\n            #   `ScrapyClientContextFactory` subclass\n            #   (https://github.com/scrapy/scrapy/issues/1429#issuecomment-131782133)\n            #\n            # * getattr() for `_ssl_method` attribute for context factories\n            #   not calling super(..., self).__init__\n            return CertificateOptions(verify=False,\n                        method=getattr(self, 'method',\n                                       getattr(self, '_ssl_method', None)),\n                        fixBrokenPeers=True,\n                        acceptableCiphers=DEFAULT_CIPHERS)\n\n        # kept for old-style HTTP/1.0 downloader context twisted calls,\n        # e.g. connectSSL()\n        def getContext(self, hostname=None, port=None):\n            return self.getCertificateOptions().getContext()\n\n        def creatorForNetloc(self, hostname, port):\n            return ScrapyClientTLSOptions(hostname.decode(\"ascii\"), self.getContext())\n\n\n    @implementer(IPolicyForHTTPS)\n    class BrowserLikeContextFactory(ScrapyClientContextFactory):\n        \"\"\"\n        Twisted-recommended context factory for web clients.\n\n        Quoting http://twistedmatrix.com/documents/current/api/twisted.web.client.Agent.html:\n        \"The default is to use a BrowserLikePolicyForHTTPS,\n        so unless you have special requirements you can leave this as-is.\"\n\n        creatorForNetloc() is the same as BrowserLikePolicyForHTTPS\n        except this context factory allows setting the TLS/SSL method to use.\n\n        Default OpenSSL method is TLS_METHOD (also called SSLv23_METHOD)\n        which allows TLS protocol negotiation.\n        \"\"\"\n        def creatorForNetloc(self, hostname, port):\n\n            # trustRoot set to platformTrust() will use the platform's root CAs.\n            #\n            # This means that a website like https://www.cacert.org will be rejected\n            # by default, since CAcert.org CA certificate is seldom shipped.\n            return optionsForClientTLS(hostname.decode(\"ascii\"),\n                                       trustRoot=platformTrust(),\n                                       extraCertificateOptions={\n                                            'method': self._ssl_method,\n                                       })\n\nexcept ImportError:\n\n    class ScrapyClientContextFactory(ClientContextFactory):\n        \"A SSL context factory which is more permissive against SSL bugs.\"\n        # see https://github.com/scrapy/scrapy/issues/82\n        # and https://github.com/scrapy/scrapy/issues/26\n        # and https://github.com/scrapy/scrapy/issues/981\n\n        def __init__(self, method=SSL.SSLv23_METHOD):\n            self.method = method\n\n        def getContext(self, hostname=None, port=None):\n            ctx = ClientContextFactory.getContext(self)\n            # Enable all workarounds to SSL bugs as documented by\n            # http://www.openssl.org/docs/ssl/SSL_CTX_set_options.html\n            ctx.set_options(SSL.OP_ALL)\n            return ctx\n", "path": "scrapy/core/downloader/contextfactory.py"}]}