From cdca314298392c2838eb39796d7d24e6bfebaa18 Mon Sep 17 00:00:00 2001 From: Stephen Holsapple Date: Mon, 14 Apr 2014 14:43:12 -0700 Subject: [PATCH] Remove incompatible SSL option in Python 2.6 An exposed SSL option, `ciphers`, was added in Python 2.7 and breaks older versions of Python with an unexpected kwargs error. I'm not sure if this is the best way to fix this, and I'm happy to consider other approachs. Some things I'm a bit up in the air about are: i) This is only broken for Python 2.6 and older whose ssl module doesn't expose this. Do the other types of workers not use ssl module, and thus might be able to make use of the `cipher` kwarg? ii) Should we silently or explicity fail? I couldn't find a nice way to do this because the configuration setting has a default value and resulted in stringy code to special case the one setting`. What I would really like to do would add a "python_version" validator that could intelligently handle this, but I went off into the weeds figuring out how the SettingsMeta class works. :) --- gunicorn/config.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/gunicorn/config.py b/gunicorn/config.py index f272bcc9..bb6f2b61 100644 --- a/gunicorn/config.py +++ b/gunicorn/config.py @@ -140,19 +140,24 @@ class Config(object): def is_ssl(self): return self.certfile or self.keyfile - @property - def ssl_options(self): - opts = {} - - for attr in('certfile', 'keyfile', 'cert_reqs', 'ssl_version', \ - 'ca_certs', 'suppress_ragged_eofs', 'do_handshake_on_connect', - 'ciphers'): - + def _load_attrs(self, attrs, version=sys.version_info): + for attr in attrs: # suppress_ragged_eofs/do_handshake_on_connect are booleans that can # be False hence we use hasattr instead of getattr(self, attr, None). - if hasattr(self, attr): - value = getattr(self, attr) - opts[attr] = value + if hasattr(self, attr) and version >= sys.version_info: + yield (attr, getattr(self, attr)) + + @property + def ssl_options(self): + + opts = {} + + opts.update(self._load_attrs(('certfile', 'keyfile', 'cert_reqs', 'ssl_version', + 'ca_certs', 'suppress_ragged_eofs', 'do_handshake_on_connect'))) + + # The `ciphers` kwarg was only available in Python 2.7, so don't make + # it available for us in older versions on Python. + opts.update(self._load_attrs(('ciphers'), version=(2, 7))) return opts @@ -1560,4 +1565,6 @@ class Ciphers(Setting): default = 'TLSv1' desc = """\ Ciphers to use (see stdlib ssl module's) + + Note, this value is only available in Python 2.7+ and is ignored in older versions of Python. """