cloud-init-dev team mailing list archive
-
cloud-init-dev team
-
Mailing list archive
-
Message #00471
[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