We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Install Python3 via EPEL on CentOS6 with letsencrypt-auto?
CentOS 6 ships with Python 2.6 by default, which isn't 100% stably supported by letsencrypt, and which the Python community at large is trying to drop support for. But there's good news! CentOS has support for Software Collections which make it possible to install Python 2.7 in parallel: https://www.softwarecollections.org/en/scls/rhscl/python27/

Would it make sense for `letsencrypt-auto` to just install a Python 2.7, in addition to all the other packages it provides, in order to a) ensure users always get a fully functional environment, b) help encourage folks to move to Python 2.7


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `letsencrypt-auto-source/pieces/fetch.py`
Content:
```
1 """Do downloading and JSON parsing without additional dependencies. ::
2 
3     # Print latest released version of LE to stdout:
4     python fetch.py --latest-version
5 
6     # Download letsencrypt-auto script from git tag v1.2.3 into the folder I'm
7     # in, and make sure its signature verifies:
8     python fetch.py --le-auto-script v1.2.3
9 
10 On failure, return non-zero.
11 
12 """
13 
14 from __future__ import print_function
15 
16 from distutils.version import LooseVersion
17 from json import loads
18 from os import devnull, environ
19 from os.path import dirname, join
20 import re
21 from subprocess import check_call, CalledProcessError
22 from sys import argv, exit
23 from urllib2 import build_opener, HTTPHandler, HTTPSHandler
24 from urllib2 import HTTPError, URLError
25 
26 PUBLIC_KEY = environ.get('LE_AUTO_PUBLIC_KEY', """-----BEGIN PUBLIC KEY-----
27 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6MR8W/galdxnpGqBsYbq
28 OzQb2eyW15YFjDDEMI0ZOzt8f504obNs920lDnpPD2/KqgsfjOgw2K7xWDJIj/18
29 xUvWPk3LDkrnokNiRkA3KOx3W6fHycKL+zID7zy+xZYBuh2fLyQtWV1VGQ45iNRp
30 9+Zo7rH86cdfgkdnWTlNSHyTLW9NbXvyv/E12bppPcEvgCTAQXgnDVJ0/sqmeiij
31 n9tTFh03aM+R2V/21h8aTraAS24qiPCz6gkmYGC8yr6mglcnNoYbsLNYZ69zF1XH
32 cXPduCPdPdfLlzVlKK1/U7hkA28eG3BIAMh6uJYBRJTpiGgaGdPd7YekUB8S6cy+
33 CQIDAQAB
34 -----END PUBLIC KEY-----
35 """)
36 
37 class ExpectedError(Exception):
38     """A novice-readable exception that also carries the original exception for
39     debugging"""
40 
41 
42 class HttpsGetter(object):
43     def __init__(self):
44         """Build an HTTPS opener."""
45         # Based on pip 1.4.1's URLOpener
46         # This verifies certs on only Python >=2.7.9.
47         self._opener = build_opener(HTTPSHandler())
48         # Strip out HTTPHandler to prevent MITM spoof:
49         for handler in self._opener.handlers:
50             if isinstance(handler, HTTPHandler):
51                 self._opener.handlers.remove(handler)
52 
53     def get(self, url):
54         """Return the document contents pointed to by an HTTPS URL.
55 
56         If something goes wrong (404, timeout, etc.), raise ExpectedError.
57 
58         """
59         try:
60             # socket module docs say default timeout is None: that is, no
61             # timeout
62             return self._opener.open(url, timeout=30).read()
63         except (HTTPError, IOError) as exc:
64             raise ExpectedError("Couldn't download %s." % url, exc)
65 
66 
67 def write(contents, dir, filename):
68     """Write something to a file in a certain directory."""
69     with open(join(dir, filename), 'w') as file:
70         file.write(contents)
71 
72 
73 def latest_stable_version(get):
74     """Return the latest stable release of letsencrypt."""
75     metadata = loads(get(
76         environ.get('LE_AUTO_JSON_URL',
77                     'https://pypi.python.org/pypi/certbot/json')))
78     # metadata['info']['version'] actually returns the latest of any kind of
79     # release release, contrary to https://wiki.python.org/moin/PyPIJSON.
80     # The regex is a sufficient regex for picking out prereleases for most
81     # packages, LE included.
82     return str(max(LooseVersion(r) for r
83                    in metadata['releases'].iterkeys()
84                    if re.match('^[0-9.]+$', r)))
85 
86 
87 def verified_new_le_auto(get, tag, temp_dir):
88     """Return the path to a verified, up-to-date letsencrypt-auto script.
89 
90     If the download's signature does not verify or something else goes wrong
91     with the verification process, raise ExpectedError.
92 
93     """
94     le_auto_dir = environ.get(
95         'LE_AUTO_DIR_TEMPLATE',
96         'https://raw.githubusercontent.com/certbot/certbot/%s/'
97         'letsencrypt-auto-source/') % tag
98     write(get(le_auto_dir + 'letsencrypt-auto'), temp_dir, 'letsencrypt-auto')
99     write(get(le_auto_dir + 'letsencrypt-auto.sig'), temp_dir, 'letsencrypt-auto.sig')
100     write(PUBLIC_KEY, temp_dir, 'public_key.pem')
101     try:
102         with open(devnull, 'w') as dev_null:
103             check_call(['openssl', 'dgst', '-sha256', '-verify',
104                         join(temp_dir, 'public_key.pem'),
105                         '-signature',
106                         join(temp_dir, 'letsencrypt-auto.sig'),
107                         join(temp_dir, 'letsencrypt-auto')],
108                        stdout=dev_null,
109                        stderr=dev_null)
110     except CalledProcessError as exc:
111         raise ExpectedError("Couldn't verify signature of downloaded "
112                             "certbot-auto.", exc)
113 
114 
115 def main():
116     get = HttpsGetter().get
117     flag = argv[1]
118     try:
119         if flag == '--latest-version':
120             print(latest_stable_version(get))
121         elif flag == '--le-auto-script':
122             tag = argv[2]
123             verified_new_le_auto(get, tag, dirname(argv[0]))
124     except ExpectedError as exc:
125         print(exc.args[0], exc.args[1])
126         return 1
127     else:
128         return 0
129 
130 
131 if __name__ == '__main__':
132     exit(main())
133
```
--- 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/letsencrypt-auto-source/pieces/fetch.py b/letsencrypt-auto-source/pieces/fetch.py
--- a/letsencrypt-auto-source/pieces/fetch.py
+++ b/letsencrypt-auto-source/pieces/fetch.py
@@ -11,17 +11,22 @@
 
 """
 
-from __future__ import print_function
+from __future__ import print_function, unicode_literals
 
 from distutils.version import LooseVersion
 from json import loads
 from os import devnull, environ
 from os.path import dirname, join
 import re
+import ssl
 from subprocess import check_call, CalledProcessError
 from sys import argv, exit
-from urllib2 import build_opener, HTTPHandler, HTTPSHandler
-from urllib2 import HTTPError, URLError
+try:
+    from urllib2 import build_opener, HTTPHandler, HTTPSHandler
+    from urllib2 import HTTPError, URLError
+except ImportError:
+    from urllib.request import build_opener, HTTPHandler, HTTPSHandler
+    from urllib.error import HTTPError, URLError
 
 PUBLIC_KEY = environ.get('LE_AUTO_PUBLIC_KEY', """-----BEGIN PUBLIC KEY-----
 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6MR8W/galdxnpGqBsYbq
@@ -43,8 +48,11 @@
     def __init__(self):
         """Build an HTTPS opener."""
         # Based on pip 1.4.1's URLOpener
-        # This verifies certs on only Python >=2.7.9.
-        self._opener = build_opener(HTTPSHandler())
+        # This verifies certs on only Python >=2.7.9, and when NO_CERT_VERIFY isn't set.
+        if environ.get('NO_CERT_VERIFY') == '1' and hasattr(ssl, 'SSLContext'):
+            self._opener = build_opener(HTTPSHandler(context=create_CERT_NONE_context()))
+        else:
+            self._opener = build_opener(HTTPSHandler())
         # Strip out HTTPHandler to prevent MITM spoof:
         for handler in self._opener.handlers:
             if isinstance(handler, HTTPHandler):
@@ -66,7 +74,7 @@
 
 def write(contents, dir, filename):
     """Write something to a file in a certain directory."""
-    with open(join(dir, filename), 'w') as file:
+    with open(join(dir, filename), 'wb') as file:
         file.write(contents)
 
 
@@ -74,13 +82,13 @@
     """Return the latest stable release of letsencrypt."""
     metadata = loads(get(
         environ.get('LE_AUTO_JSON_URL',
-                    'https://pypi.python.org/pypi/certbot/json')))
+                    'https://pypi.python.org/pypi/certbot/json')).decode('UTF-8'))
     # metadata['info']['version'] actually returns the latest of any kind of
     # release release, contrary to https://wiki.python.org/moin/PyPIJSON.
     # The regex is a sufficient regex for picking out prereleases for most
     # packages, LE included.
     return str(max(LooseVersion(r) for r
-                   in metadata['releases'].iterkeys()
+                   in iter(metadata['releases'].keys())
                    if re.match('^[0-9.]+$', r)))
 
 
@@ -97,7 +105,7 @@
         'letsencrypt-auto-source/') % tag
     write(get(le_auto_dir + 'letsencrypt-auto'), temp_dir, 'letsencrypt-auto')
     write(get(le_auto_dir + 'letsencrypt-auto.sig'), temp_dir, 'letsencrypt-auto.sig')
-    write(PUBLIC_KEY, temp_dir, 'public_key.pem')
+    write(PUBLIC_KEY.encode('UTF-8'), temp_dir, 'public_key.pem')
     try:
         with open(devnull, 'w') as dev_null:
             check_call(['openssl', 'dgst', '-sha256', '-verify',
@@ -112,6 +120,14 @@
                             "certbot-auto.", exc)
 
 
+def create_CERT_NONE_context():
+    """Create a SSLContext object to not check hostname."""
+    # PROTOCOL_TLS isn't available before 2.7.13 but this code is for 2.7.9+, so use this.
+    context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
+    context.verify_mode = ssl.CERT_NONE
+    return context
+
+
 def main():
     get = HttpsGetter().get
     flag = argv[1]

{"golden_diff": "diff --git a/letsencrypt-auto-source/pieces/fetch.py b/letsencrypt-auto-source/pieces/fetch.py\n--- a/letsencrypt-auto-source/pieces/fetch.py\n+++ b/letsencrypt-auto-source/pieces/fetch.py\n@@ -11,17 +11,22 @@\n \n \"\"\"\n \n-from __future__ import print_function\n+from __future__ import print_function, unicode_literals\n \n from distutils.version import LooseVersion\n from json import loads\n from os import devnull, environ\n from os.path import dirname, join\n import re\n+import ssl\n from subprocess import check_call, CalledProcessError\n from sys import argv, exit\n-from urllib2 import build_opener, HTTPHandler, HTTPSHandler\n-from urllib2 import HTTPError, URLError\n+try:\n+    from urllib2 import build_opener, HTTPHandler, HTTPSHandler\n+    from urllib2 import HTTPError, URLError\n+except ImportError:\n+    from urllib.request import build_opener, HTTPHandler, HTTPSHandler\n+    from urllib.error import HTTPError, URLError\n \n PUBLIC_KEY = environ.get('LE_AUTO_PUBLIC_KEY', \"\"\"-----BEGIN PUBLIC KEY-----\n MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6MR8W/galdxnpGqBsYbq\n@@ -43,8 +48,11 @@\n     def __init__(self):\n         \"\"\"Build an HTTPS opener.\"\"\"\n         # Based on pip 1.4.1's URLOpener\n-        # This verifies certs on only Python >=2.7.9.\n-        self._opener = build_opener(HTTPSHandler())\n+        # This verifies certs on only Python >=2.7.9, and when NO_CERT_VERIFY isn't set.\n+        if environ.get('NO_CERT_VERIFY') == '1' and hasattr(ssl, 'SSLContext'):\n+            self._opener = build_opener(HTTPSHandler(context=create_CERT_NONE_context()))\n+        else:\n+            self._opener = build_opener(HTTPSHandler())\n         # Strip out HTTPHandler to prevent MITM spoof:\n         for handler in self._opener.handlers:\n             if isinstance(handler, HTTPHandler):\n@@ -66,7 +74,7 @@\n \n def write(contents, dir, filename):\n     \"\"\"Write something to a file in a certain directory.\"\"\"\n-    with open(join(dir, filename), 'w') as file:\n+    with open(join(dir, filename), 'wb') as file:\n         file.write(contents)\n \n \n@@ -74,13 +82,13 @@\n     \"\"\"Return the latest stable release of letsencrypt.\"\"\"\n     metadata = loads(get(\n         environ.get('LE_AUTO_JSON_URL',\n-                    'https://pypi.python.org/pypi/certbot/json')))\n+                    'https://pypi.python.org/pypi/certbot/json')).decode('UTF-8'))\n     # metadata['info']['version'] actually returns the latest of any kind of\n     # release release, contrary to https://wiki.python.org/moin/PyPIJSON.\n     # The regex is a sufficient regex for picking out prereleases for most\n     # packages, LE included.\n     return str(max(LooseVersion(r) for r\n-                   in metadata['releases'].iterkeys()\n+                   in iter(metadata['releases'].keys())\n                    if re.match('^[0-9.]+$', r)))\n \n \n@@ -97,7 +105,7 @@\n         'letsencrypt-auto-source/') % tag\n     write(get(le_auto_dir + 'letsencrypt-auto'), temp_dir, 'letsencrypt-auto')\n     write(get(le_auto_dir + 'letsencrypt-auto.sig'), temp_dir, 'letsencrypt-auto.sig')\n-    write(PUBLIC_KEY, temp_dir, 'public_key.pem')\n+    write(PUBLIC_KEY.encode('UTF-8'), temp_dir, 'public_key.pem')\n     try:\n         with open(devnull, 'w') as dev_null:\n             check_call(['openssl', 'dgst', '-sha256', '-verify',\n@@ -112,6 +120,14 @@\n                             \"certbot-auto.\", exc)\n \n \n+def create_CERT_NONE_context():\n+    \"\"\"Create a SSLContext object to not check hostname.\"\"\"\n+    # PROTOCOL_TLS isn't available before 2.7.13 but this code is for 2.7.9+, so use this.\n+    context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)\n+    context.verify_mode = ssl.CERT_NONE\n+    return context\n+\n+\n def main():\n     get = HttpsGetter().get\n     flag = argv[1]\n", "issue": "Install Python3 via EPEL on CentOS6 with letsencrypt-auto?\nCentOS 6 ships with Python 2.6 by default, which isn't 100% stably supported by letsencrypt, and which the Python community at large is trying to drop support for. But there's good news! CentOS has support for Software Collections which make it possible to install Python 2.7 in parallel: https://www.softwarecollections.org/en/scls/rhscl/python27/\n\nWould it make sense for `letsencrypt-auto` to just install a Python 2.7, in addition to all the other packages it provides, in order to a) ensure users always get a fully functional environment, b) help encourage folks to move to Python 2.7\n\n", "before_files": [{"content": "\"\"\"Do downloading and JSON parsing without additional dependencies. ::\n\n    # Print latest released version of LE to stdout:\n    python fetch.py --latest-version\n\n    # Download letsencrypt-auto script from git tag v1.2.3 into the folder I'm\n    # in, and make sure its signature verifies:\n    python fetch.py --le-auto-script v1.2.3\n\nOn failure, return non-zero.\n\n\"\"\"\n\nfrom __future__ import print_function\n\nfrom distutils.version import LooseVersion\nfrom json import loads\nfrom os import devnull, environ\nfrom os.path import dirname, join\nimport re\nfrom subprocess import check_call, CalledProcessError\nfrom sys import argv, exit\nfrom urllib2 import build_opener, HTTPHandler, HTTPSHandler\nfrom urllib2 import HTTPError, URLError\n\nPUBLIC_KEY = environ.get('LE_AUTO_PUBLIC_KEY', \"\"\"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6MR8W/galdxnpGqBsYbq\nOzQb2eyW15YFjDDEMI0ZOzt8f504obNs920lDnpPD2/KqgsfjOgw2K7xWDJIj/18\nxUvWPk3LDkrnokNiRkA3KOx3W6fHycKL+zID7zy+xZYBuh2fLyQtWV1VGQ45iNRp\n9+Zo7rH86cdfgkdnWTlNSHyTLW9NbXvyv/E12bppPcEvgCTAQXgnDVJ0/sqmeiij\nn9tTFh03aM+R2V/21h8aTraAS24qiPCz6gkmYGC8yr6mglcnNoYbsLNYZ69zF1XH\ncXPduCPdPdfLlzVlKK1/U7hkA28eG3BIAMh6uJYBRJTpiGgaGdPd7YekUB8S6cy+\nCQIDAQAB\n-----END PUBLIC KEY-----\n\"\"\")\n\nclass ExpectedError(Exception):\n    \"\"\"A novice-readable exception that also carries the original exception for\n    debugging\"\"\"\n\n\nclass HttpsGetter(object):\n    def __init__(self):\n        \"\"\"Build an HTTPS opener.\"\"\"\n        # Based on pip 1.4.1's URLOpener\n        # This verifies certs on only Python >=2.7.9.\n        self._opener = build_opener(HTTPSHandler())\n        # Strip out HTTPHandler to prevent MITM spoof:\n        for handler in self._opener.handlers:\n            if isinstance(handler, HTTPHandler):\n                self._opener.handlers.remove(handler)\n\n    def get(self, url):\n        \"\"\"Return the document contents pointed to by an HTTPS URL.\n\n        If something goes wrong (404, timeout, etc.), raise ExpectedError.\n\n        \"\"\"\n        try:\n            # socket module docs say default timeout is None: that is, no\n            # timeout\n            return self._opener.open(url, timeout=30).read()\n        except (HTTPError, IOError) as exc:\n            raise ExpectedError(\"Couldn't download %s.\" % url, exc)\n\n\ndef write(contents, dir, filename):\n    \"\"\"Write something to a file in a certain directory.\"\"\"\n    with open(join(dir, filename), 'w') as file:\n        file.write(contents)\n\n\ndef latest_stable_version(get):\n    \"\"\"Return the latest stable release of letsencrypt.\"\"\"\n    metadata = loads(get(\n        environ.get('LE_AUTO_JSON_URL',\n                    'https://pypi.python.org/pypi/certbot/json')))\n    # metadata['info']['version'] actually returns the latest of any kind of\n    # release release, contrary to https://wiki.python.org/moin/PyPIJSON.\n    # The regex is a sufficient regex for picking out prereleases for most\n    # packages, LE included.\n    return str(max(LooseVersion(r) for r\n                   in metadata['releases'].iterkeys()\n                   if re.match('^[0-9.]+$', r)))\n\n\ndef verified_new_le_auto(get, tag, temp_dir):\n    \"\"\"Return the path to a verified, up-to-date letsencrypt-auto script.\n\n    If the download's signature does not verify or something else goes wrong\n    with the verification process, raise ExpectedError.\n\n    \"\"\"\n    le_auto_dir = environ.get(\n        'LE_AUTO_DIR_TEMPLATE',\n        'https://raw.githubusercontent.com/certbot/certbot/%s/'\n        'letsencrypt-auto-source/') % tag\n    write(get(le_auto_dir + 'letsencrypt-auto'), temp_dir, 'letsencrypt-auto')\n    write(get(le_auto_dir + 'letsencrypt-auto.sig'), temp_dir, 'letsencrypt-auto.sig')\n    write(PUBLIC_KEY, temp_dir, 'public_key.pem')\n    try:\n        with open(devnull, 'w') as dev_null:\n            check_call(['openssl', 'dgst', '-sha256', '-verify',\n                        join(temp_dir, 'public_key.pem'),\n                        '-signature',\n                        join(temp_dir, 'letsencrypt-auto.sig'),\n                        join(temp_dir, 'letsencrypt-auto')],\n                       stdout=dev_null,\n                       stderr=dev_null)\n    except CalledProcessError as exc:\n        raise ExpectedError(\"Couldn't verify signature of downloaded \"\n                            \"certbot-auto.\", exc)\n\n\ndef main():\n    get = HttpsGetter().get\n    flag = argv[1]\n    try:\n        if flag == '--latest-version':\n            print(latest_stable_version(get))\n        elif flag == '--le-auto-script':\n            tag = argv[2]\n            verified_new_le_auto(get, tag, dirname(argv[0]))\n    except ExpectedError as exc:\n        print(exc.args[0], exc.args[1])\n        return 1\n    else:\n        return 0\n\n\nif __name__ == '__main__':\n    exit(main())\n", "path": "letsencrypt-auto-source/pieces/fetch.py"}], "after_files": [{"content": "\"\"\"Do downloading and JSON parsing without additional dependencies. ::\n\n    # Print latest released version of LE to stdout:\n    python fetch.py --latest-version\n\n    # Download letsencrypt-auto script from git tag v1.2.3 into the folder I'm\n    # in, and make sure its signature verifies:\n    python fetch.py --le-auto-script v1.2.3\n\nOn failure, return non-zero.\n\n\"\"\"\n\nfrom __future__ import print_function, unicode_literals\n\nfrom distutils.version import LooseVersion\nfrom json import loads\nfrom os import devnull, environ\nfrom os.path import dirname, join\nimport re\nimport ssl\nfrom subprocess import check_call, CalledProcessError\nfrom sys import argv, exit\ntry:\n    from urllib2 import build_opener, HTTPHandler, HTTPSHandler\n    from urllib2 import HTTPError, URLError\nexcept ImportError:\n    from urllib.request import build_opener, HTTPHandler, HTTPSHandler\n    from urllib.error import HTTPError, URLError\n\nPUBLIC_KEY = environ.get('LE_AUTO_PUBLIC_KEY', \"\"\"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6MR8W/galdxnpGqBsYbq\nOzQb2eyW15YFjDDEMI0ZOzt8f504obNs920lDnpPD2/KqgsfjOgw2K7xWDJIj/18\nxUvWPk3LDkrnokNiRkA3KOx3W6fHycKL+zID7zy+xZYBuh2fLyQtWV1VGQ45iNRp\n9+Zo7rH86cdfgkdnWTlNSHyTLW9NbXvyv/E12bppPcEvgCTAQXgnDVJ0/sqmeiij\nn9tTFh03aM+R2V/21h8aTraAS24qiPCz6gkmYGC8yr6mglcnNoYbsLNYZ69zF1XH\ncXPduCPdPdfLlzVlKK1/U7hkA28eG3BIAMh6uJYBRJTpiGgaGdPd7YekUB8S6cy+\nCQIDAQAB\n-----END PUBLIC KEY-----\n\"\"\")\n\nclass ExpectedError(Exception):\n    \"\"\"A novice-readable exception that also carries the original exception for\n    debugging\"\"\"\n\n\nclass HttpsGetter(object):\n    def __init__(self):\n        \"\"\"Build an HTTPS opener.\"\"\"\n        # Based on pip 1.4.1's URLOpener\n        # This verifies certs on only Python >=2.7.9, and when NO_CERT_VERIFY isn't set.\n        if environ.get('NO_CERT_VERIFY') == '1' and hasattr(ssl, 'SSLContext'):\n            self._opener = build_opener(HTTPSHandler(context=create_CERT_NONE_context()))\n        else:\n            self._opener = build_opener(HTTPSHandler())\n        # Strip out HTTPHandler to prevent MITM spoof:\n        for handler in self._opener.handlers:\n            if isinstance(handler, HTTPHandler):\n                self._opener.handlers.remove(handler)\n\n    def get(self, url):\n        \"\"\"Return the document contents pointed to by an HTTPS URL.\n\n        If something goes wrong (404, timeout, etc.), raise ExpectedError.\n\n        \"\"\"\n        try:\n            # socket module docs say default timeout is None: that is, no\n            # timeout\n            return self._opener.open(url, timeout=30).read()\n        except (HTTPError, IOError) as exc:\n            raise ExpectedError(\"Couldn't download %s.\" % url, exc)\n\n\ndef write(contents, dir, filename):\n    \"\"\"Write something to a file in a certain directory.\"\"\"\n    with open(join(dir, filename), 'wb') as file:\n        file.write(contents)\n\n\ndef latest_stable_version(get):\n    \"\"\"Return the latest stable release of letsencrypt.\"\"\"\n    metadata = loads(get(\n        environ.get('LE_AUTO_JSON_URL',\n                    'https://pypi.python.org/pypi/certbot/json')).decode('UTF-8'))\n    # metadata['info']['version'] actually returns the latest of any kind of\n    # release release, contrary to https://wiki.python.org/moin/PyPIJSON.\n    # The regex is a sufficient regex for picking out prereleases for most\n    # packages, LE included.\n    return str(max(LooseVersion(r) for r\n                   in iter(metadata['releases'].keys())\n                   if re.match('^[0-9.]+$', r)))\n\n\ndef verified_new_le_auto(get, tag, temp_dir):\n    \"\"\"Return the path to a verified, up-to-date letsencrypt-auto script.\n\n    If the download's signature does not verify or something else goes wrong\n    with the verification process, raise ExpectedError.\n\n    \"\"\"\n    le_auto_dir = environ.get(\n        'LE_AUTO_DIR_TEMPLATE',\n        'https://raw.githubusercontent.com/certbot/certbot/%s/'\n        'letsencrypt-auto-source/') % tag\n    write(get(le_auto_dir + 'letsencrypt-auto'), temp_dir, 'letsencrypt-auto')\n    write(get(le_auto_dir + 'letsencrypt-auto.sig'), temp_dir, 'letsencrypt-auto.sig')\n    write(PUBLIC_KEY.encode('UTF-8'), temp_dir, 'public_key.pem')\n    try:\n        with open(devnull, 'w') as dev_null:\n            check_call(['openssl', 'dgst', '-sha256', '-verify',\n                        join(temp_dir, 'public_key.pem'),\n                        '-signature',\n                        join(temp_dir, 'letsencrypt-auto.sig'),\n                        join(temp_dir, 'letsencrypt-auto')],\n                       stdout=dev_null,\n                       stderr=dev_null)\n    except CalledProcessError as exc:\n        raise ExpectedError(\"Couldn't verify signature of downloaded \"\n                            \"certbot-auto.\", exc)\n\n\ndef create_CERT_NONE_context():\n    \"\"\"Create a SSLContext object to not check hostname.\"\"\"\n    # PROTOCOL_TLS isn't available before 2.7.13 but this code is for 2.7.9+, so use this.\n    context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)\n    context.verify_mode = ssl.CERT_NONE\n    return context\n\n\ndef main():\n    get = HttpsGetter().get\n    flag = argv[1]\n    try:\n        if flag == '--latest-version':\n            print(latest_stable_version(get))\n        elif flag == '--le-auto-script':\n            tag = argv[2]\n            verified_new_le_auto(get, tag, dirname(argv[0]))\n    except ExpectedError as exc:\n        print(exc.args[0], exc.args[1])\n        return 1\n    else:\n        return 0\n\n\nif __name__ == '__main__':\n    exit(main())\n", "path": "letsencrypt-auto-source/pieces/fetch.py"}]}