← Back to team overview

cloud-init-dev team mailing list archive

[Merge] lp:~harlowja/cloud-init/six-2-3-compat into lp:cloud-init

 

Joshua Harlow has proposed merging lp:~harlowja/cloud-init/six-2-3-compat into lp:cloud-init.

Requested reviews:
  cloud init development team (cloud-init-dev)

For more details, see:
https://code.launchpad.net/~harlowja/cloud-init/six-2-3-compat/+merge/224933

This starts along the path of dual python2/3 compatability.
-- 
https://code.launchpad.net/~harlowja/cloud-init/six-2-3-compat/+merge/224933
Your team cloud init development team is requested to review the proposed merge of lp:~harlowja/cloud-init/six-2-3-compat into lp:cloud-init.
=== modified file 'cloudinit/ec2_utils.py'
--- cloudinit/ec2_utils.py	2014-02-08 20:20:33 +0000
+++ cloudinit/ec2_utils.py	2014-06-29 18:03:24 +0000
@@ -16,6 +16,11 @@
 #    You should have received a copy of the GNU General Public License
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+<<<<<<< TREE
+=======
+from six.moves.urllib import parse
+
+>>>>>>> MERGE-SOURCE
 import functools
 import httplib
 import json
@@ -37,6 +42,19 @@
     return False
 
 
+<<<<<<< TREE
+=======
+def combine_url(base, add_on):
+    base_parsed = list(parse.urlparse(base))
+    path = base_parsed[2]
+    if path and not path.endswith("/"):
+        path += "/"
+    path += parse.quote(str(add_on), safe="/:")
+    base_parsed[2] = path
+    return parse.urlunparse(base_parsed)
+
+
+>>>>>>> MERGE-SOURCE
 # See: http://bit.ly/TyoUQs
 #
 class MetadataMaterializer(object):

=== modified file 'cloudinit/helpers.py'
--- cloudinit/helpers.py	2014-01-17 20:12:31 +0000
+++ cloudinit/helpers.py	2014-06-29 18:03:24 +0000
@@ -23,10 +23,12 @@
 from time import time
 
 import contextlib
-import io
 import os
 
-from ConfigParser import (NoSectionError, NoOptionError, RawConfigParser)
+import six
+
+from six.moves.configparser import (NoSectionError, NoOptionError)
+from six.moves.configparser import RawConfigParser
 
 from cloudinit.settings import (PER_INSTANCE, PER_ALWAYS, PER_ONCE,
                                 CFG_ENV_NAME)
@@ -448,11 +450,9 @@
         return RawConfigParser.getint(self, section, option)
 
     def stringify(self, header=None):
-        contents = ''
-        with io.BytesIO() as outputstream:
-            self.write(outputstream)
-            outputstream.flush()
-            contents = outputstream.getvalue()
-            if header:
-                contents = "\n".join([header, contents])
+        buf = six.StringIO()
+        self.write(buf)
+        contents = buf.getvalue()
+        if header:
+            contents = "\n".join([header, contents])
         return contents

=== modified file 'cloudinit/log.py'
--- cloudinit/log.py	2013-04-17 16:42:55 +0000
+++ cloudinit/log.py	2014-06-29 18:03:24 +0000
@@ -28,7 +28,7 @@
 import os
 import sys
 
-from StringIO import StringIO
+import six
 
 # Logging levels for easy access
 CRITICAL = logging.CRITICAL
@@ -98,7 +98,7 @@
                 # is acting as a file)
                 pass
             else:
-                log_cfg = StringIO(log_cfg)
+                log_cfg = six.StringIO(log_cfg)
             # Attempt to load its config
             logging.config.fileConfig(log_cfg)
             # The first one to work wins!

=== modified file 'cloudinit/signal_handler.py'
--- cloudinit/signal_handler.py	2012-09-19 20:33:56 +0000
+++ cloudinit/signal_handler.py	2014-06-29 18:03:24 +0000
@@ -22,7 +22,7 @@
 import signal
 import sys
 
-from StringIO import StringIO
+import six
 
 from cloudinit import log as logging
 from cloudinit import util
@@ -55,7 +55,7 @@
 def _handle_exit(signum, frame):
     (msg, rc) = EXIT_FOR[signum]
     msg = msg % ({'version': vr.version()})
-    contents = StringIO()
+    contents = six.StringIO()
     contents.write("%s\n" % (msg))
     _pprint_frame(frame, 1, BACK_FRAME_TRACE_DEPTH, contents)
     util.multi_log(contents.getvalue(),

=== modified file 'cloudinit/stages.py'
--- cloudinit/stages.py	2014-02-13 18:53:08 +0000
+++ cloudinit/stages.py	2014-06-29 18:03:24 +0000
@@ -20,12 +20,12 @@
 #    You should have received a copy of the GNU General Public License
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-import cPickle as pickle
-
 import copy
 import os
 import sys
 
+from six.moves import cPickle as pickle
+
 from cloudinit.settings import (PER_INSTANCE, FREQUENCIES, CLOUD_CONFIG)
 
 from cloudinit import handlers

=== modified file 'cloudinit/url_helper.py'
--- cloudinit/url_helper.py	2014-02-13 17:13:42 +0000
+++ cloudinit/url_helper.py	2014-06-29 18:03:24 +0000
@@ -25,9 +25,9 @@
 import urllib
 
 import requests
-from requests import exceptions
+from requests import exceptions as request_exceptions
 
-from urlparse import (urlparse, urlunparse)
+from six.moves.urllib import parse
 
 from cloudinit import log as logging
 from cloudinit import version
@@ -54,13 +54,13 @@
 
 
 def _cleanurl(url):
-    parsed_url = list(urlparse(url, scheme='http'))  # pylint: disable=E1123
+    parsed_url = list(parse.urlparse(url, scheme='http'))  # pylint: disable=E1123
     if not parsed_url[1] and parsed_url[2]:
         # Swap these since this seems to be a common
         # occurrence when given urls like 'www.google.com'
         parsed_url[1] = parsed_url[2]
         parsed_url[2] = ''
-    return urlunparse(parsed_url)
+    return parse.urlunparse(parsed_url)
 
 
 def combine_url(base, *add_ons):
@@ -148,9 +148,20 @@
             self.headers = {}
 
 
+<<<<<<< TREE
 def _get_ssl_args(url, ssl_details):
     ssl_args = {}
     scheme = urlparse(url).scheme  # pylint: disable=E1101
+=======
+def readurl(url, data=None, timeout=None, retries=0, sec_between=1,
+            headers=None, headers_cb=None, ssl_details=None,
+            check_status=True, allow_redirects=True):
+    url = _cleanurl(url)
+    req_args = {
+        'url': url,
+    }
+    scheme = parse.urlparse(url).scheme  # pylint: disable=E1101
+>>>>>>> MERGE-SOURCE
     if scheme == 'https' and ssl_details:
         if not SSL_ENABLED:
             LOG.warn("SSL is not supported in requests v%s, "
@@ -235,15 +246,15 @@
             # subclass for responses, so add our own backward-compat
             # attrs
             return UrlResponse(r)
-        except exceptions.RequestException as e:
-            if (isinstance(e, (exceptions.HTTPError))
+        except request_exceptions.RequestException as e:
+            if (isinstance(e, (request_exceptions.HTTPError))
                 and hasattr(e, 'response')  # This appeared in v 0.10.8
                 and hasattr(e.response, 'status_code')):
                 excps.append(UrlError(e, code=e.response.status_code,
                                       headers=e.response.headers))
             else:
                 excps.append(UrlError(e))
-                if SSL_ENABLED and isinstance(e, exceptions.SSLError):
+                if SSL_ENABLED and isinstance(e, request_exceptions.SSLError):
                     # ssl exceptions are not going to get fixed by waiting a
                     # few seconds
                     break

=== modified file 'cloudinit/util.py'
--- cloudinit/util.py	2014-02-24 22:20:12 +0000
+++ cloudinit/util.py	2014-06-29 18:03:24 +0000
@@ -22,8 +22,6 @@
 #
 # pylint: disable=C0302
 
-from StringIO import StringIO
-
 import contextlib
 import copy as obj_copy
 import ctypes
@@ -47,7 +45,9 @@
 import sys
 import tempfile
 import time
-import urlparse
+
+import six
+from six.moves.urllib import parse
 
 import yaml
 
@@ -296,9 +296,12 @@
     return fn
 
 
-def decomp_gzip(data, quiet=True):
+def decomp_gzip(data, quiet=True, encoding=None):
     try:
-        buf = StringIO(str(data))
+        if encoding:
+            buf = six.BytesIO(six.binary_type(data, encoding=encoding))
+        else:
+            buf = six.BytesIO(data)
         with contextlib.closing(gzip.GzipFile(None, "rb", 1, buf)) as gh:
             return gh.read()
     except Exception as e:
@@ -536,7 +539,7 @@
     pieces.append(query or '')
     pieces.append(fragment or '')
 
-    return urlparse.urlunparse(pieces)
+    return parse.urlunparse(pieces)
 
 
 def mergemanydict(srcs, reverse=False):
@@ -982,7 +985,11 @@
 
 def is_resolvable_url(url):
     """determine if this url is resolvable (existing or ip)."""
+<<<<<<< TREE
     return is_resolvable(urlparse.urlparse(url).hostname)
+=======
+    return (is_resolvable(parse.urlparse(url).hostname))
+>>>>>>> MERGE-SOURCE
 
 
 def search_for_mirror(candidates):
@@ -1074,9 +1081,9 @@
     return out_list
 
 
-def load_file(fname, read_cb=None, quiet=False):
+def load_file(fname, read_cb=None, quiet=False, encoding='utf-8'):
     LOG.debug("Reading from %s (quiet=%s)", fname, quiet)
-    ofh = StringIO()
+    ofh = six.BytesIO()
     try:
         with open(fname, 'rb') as ifh:
             pipe_in_out(ifh, ofh, chunk_cb=read_cb)
@@ -1087,6 +1094,8 @@
             raise
     contents = ofh.getvalue()
     LOG.debug("Read %s bytes from %s", len(contents), fname)
+    if encoding:
+        contents = contents.decode(encoding)
     return contents
 
 
@@ -1472,10 +1481,11 @@
             os.chmod(path, real_mode)
 
 
-def write_file(filename, content, mode=0644, omode="wb"):
+def write_file(filename, content, mode=0644, omode="wb", encoding='utf-8'):
     """
     Writes a file with the given content and sets the file mode as specified.
-    Resotres the SELinux context if possible.
+
+    Restores the SELinux context if possible.
 
     @param filename: The full path of the file to write.
     @param content: The content to write to the file.
@@ -1487,6 +1497,8 @@
                filename, omode, mode, len(content))
     with SeLinuxGuard(path=filename):
         with open(filename, omode) as fh:
+            if encoding:
+                content = six.binary_type(content, encoding=encoding)
             fh.write(content)
             fh.flush()
     chmod(filename, mode)

=== modified file 'requirements.txt'
--- requirements.txt	2014-02-12 10:14:49 +0000
+++ requirements.txt	2014-06-29 18:03:24 +0000
@@ -31,3 +31,8 @@
 
 # For patching pieces of cloud-config together
 jsonpatch
+
+# For python 2 and 3 cross-compat, cloud-init is used in distros which
+# are still python 2 based (rhel, centos...) while it is also used in distros
+# which are python 3 based (newer ubuntu, linux mint...)
+six