1
0
mirror of https://github.com/certbot/certbot.git synced 2025-08-06 16:42:41 +03:00

Merge pull request #5605 from certbot/rm-eol-2.6

Drop Python 2.6 and 3.3 support
This commit is contained in:
Brad Warren
2018-02-26 13:34:50 -08:00
committed by GitHub
35 changed files with 180 additions and 252 deletions

View File

@@ -25,16 +25,12 @@ matrix:
addons: addons:
- python: "2.7" - python: "2.7"
env: TOXENV=lint env: TOXENV=lint
- python: "2.6"
env: TOXENV=py26
sudo: required
services: docker
- python: "2.7" - python: "2.7"
env: TOXENV=py27-oldest env: TOXENV=py27-oldest
sudo: required sudo: required
services: docker services: docker
- python: "3.3" - python: "3.4"
env: TOXENV=py33 env: TOXENV=py34
sudo: required sudo: required
services: docker services: docker
- python: "3.6" - python: "3.6"

View File

@@ -10,13 +10,3 @@ supported version: `draft-ietf-acme-01`_.
https://github.com/ietf-wg-acme/acme/tree/draft-ietf-acme-acme-01 https://github.com/ietf-wg-acme/acme/tree/draft-ietf-acme-acme-01
""" """
import sys
import warnings
for (major, minor) in [(2, 6), (3, 3)]:
if sys.version_info[:2] == (major, minor):
warnings.warn(
"Python {0}.{1} support will be dropped in the next release of "
"acme. Please upgrade your Python version.".format(major, minor),
DeprecationWarning,
) #pragma: no cover

View File

@@ -5,7 +5,6 @@ import logging
import os import os
import re import re
import socket import socket
import sys
import OpenSSL import OpenSSL
import josepy as jose import josepy as jose
@@ -132,8 +131,7 @@ def probe_sni(name, host, port=443, timeout=300,
context = OpenSSL.SSL.Context(method) context = OpenSSL.SSL.Context(method)
context.set_timeout(timeout) context.set_timeout(timeout)
socket_kwargs = {} if sys.version_info < (2, 7) else { socket_kwargs = {'source_address': source_address}
'source_address': source_address}
host_protocol_agnostic = None if host == '::' or host == '0' else host host_protocol_agnostic = None if host == '::' or host == '0' else host

View File

@@ -194,9 +194,9 @@ class MakeCSRTest(unittest.TestCase):
self.assertTrue(b'--END CERTIFICATE REQUEST--' in csr_pem) self.assertTrue(b'--END CERTIFICATE REQUEST--' in csr_pem)
csr = OpenSSL.crypto.load_certificate_request( csr = OpenSSL.crypto.load_certificate_request(
OpenSSL.crypto.FILETYPE_PEM, csr_pem) OpenSSL.crypto.FILETYPE_PEM, csr_pem)
# In pyopenssl 0.13 (used with TOXENV=py26-oldest and py27-oldest), csr # In pyopenssl 0.13 (used with TOXENV=py27-oldest), csr objects don't
# objects don't have a get_extensions() method, so we skip this test if # have a get_extensions() method, so we skip this test if the method
# the method isn't available. # isn't available.
if hasattr(csr, 'get_extensions'): if hasattr(csr, 'get_extensions'):
self.assertEquals(len(csr.get_extensions()), 1) self.assertEquals(len(csr.get_extensions()), 1)
self.assertEquals(csr.get_extensions()[0].get_data(), self.assertEquals(csr.get_extensions()[0].get_data(),
@@ -212,9 +212,9 @@ class MakeCSRTest(unittest.TestCase):
csr = OpenSSL.crypto.load_certificate_request( csr = OpenSSL.crypto.load_certificate_request(
OpenSSL.crypto.FILETYPE_PEM, csr_pem) OpenSSL.crypto.FILETYPE_PEM, csr_pem)
# In pyopenssl 0.13 (used with TOXENV=py26-oldest and py27-oldest), csr # In pyopenssl 0.13 (used with TOXENV=py27-oldest), csr objects don't
# objects don't have a get_extensions() method, so we skip this test if # have a get_extensions() method, so we skip this test if the method
# the method isn't available. # isn't available.
if hasattr(csr, 'get_extensions'): if hasattr(csr, 'get_extensions'):
self.assertEquals(len(csr.get_extensions()), 2) self.assertEquals(len(csr.get_extensions()), 2)
# NOTE: Ideally we would filter by the TLS Feature OID, but # NOTE: Ideally we would filter by the TLS Feature OID, but

View File

@@ -23,13 +23,6 @@ install_requires = [
'six>=1.9.0', # needed for python_2_unicode_compatible 'six>=1.9.0', # needed for python_2_unicode_compatible
] ]
# env markers cause problems with older pip and setuptools
if sys.version_info < (2, 7):
install_requires.extend([
'argparse',
'ordereddict',
])
dev_extras = [ dev_extras = [
'pytest', 'pytest',
'pytest-xdist', 'pytest-xdist',
@@ -50,16 +43,15 @@ setup(
author="Certbot Project", author="Certbot Project",
author_email='client-dev@letsencrypt.org', author_email='client-dev@letsencrypt.org',
license='Apache License 2.0', license='Apache License 2.0',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
classifiers=[ classifiers=[
'Development Status :: 3 - Alpha', 'Development Status :: 3 - Alpha',
'Intended Audience :: Developers', 'Intended Audience :: Developers',
'License :: OSI Approved :: Apache Software License', 'License :: OSI Approved :: Apache Software License',
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',

View File

@@ -30,6 +30,7 @@ setup(
author="Certbot Project", author="Certbot Project",
author_email='client-dev@letsencrypt.org', author_email='client-dev@letsencrypt.org',
license='Apache License 2.0', license='Apache License 2.0',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
classifiers=[ classifiers=[
'Development Status :: 3 - Alpha', 'Development Status :: 3 - Alpha',
'Environment :: Plugins', 'Environment :: Plugins',
@@ -38,10 +39,8 @@ setup(
'Operating System :: POSIX :: Linux', 'Operating System :: POSIX :: Linux',
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',

View File

@@ -34,16 +34,15 @@ setup(
author="Certbot Project", author="Certbot Project",
author_email='client-dev@letsencrypt.org', author_email='client-dev@letsencrypt.org',
license='Apache License 2.0', license='Apache License 2.0',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
classifiers=[ classifiers=[
'Development Status :: 3 - Alpha', 'Development Status :: 3 - Alpha',
'Intended Audience :: Developers', 'Intended Audience :: Developers',
'License :: OSI Approved :: Apache Software License', 'License :: OSI Approved :: Apache Software License',
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',

View File

@@ -29,6 +29,7 @@ setup(
author="Certbot Project", author="Certbot Project",
author_email='client-dev@letsencrypt.org', author_email='client-dev@letsencrypt.org',
license='Apache License 2.0', license='Apache License 2.0',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
classifiers=[ classifiers=[
'Development Status :: 3 - Alpha', 'Development Status :: 3 - Alpha',
'Environment :: Plugins', 'Environment :: Plugins',
@@ -37,10 +38,8 @@ setup(
'Operating System :: POSIX :: Linux', 'Operating System :: POSIX :: Linux',
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',

View File

@@ -29,6 +29,7 @@ setup(
author="Certbot Project", author="Certbot Project",
author_email='client-dev@letsencrypt.org', author_email='client-dev@letsencrypt.org',
license='Apache License 2.0', license='Apache License 2.0',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
classifiers=[ classifiers=[
'Development Status :: 3 - Alpha', 'Development Status :: 3 - Alpha',
'Environment :: Plugins', 'Environment :: Plugins',
@@ -39,7 +40,6 @@ setup(
'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',

View File

@@ -30,6 +30,7 @@ setup(
author="Certbot Project", author="Certbot Project",
author_email='client-dev@letsencrypt.org', author_email='client-dev@letsencrypt.org',
license='Apache License 2.0', license='Apache License 2.0',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
classifiers=[ classifiers=[
'Development Status :: 3 - Alpha', 'Development Status :: 3 - Alpha',
'Environment :: Plugins', 'Environment :: Plugins',
@@ -38,10 +39,8 @@ setup(
'Operating System :: POSIX :: Linux', 'Operating System :: POSIX :: Linux',
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',

View File

@@ -29,6 +29,7 @@ setup(
author="Certbot Project", author="Certbot Project",
author_email='client-dev@letsencrypt.org', author_email='client-dev@letsencrypt.org',
license='Apache License 2.0', license='Apache License 2.0',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
classifiers=[ classifiers=[
'Development Status :: 3 - Alpha', 'Development Status :: 3 - Alpha',
'Environment :: Plugins', 'Environment :: Plugins',
@@ -39,7 +40,6 @@ setup(
'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',

View File

@@ -29,6 +29,7 @@ setup(
author="Certbot Project", author="Certbot Project",
author_email='client-dev@letsencrypt.org', author_email='client-dev@letsencrypt.org',
license='Apache License 2.0', license='Apache License 2.0',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
classifiers=[ classifiers=[
'Development Status :: 3 - Alpha', 'Development Status :: 3 - Alpha',
'Environment :: Plugins', 'Environment :: Plugins',
@@ -39,7 +40,6 @@ setup(
'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',

View File

@@ -34,6 +34,7 @@ setup(
author="Certbot Project", author="Certbot Project",
author_email='client-dev@letsencrypt.org', author_email='client-dev@letsencrypt.org',
license='Apache License 2.0', license='Apache License 2.0',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
classifiers=[ classifiers=[
'Development Status :: 3 - Alpha', 'Development Status :: 3 - Alpha',
'Environment :: Plugins', 'Environment :: Plugins',
@@ -42,10 +43,8 @@ setup(
'Operating System :: POSIX :: Linux', 'Operating System :: POSIX :: Linux',
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',

View File

@@ -29,6 +29,7 @@ setup(
author="Certbot Project", author="Certbot Project",
author_email='client-dev@letsencrypt.org', author_email='client-dev@letsencrypt.org',
license='Apache License 2.0', license='Apache License 2.0',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
classifiers=[ classifiers=[
'Development Status :: 3 - Alpha', 'Development Status :: 3 - Alpha',
'Environment :: Plugins', 'Environment :: Plugins',
@@ -39,7 +40,6 @@ setup(
'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',

View File

@@ -29,6 +29,7 @@ setup(
author="Certbot Project", author="Certbot Project",
author_email='client-dev@letsencrypt.org', author_email='client-dev@letsencrypt.org',
license='Apache License 2.0', license='Apache License 2.0',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
classifiers=[ classifiers=[
'Development Status :: 3 - Alpha', 'Development Status :: 3 - Alpha',
'Environment :: Plugins', 'Environment :: Plugins',
@@ -39,7 +40,6 @@ setup(
'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',

View File

@@ -29,6 +29,7 @@ setup(
author="Certbot Project", author="Certbot Project",
author_email='client-dev@letsencrypt.org', author_email='client-dev@letsencrypt.org',
license='Apache License 2.0', license='Apache License 2.0',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
classifiers=[ classifiers=[
'Development Status :: 3 - Alpha', 'Development Status :: 3 - Alpha',
'Environment :: Plugins', 'Environment :: Plugins',
@@ -37,10 +38,8 @@ setup(
'Operating System :: POSIX :: Linux', 'Operating System :: POSIX :: Linux',
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',

View File

@@ -22,6 +22,7 @@ setup(
author="Certbot Project", author="Certbot Project",
author_email='client-dev@letsencrypt.org', author_email='client-dev@letsencrypt.org',
license='Apache License 2.0', license='Apache License 2.0',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
classifiers=[ classifiers=[
'Development Status :: 3 - Alpha', 'Development Status :: 3 - Alpha',
'Environment :: Plugins', 'Environment :: Plugins',
@@ -30,10 +31,8 @@ setup(
'Operating System :: POSIX :: Linux', 'Operating System :: POSIX :: Linux',
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',

View File

@@ -30,6 +30,7 @@ setup(
author="Certbot Project", author="Certbot Project",
author_email='client-dev@letsencrypt.org', author_email='client-dev@letsencrypt.org',
license='Apache License 2.0', license='Apache License 2.0',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
classifiers=[ classifiers=[
'Development Status :: 3 - Alpha', 'Development Status :: 3 - Alpha',
'Environment :: Plugins', 'Environment :: Plugins',
@@ -38,10 +39,8 @@ setup(
'Operating System :: POSIX :: Linux', 'Operating System :: POSIX :: Linux',
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',

View File

@@ -165,12 +165,7 @@ class ColoredStreamHandler(logging.StreamHandler):
""" """
def __init__(self, stream=None): def __init__(self, stream=None):
# logging handlers use old style classes in Python 2.6 so super(ColoredStreamHandler, self).__init__(stream)
# super() cannot be used
if sys.version_info < (2, 7): # pragma: no cover
logging.StreamHandler.__init__(self, stream)
else:
super(ColoredStreamHandler, self).__init__(stream)
self.colored = (sys.stderr.isatty() if stream is None else self.colored = (sys.stderr.isatty() if stream is None else
stream.isatty()) stream.isatty())
self.red_level = logging.WARNING self.red_level = logging.WARNING
@@ -184,9 +179,7 @@ class ColoredStreamHandler(logging.StreamHandler):
:rtype: str :rtype: str
""" """
out = (logging.StreamHandler.format(self, record) out = super(ColoredStreamHandler, self).format(record)
if sys.version_info < (2, 7)
else super(ColoredStreamHandler, self).format(record))
if self.colored and record.levelno >= self.red_level: if self.colored and record.levelno >= self.red_level:
return ''.join((util.ANSI_SGR_RED, out, util.ANSI_SGR_RESET)) return ''.join((util.ANSI_SGR_RED, out, util.ANSI_SGR_RESET))
else: else:
@@ -203,23 +196,14 @@ class MemoryHandler(logging.handlers.MemoryHandler):
def __init__(self, target=None): def __init__(self, target=None):
# capacity doesn't matter because should_flush() is overridden # capacity doesn't matter because should_flush() is overridden
capacity = float('inf') capacity = float('inf')
# logging handlers use old style classes in Python 2.6 so super(MemoryHandler, self).__init__(capacity, target=target)
# super() cannot be used
if sys.version_info < (2, 7): # pragma: no cover
logging.handlers.MemoryHandler.__init__(
self, capacity, target=target)
else:
super(MemoryHandler, self).__init__(capacity, target=target)
def close(self): def close(self):
"""Close the memory handler, but don't set the target to None.""" """Close the memory handler, but don't set the target to None."""
# This allows the logging module which may only have a weak # This allows the logging module which may only have a weak
# reference to the target handler to properly flush and close it. # reference to the target handler to properly flush and close it.
target = self.target target = self.target
if sys.version_info < (2, 7): # pragma: no cover super(MemoryHandler, self).close()
logging.handlers.MemoryHandler.close(self)
else:
super(MemoryHandler, self).close()
self.target = target self.target = target
def flush(self, force=False): # pylint: disable=arguments-differ def flush(self, force=False): # pylint: disable=arguments-differ
@@ -233,10 +217,7 @@ class MemoryHandler(logging.handlers.MemoryHandler):
# This method allows flush() calls in logging.shutdown to be a # This method allows flush() calls in logging.shutdown to be a
# noop so we can control when this handler is flushed. # noop so we can control when this handler is flushed.
if force: if force:
if sys.version_info < (2, 7): # pragma: no cover super(MemoryHandler, self).flush()
logging.handlers.MemoryHandler.flush(self)
else:
super(MemoryHandler, self).flush()
def shouldFlush(self, record): def shouldFlush(self, record):
"""Should the buffer be automatically flushed? """Should the buffer be automatically flushed?
@@ -262,12 +243,7 @@ class TempHandler(logging.StreamHandler):
""" """
def __init__(self): def __init__(self):
stream = tempfile.NamedTemporaryFile('w', delete=False) stream = tempfile.NamedTemporaryFile('w', delete=False)
# logging handlers use old style classes in Python 2.6 so super(TempHandler, self).__init__(stream)
# super() cannot be used
if sys.version_info < (2, 7): # pragma: no cover
logging.StreamHandler.__init__(self, stream)
else:
super(TempHandler, self).__init__(stream)
self.path = stream.name self.path = stream.name
self._delete = True self._delete = True
@@ -278,12 +254,7 @@ class TempHandler(logging.StreamHandler):
""" """
self._delete = False self._delete = False
# logging handlers use old style classes in Python 2.6 so super(TempHandler, self).emit(record)
# super() cannot be used
if sys.version_info < (2, 7): # pragma: no cover
logging.StreamHandler.emit(self, record)
else:
super(TempHandler, self).emit(record)
def close(self): def close(self):
"""Close the handler and the temporary log file. """Close the handler and the temporary log file.
@@ -299,10 +270,7 @@ class TempHandler(logging.StreamHandler):
if self._delete: if self._delete:
os.remove(self.path) os.remove(self.path)
self._delete = False self._delete = False
if sys.version_info < (2, 7): # pragma: no cover super(TempHandler, self).close()
logging.StreamHandler.close(self)
else:
super(TempHandler, self).close()
finally: finally:
self.release() self.release()

View File

@@ -5,7 +5,6 @@ import functools
import logging.handlers import logging.handlers
import os import os
import sys import sys
import warnings
import configobj import configobj
import josepy as jose import josepy as jose
@@ -1256,17 +1255,6 @@ def main(cli_args=sys.argv[1:]):
# Let plugins_cmd be run as un-privileged user. # Let plugins_cmd be run as un-privileged user.
if config.func != plugins_cmd: if config.func != plugins_cmd:
raise raise
deprecation_fmt = (
"Python %s.%s support will be dropped in the next "
"release of Certbot - please upgrade your Python version.")
# We use the warnings system for Python 2.6 and logging for Python 3
# because DeprecationWarnings are only reported by default in Python <= 2.6
# and warnings can be disabled by the user.
if sys.version_info[:2] == (2, 6):
warning = deprecation_fmt % sys.version_info[:2]
warnings.warn(warning, DeprecationWarning)
elif sys.version_info[:2] == (3, 3):
logger.warning(deprecation_fmt, *sys.version_info[:2])
set_displayer(config) set_displayer(config)

View File

@@ -5,6 +5,8 @@ import logging
import pkg_resources import pkg_resources
import six import six
from collections import OrderedDict
import zope.interface import zope.interface
import zope.interface.verify import zope.interface.verify
@@ -12,12 +14,6 @@ from certbot import constants
from certbot import errors from certbot import errors
from certbot import interfaces from certbot import interfaces
try:
from collections import OrderedDict
except ImportError: # pragma: no cover
# OrderedDict was added in Python 2.7
from ordereddict import OrderedDict # pylint: disable=import-error
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@@ -16,18 +16,14 @@ import stat
import subprocess import subprocess
import sys import sys
from collections import OrderedDict
import configargparse import configargparse
from certbot import constants from certbot import constants
from certbot import errors from certbot import errors
from certbot import lock from certbot import lock
try:
from collections import OrderedDict
except ImportError: # pragma: no cover
# OrderedDict was added in Python 2.7
from ordereddict import OrderedDict # pylint: disable=import-error
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@@ -422,7 +422,7 @@ OS-level dependencies can be installed like so:
In general... In general...
* ``sudo`` is required as a suggested way of running privileged process * ``sudo`` is required as a suggested way of running privileged process
* `Python`_ 2.6/2.7 is required * `Python`_ 2.7 is required
* `Augeas`_ is required for the Python bindings * `Augeas`_ is required for the Python bindings
* ``virtualenv`` and ``pip`` are used for managing other python library * ``virtualenv`` and ``pip`` are used for managing other python library
dependencies dependencies

View File

@@ -22,7 +22,7 @@ your system.
System Requirements System Requirements
=================== ===================
Certbot currently requires Python 2.6, 2.7, or 3.3+. By default, it requires Certbot currently requires Python 2.7, or 3.4+. By default, it requires
root access in order to write to ``/etc/letsencrypt``, root access in order to write to ``/etc/letsencrypt``,
``/var/log/letsencrypt``, ``/var/lib/letsencrypt``; to bind to ports 80 and 443 ``/var/log/letsencrypt``, ``/var/lib/letsencrypt``; to bind to ports 80 and 443
(if you use the ``standalone`` plugin) and to read and modify webserver (if you use the ``standalone`` plugin) and to read and modify webserver

View File

@@ -249,7 +249,7 @@ DeprecationBootstrap() {
fi fi
} }
MIN_PYTHON_VERSION="2.6" MIN_PYTHON_VERSION="2.7"
MIN_PYVER=$(echo "$MIN_PYTHON_VERSION" | sed 's/\.//') MIN_PYVER=$(echo "$MIN_PYTHON_VERSION" | sed 's/\.//')
# Sets LE_PYTHON to Python version string and PYVER to the first two # Sets LE_PYTHON to Python version string and PYVER to the first two
# digits of the python version # digits of the python version
@@ -1240,6 +1240,7 @@ anything goes wrong, it will exit with a non-zero status code.
from __future__ import print_function from __future__ import print_function
from distutils.version import StrictVersion from distutils.version import StrictVersion
from hashlib import sha256 from hashlib import sha256
from os import environ
from os.path import join from os.path import join
from pipes import quote from pipes import quote
from shutil import rmtree from shutil import rmtree
@@ -1273,33 +1274,32 @@ except ImportError:
from urllib.parse import urlparse # 3.4 from urllib.parse import urlparse # 3.4
__version__ = 1, 3, 0 __version__ = 1, 5, 0
PIP_VERSION = '9.0.1' PIP_VERSION = '9.0.1'
DEFAULT_INDEX_BASE = 'https://pypi.python.org'
# wheel has a conditional dependency on argparse: # wheel has a conditional dependency on argparse:
maybe_argparse = ( maybe_argparse = (
[('https://pypi.python.org/packages/18/dd/' [('18/dd/e617cfc3f6210ae183374cd9f6a26b20514bbb5a792af97949c5aacddf0f/'
'e617cfc3f6210ae183374cd9f6a26b20514bbb5a792af97949c5aacddf0f/'
'argparse-1.4.0.tar.gz', 'argparse-1.4.0.tar.gz',
'62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4')] '62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4')]
if version_info < (2, 7, 0) else []) if version_info < (2, 7, 0) else [])
PACKAGES = maybe_argparse + [ # Pip has no dependencies, as it vendors everything:
# Pip has no dependencies, as it vendors everything: PIP_PACKAGE = [
('https://pypi.python.org/packages/11/b6/' ('11/b6/abcb525026a4be042b486df43905d6893fb04f05aac21c32c638e939e447/'
'abcb525026a4be042b486df43905d6893fb04f05aac21c32c638e939e447/' 'pip-{0}.tar.gz'.format(PIP_VERSION),
'pip-{0}.tar.gz' '09f243e1a7b461f654c26a725fa373211bb7ff17a9300058b205c61658ca940d')]
.format(PIP_VERSION),
'09f243e1a7b461f654c26a725fa373211bb7ff17a9300058b205c61658ca940d'),
OTHER_PACKAGES = maybe_argparse + [
# This version of setuptools has only optional dependencies: # This version of setuptools has only optional dependencies:
('https://pypi.python.org/packages/69/65/' ('59/88/2f3990916931a5de6fa9706d6d75eb32ee8b78627bb2abaab7ed9e6d0622/'
'4c544cde88d4d876cdf5cbc5f3f15d02646477756d89547e9a7ecd6afa76/' 'setuptools-29.0.1.tar.gz',
'setuptools-20.2.2.tar.gz', 'b539118819a4857378398891fa5366e090690e46b3e41421a1e07d6e9fd8feb0'),
'24fcfc15364a9fe09a220f37d2dcedc849795e3de3e4b393ee988e66a9cbd85a'), ('c9/1d/bd19e691fd4cfe908c76c429fe6e4436c9e83583c4414b54f6c85471954a/'
('https://pypi.python.org/packages/c9/1d/'
'bd19e691fd4cfe908c76c429fe6e4436c9e83583c4414b54f6c85471954a/'
'wheel-0.29.0.tar.gz', 'wheel-0.29.0.tar.gz',
'1ebb8ad7e26b448e9caa4773d2357849bf80ff9e313964bcaf79cbf0201a1648') '1ebb8ad7e26b448e9caa4773d2357849bf80ff9e313964bcaf79cbf0201a1648')
] ]
@@ -1320,12 +1320,13 @@ def hashed_download(url, temp, digest):
# >=2.7.9 verifies HTTPS certs itself, and, in any case, the cert # >=2.7.9 verifies HTTPS certs itself, and, in any case, the cert
# authenticity has only privacy (not arbitrary code execution) # authenticity has only privacy (not arbitrary code execution)
# implications, since we're checking hashes. # implications, since we're checking hashes.
def opener(): def opener(using_https=True):
opener = build_opener(HTTPSHandler()) opener = build_opener(HTTPSHandler())
# Strip out HTTPHandler to prevent MITM spoof: if using_https:
for handler in opener.handlers: # Strip out HTTPHandler to prevent MITM spoof:
if isinstance(handler, HTTPHandler): for handler in opener.handlers:
opener.handlers.remove(handler) if isinstance(handler, HTTPHandler):
opener.handlers.remove(handler)
return opener return opener
def read_chunks(response, chunk_size): def read_chunks(response, chunk_size):
@@ -1335,8 +1336,9 @@ def hashed_download(url, temp, digest):
break break
yield chunk yield chunk
response = opener().open(url) parsed_url = urlparse(url)
path = join(temp, urlparse(url).path.split('/')[-1]) response = opener(using_https=parsed_url.scheme == 'https').open(url)
path = join(temp, parsed_url.path.split('/')[-1])
actual_hash = sha256() actual_hash = sha256()
with open(path, 'wb') as file: with open(path, 'wb') as file:
for chunk in read_chunks(response, 4096): for chunk in read_chunks(response, 4096):
@@ -1349,6 +1351,24 @@ def hashed_download(url, temp, digest):
return path return path
def get_index_base():
"""Return the URL to the dir containing the "packages" folder.
Try to wring something out of PIP_INDEX_URL, if set. Hack "/simple" off the
end if it's there; that is likely to give us the right dir.
"""
env_var = environ.get('PIP_INDEX_URL', '').rstrip('/')
if env_var:
SIMPLE = '/simple'
if env_var.endswith(SIMPLE):
return env_var[:-len(SIMPLE)]
else:
return env_var
else:
return DEFAULT_INDEX_BASE
def main(): def main():
pip_version = StrictVersion(check_output(['pip', '--version']) pip_version = StrictVersion(check_output(['pip', '--version'])
.decode('utf-8').split()[1]) .decode('utf-8').split()[1])
@@ -1356,17 +1376,24 @@ def main():
if pip_version >= min_pip_version: if pip_version >= min_pip_version:
return 0 return 0
has_pip_cache = pip_version >= StrictVersion('6.0') has_pip_cache = pip_version >= StrictVersion('6.0')
index_base = get_index_base()
temp = mkdtemp(prefix='pipstrap-') temp = mkdtemp(prefix='pipstrap-')
try: try:
downloads = [hashed_download(url, temp, digest) # We download and install pip first, then the rest, to avoid the bug
for url, digest in PACKAGES] # https://github.com/certbot/certbot/issues/4938.
check_output('pip install --no-index --no-deps -U ' + pip_downloads, other_downloads = [
# Disable cache since we're not using it and it otherwise [hashed_download(index_base + '/packages/' + path,
# sometimes throws permission warnings: temp,
('--no-cache-dir ' if has_pip_cache else '') + digest)
' '.join(quote(d) for d in downloads), for path, digest in packages]
shell=True) for packages in (PIP_PACKAGE, OTHER_PACKAGES)]
for downloads in (pip_downloads, other_downloads):
check_output('pip install --no-index --no-deps -U ' +
# Disable cache since we're not using it and it
# otherwise sometimes throws permission warnings:
('--no-cache-dir ' if has_pip_cache else '') +
' '.join(quote(d) for d in downloads),
shell=True)
except HashError as exc: except HashError as exc:
print(exc) print(exc)
except Exception: except Exception:

View File

@@ -249,7 +249,7 @@ DeprecationBootstrap() {
fi fi
} }
MIN_PYTHON_VERSION="2.6" MIN_PYTHON_VERSION="2.7"
MIN_PYVER=$(echo "$MIN_PYTHON_VERSION" | sed 's/\.//') MIN_PYVER=$(echo "$MIN_PYTHON_VERSION" | sed 's/\.//')
# Sets LE_PYTHON to Python version string and PYVER to the first two # Sets LE_PYTHON to Python version string and PYVER to the first two
# digits of the python version # digits of the python version

View File

@@ -23,6 +23,7 @@ anything goes wrong, it will exit with a non-zero status code.
from __future__ import print_function from __future__ import print_function
from distutils.version import StrictVersion from distutils.version import StrictVersion
from hashlib import sha256 from hashlib import sha256
from os import environ
from os.path import join from os.path import join
from pipes import quote from pipes import quote
from shutil import rmtree from shutil import rmtree
@@ -56,33 +57,32 @@ except ImportError:
from urllib.parse import urlparse # 3.4 from urllib.parse import urlparse # 3.4
__version__ = 1, 3, 0 __version__ = 1, 5, 0
PIP_VERSION = '9.0.1' PIP_VERSION = '9.0.1'
DEFAULT_INDEX_BASE = 'https://pypi.python.org'
# wheel has a conditional dependency on argparse: # wheel has a conditional dependency on argparse:
maybe_argparse = ( maybe_argparse = (
[('https://pypi.python.org/packages/18/dd/' [('18/dd/e617cfc3f6210ae183374cd9f6a26b20514bbb5a792af97949c5aacddf0f/'
'e617cfc3f6210ae183374cd9f6a26b20514bbb5a792af97949c5aacddf0f/'
'argparse-1.4.0.tar.gz', 'argparse-1.4.0.tar.gz',
'62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4')] '62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4')]
if version_info < (2, 7, 0) else []) if version_info < (2, 7, 0) else [])
PACKAGES = maybe_argparse + [ # Pip has no dependencies, as it vendors everything:
# Pip has no dependencies, as it vendors everything: PIP_PACKAGE = [
('https://pypi.python.org/packages/11/b6/' ('11/b6/abcb525026a4be042b486df43905d6893fb04f05aac21c32c638e939e447/'
'abcb525026a4be042b486df43905d6893fb04f05aac21c32c638e939e447/' 'pip-{0}.tar.gz'.format(PIP_VERSION),
'pip-{0}.tar.gz' '09f243e1a7b461f654c26a725fa373211bb7ff17a9300058b205c61658ca940d')]
.format(PIP_VERSION),
'09f243e1a7b461f654c26a725fa373211bb7ff17a9300058b205c61658ca940d'),
OTHER_PACKAGES = maybe_argparse + [
# This version of setuptools has only optional dependencies: # This version of setuptools has only optional dependencies:
('https://pypi.python.org/packages/69/65/' ('59/88/2f3990916931a5de6fa9706d6d75eb32ee8b78627bb2abaab7ed9e6d0622/'
'4c544cde88d4d876cdf5cbc5f3f15d02646477756d89547e9a7ecd6afa76/' 'setuptools-29.0.1.tar.gz',
'setuptools-20.2.2.tar.gz', 'b539118819a4857378398891fa5366e090690e46b3e41421a1e07d6e9fd8feb0'),
'24fcfc15364a9fe09a220f37d2dcedc849795e3de3e4b393ee988e66a9cbd85a'), ('c9/1d/bd19e691fd4cfe908c76c429fe6e4436c9e83583c4414b54f6c85471954a/'
('https://pypi.python.org/packages/c9/1d/'
'bd19e691fd4cfe908c76c429fe6e4436c9e83583c4414b54f6c85471954a/'
'wheel-0.29.0.tar.gz', 'wheel-0.29.0.tar.gz',
'1ebb8ad7e26b448e9caa4773d2357849bf80ff9e313964bcaf79cbf0201a1648') '1ebb8ad7e26b448e9caa4773d2357849bf80ff9e313964bcaf79cbf0201a1648')
] ]
@@ -103,12 +103,13 @@ def hashed_download(url, temp, digest):
# >=2.7.9 verifies HTTPS certs itself, and, in any case, the cert # >=2.7.9 verifies HTTPS certs itself, and, in any case, the cert
# authenticity has only privacy (not arbitrary code execution) # authenticity has only privacy (not arbitrary code execution)
# implications, since we're checking hashes. # implications, since we're checking hashes.
def opener(): def opener(using_https=True):
opener = build_opener(HTTPSHandler()) opener = build_opener(HTTPSHandler())
# Strip out HTTPHandler to prevent MITM spoof: if using_https:
for handler in opener.handlers: # Strip out HTTPHandler to prevent MITM spoof:
if isinstance(handler, HTTPHandler): for handler in opener.handlers:
opener.handlers.remove(handler) if isinstance(handler, HTTPHandler):
opener.handlers.remove(handler)
return opener return opener
def read_chunks(response, chunk_size): def read_chunks(response, chunk_size):
@@ -118,8 +119,9 @@ def hashed_download(url, temp, digest):
break break
yield chunk yield chunk
response = opener().open(url) parsed_url = urlparse(url)
path = join(temp, urlparse(url).path.split('/')[-1]) response = opener(using_https=parsed_url.scheme == 'https').open(url)
path = join(temp, parsed_url.path.split('/')[-1])
actual_hash = sha256() actual_hash = sha256()
with open(path, 'wb') as file: with open(path, 'wb') as file:
for chunk in read_chunks(response, 4096): for chunk in read_chunks(response, 4096):
@@ -132,6 +134,24 @@ def hashed_download(url, temp, digest):
return path return path
def get_index_base():
"""Return the URL to the dir containing the "packages" folder.
Try to wring something out of PIP_INDEX_URL, if set. Hack "/simple" off the
end if it's there; that is likely to give us the right dir.
"""
env_var = environ.get('PIP_INDEX_URL', '').rstrip('/')
if env_var:
SIMPLE = '/simple'
if env_var.endswith(SIMPLE):
return env_var[:-len(SIMPLE)]
else:
return env_var
else:
return DEFAULT_INDEX_BASE
def main(): def main():
pip_version = StrictVersion(check_output(['pip', '--version']) pip_version = StrictVersion(check_output(['pip', '--version'])
.decode('utf-8').split()[1]) .decode('utf-8').split()[1])
@@ -139,17 +159,24 @@ def main():
if pip_version >= min_pip_version: if pip_version >= min_pip_version:
return 0 return 0
has_pip_cache = pip_version >= StrictVersion('6.0') has_pip_cache = pip_version >= StrictVersion('6.0')
index_base = get_index_base()
temp = mkdtemp(prefix='pipstrap-') temp = mkdtemp(prefix='pipstrap-')
try: try:
downloads = [hashed_download(url, temp, digest) # We download and install pip first, then the rest, to avoid the bug
for url, digest in PACKAGES] # https://github.com/certbot/certbot/issues/4938.
check_output('pip install --no-index --no-deps -U ' + pip_downloads, other_downloads = [
# Disable cache since we're not using it and it otherwise [hashed_download(index_base + '/packages/' + path,
# sometimes throws permission warnings: temp,
('--no-cache-dir ' if has_pip_cache else '') + digest)
' '.join(quote(d) for d in downloads), for path, digest in packages]
shell=True) for packages in (PIP_PACKAGE, OTHER_PACKAGES)]
for downloads in (pip_downloads, other_downloads):
check_output('pip install --no-index --no-deps -U ' +
# Disable cache since we're not using it and it
# otherwise sometimes throws permission warnings:
('--no-cache-dir ' if has_pip_cache else '') +
' '.join(quote(d) for d in downloads),
shell=True)
except HashError as exc: except HashError as exc:
print(exc) print(exc)
except Exception: except Exception:

View File

@@ -287,8 +287,8 @@ class AutoTests(TestCase):
self.assertTrue(re.match(r'letsencrypt \d+\.\d+\.\d+', self.assertTrue(re.match(r'letsencrypt \d+\.\d+\.\d+',
err.strip().splitlines()[-1])) err.strip().splitlines()[-1]))
# Make a few assertions to test the validity of the next tests: # Make a few assertions to test the validity of the next tests:
self.assertTrue('Upgrading certbot-auto ' in out) self.assertIn('Upgrading certbot-auto ', out)
self.assertTrue('Creating virtual environment...' in out) self.assertIn('Creating virtual environment...', out)
# Now we have le-auto 99.9.9 and LE 99.9.9 installed. This # Now we have le-auto 99.9.9 and LE 99.9.9 installed. This
# conveniently sets us up to test the next 2 cases. # conveniently sets us up to test the next 2 cases.
@@ -296,8 +296,8 @@ class AutoTests(TestCase):
# Test when neither phase-1 upgrade nor phase-2 upgrade is # Test when neither phase-1 upgrade nor phase-2 upgrade is
# needed (probably a common case): # needed (probably a common case):
out, err = run_letsencrypt_auto() out, err = run_letsencrypt_auto()
self.assertFalse('Upgrading certbot-auto ' in out) self.assertNotIn('Upgrading certbot-auto ', out)
self.assertFalse('Creating virtual environment...' in out) self.assertNotIn('Creating virtual environment...', out)
def test_phase2_upgrade(self): def test_phase2_upgrade(self):
"""Test a phase-2 upgrade without a phase-1 upgrade.""" """Test a phase-2 upgrade without a phase-1 upgrade."""
@@ -312,8 +312,8 @@ class AutoTests(TestCase):
# Create venv saving the correct bootstrap script version # Create venv saving the correct bootstrap script version
out, err = run_le_auto(le_auto_path, venv_dir, base_url, out, err = run_le_auto(le_auto_path, venv_dir, base_url,
PIP_FIND_LINKS=pip_find_links) PIP_FIND_LINKS=pip_find_links)
self.assertFalse('Upgrading certbot-auto ' in out) self.assertNotIn('Upgrading certbot-auto ', out)
self.assertTrue('Creating virtual environment...' in out) self.assertIn('Creating virtual environment...', out)
with open(join(venv_dir, BOOTSTRAP_FILENAME)) as f: with open(join(venv_dir, BOOTSTRAP_FILENAME)) as f:
bootstrap_version = f.read() bootstrap_version = f.read()
@@ -329,8 +329,8 @@ class AutoTests(TestCase):
out, err = run_le_auto(le_auto_path, venv_dir, base_url, out, err = run_le_auto(le_auto_path, venv_dir, base_url,
PIP_FIND_LINKS=pip_find_links) PIP_FIND_LINKS=pip_find_links)
self.assertFalse('Upgrading certbot-auto ' in out) self.assertNotIn('Upgrading certbot-auto ', out)
self.assertTrue('Creating virtual environment...' in out) self.assertIn('Creating virtual environment...', out)
def test_openssl_failure(self): def test_openssl_failure(self):
"""Make sure we stop if the openssl signature check fails.""" """Make sure we stop if the openssl signature check fails."""

View File

@@ -5,7 +5,6 @@ from __future__ import print_function
import argparse import argparse
import atexit import atexit
import contextlib
import os import os
import re import re
import shutil import shutil
@@ -302,8 +301,7 @@ def main():
make_and_verify_selection(args.server_root, tempdir) make_and_verify_selection(args.server_root, tempdir)
tarpath = os.path.join(tempdir, "config.tar.gz") tarpath = os.path.join(tempdir, "config.tar.gz")
# contextlib.closing used for py26 support with tarfile.open(tarpath, mode="w:gz") as tar:
with contextlib.closing(tarfile.open(tarpath, mode="w:gz")) as tar:
tar.add(tempdir, arcname=".") tar.add(tempdir, arcname=".")
# TODO: Submit tarpath # TODO: Submit tarpath

View File

@@ -24,6 +24,7 @@ setup(
author="Certbot Project", author="Certbot Project",
author_email='client-dev@letsencrypt.org', author_email='client-dev@letsencrypt.org',
license='Apache License 2.0', license='Apache License 2.0',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
classifiers=[ classifiers=[
'Development Status :: 3 - Alpha', 'Development Status :: 3 - Alpha',
'Intended Audience :: System Administrators', 'Intended Audience :: System Administrators',
@@ -31,10 +32,8 @@ setup(
'Operating System :: POSIX :: Linux', 'Operating System :: POSIX :: Linux',
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',

View File

@@ -51,13 +51,6 @@ install_requires = [
'zope.interface', 'zope.interface',
] ]
# env markers cause problems with older pip and setuptools
if sys.version_info < (2, 7):
install_requires.extend([
'argparse',
'ordereddict',
])
dev_extras = [ dev_extras = [
# Pin astroid==1.3.5, pylint==1.4.2 as a workaround for #289 # Pin astroid==1.3.5, pylint==1.4.2 as a workaround for #289
'astroid==1.3.5', 'astroid==1.3.5',
@@ -88,6 +81,7 @@ setup(
author="Certbot Project", author="Certbot Project",
author_email='client-dev@letsencrypt.org', author_email='client-dev@letsencrypt.org',
license='Apache License 2.0', license='Apache License 2.0',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
classifiers=[ classifiers=[
'Development Status :: 3 - Alpha', 'Development Status :: 3 - Alpha',
'Environment :: Console', 'Environment :: Console',
@@ -97,10 +91,8 @@ setup(
'Operating System :: POSIX :: Linux', 'Operating System :: POSIX :: Linux',
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',

View File

@@ -15,10 +15,4 @@ VENV_BIN=${VENV_PATH}/bin
cd letsencrypt cd letsencrypt
./tools/venv.sh ./tools/venv.sh
PYVER=`python --version 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'` venv/bin/tox -e py27
if [ $PYVER -eq 26 ] ; then
venv/bin/tox -e py26
else
venv/bin/tox -e py27
fi

View File

@@ -3,7 +3,7 @@ import sys
# Run Python's built-in HTTP server # Run Python's built-in HTTP server
# Usage: python ./tests/run_http_server.py port_num # Usage: python ./tests/run_http_server.py port_num
# NOTE: This script should be compatible with 2.6, 2.7, 3.3+ # NOTE: This script should be compatible with 2.7, 3.4+
# sys.argv (port number) is passed as-is to the HTTP server module # sys.argv (port number) is passed as-is to the HTTP server module
runpy.run_module( runpy.run_module(

View File

@@ -18,10 +18,6 @@ for requirement in "$@" ; do
pkg=$(echo $requirement | cut -f1 -d\[) # remove any extras such as [dev] pkg=$(echo $requirement | cut -f1 -d\[) # remove any extras such as [dev]
if [ $pkg = "." ]; then if [ $pkg = "." ]; then
pkg="certbot" pkg="certbot"
else
# Work around a bug in pytest/importlib for the deprecated Python 3.3.
# See https://travis-ci.org/certbot/certbot/jobs/308774157#L1333.
pkg=$(echo "$pkg" | tr - _)
fi fi
"$(dirname $0)/pytest.sh" --pyargs $pkg "$(dirname $0)/pytest.sh" --pyargs $pkg
done done

41
tox.ini
View File

@@ -4,7 +4,7 @@
[tox] [tox]
skipsdist = true skipsdist = true
envlist = modification,py{26,33,34,35,36},cover,lint envlist = modification,py{34,35,36},cover,lint
[base] [base]
# pip installs the requested packages in editable mode # pip installs the requested packages in editable mode
@@ -14,25 +14,22 @@ pip_install = {toxinidir}/tools/pip_install_editable.sh
# before the script moves on to the next package. All dependencies are pinned # before the script moves on to the next package. All dependencies are pinned
# to a specific version for increased stability for developers. # to a specific version for increased stability for developers.
install_and_test = {toxinidir}/tools/install_and_test.sh install_and_test = {toxinidir}/tools/install_and_test.sh
py26_packages = all_packages =
acme[dev] \ acme[dev] \
.[dev] \ .[dev] \
certbot-apache \ certbot-apache \
certbot-dns-cloudflare \ certbot-dns-cloudflare \
certbot-dns-cloudxns \
certbot-dns-digitalocean \ certbot-dns-digitalocean \
certbot-dns-dnsimple \
certbot-dns-dnsmadeeasy \
certbot-dns-google \ certbot-dns-google \
certbot-dns-luadns \
certbot-dns-nsone \
certbot-dns-rfc2136 \ certbot-dns-rfc2136 \
certbot-dns-route53 \ certbot-dns-route53 \
certbot-nginx \ certbot-nginx \
letshelp-certbot letshelp-certbot
non_py26_packages =
certbot-dns-cloudxns \
certbot-dns-dnsimple \
certbot-dns-dnsmadeeasy \
certbot-dns-luadns \
certbot-dns-nsone
all_packages =
{[base]py26_packages} {[base]non_py26_packages}
install_packages = install_packages =
{toxinidir}/tools/pip_install_editable.sh {[base]all_packages} {toxinidir}/tools/pip_install_editable.sh {[base]all_packages}
source_paths = source_paths =
@@ -54,32 +51,15 @@ source_paths =
letshelp-certbot/letshelp_certbot letshelp-certbot/letshelp_certbot
tests/lock_test.py tests/lock_test.py
[testenv:py26]
commands =
{[base]install_and_test} {[base]py26_packages}
python tests/lock_test.py
deps =
setuptools==36.8.0
wheel==0.29.0
passenv = TRAVIS
[testenv] [testenv]
commands = commands =
{[testenv:py26]commands} {[base]install_and_test} {[base]all_packages}
{[base]install_and_test} {[base]non_py26_packages} python tests/lock_test.py
setenv = setenv =
PYTHONPATH = {toxinidir} PYTHONPATH = {toxinidir}
PYTHONHASHSEED = 0 PYTHONHASHSEED = 0
passenv = passenv =
{[testenv:py26]passenv} TRAVIS
[testenv:py33]
commands =
{[testenv]commands}
deps =
wheel==0.29.0
passenv =
{[testenv]passenv}
[testenv:py27-oldest] [testenv:py27-oldest]
commands = commands =
@@ -104,7 +84,6 @@ passenv =
{[testenv]passenv} {[testenv]passenv}
[testenv:lint] [testenv:lint]
# recent versions of pylint do not support Python 2.6 (#97, #187)
basepython = python2.7 basepython = python2.7
# separating into multiple invocations disables cross package # separating into multiple invocations disables cross package
# duplicate code checking; if one of the commands fails, others will # duplicate code checking; if one of the commands fails, others will