libcloud-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From to...@apache.org
Subject svn commit: r1210045 - in /libcloud/trunk: ./ libcloud/ libcloud/common/ libcloud/compute/ libcloud/compute/drivers/ libcloud/dns/ libcloud/dns/drivers/ libcloud/loadbalancer/ libcloud/loadbalancer/drivers/ libcloud/storage/ libcloud/storage/drivers/ l...
Date Sun, 04 Dec 2011 01:59:17 GMT
Author: tomaz
Date: Sun Dec  4 01:59:15 2011
New Revision: 1210045

URL: http://svn.apache.org/viewvc?rev=1210045&view=rev
Log:
Re-organize libcloud.utils modules and create a new libcloud.utils package.
Update affected code.

Added:
    libcloud/trunk/libcloud/utils/
    libcloud/trunk/libcloud/utils/__init__.py
    libcloud/trunk/libcloud/utils/files.py
    libcloud/trunk/libcloud/utils/misc.py
    libcloud/trunk/libcloud/utils/py3.py
    libcloud/trunk/libcloud/utils/xml.py
Removed:
    libcloud/trunk/libcloud/utils.py
Modified:
    libcloud/trunk/CHANGES
    libcloud/trunk/libcloud/common/base.py
    libcloud/trunk/libcloud/common/cloudstack.py
    libcloud/trunk/libcloud/common/gandi.py
    libcloud/trunk/libcloud/common/gogrid.py
    libcloud/trunk/libcloud/common/openstack.py
    libcloud/trunk/libcloud/compute/base.py
    libcloud/trunk/libcloud/compute/deployment.py
    libcloud/trunk/libcloud/compute/drivers/bluebox.py
    libcloud/trunk/libcloud/compute/drivers/brightbox.py
    libcloud/trunk/libcloud/compute/drivers/cloudsigma.py
    libcloud/trunk/libcloud/compute/drivers/ec2.py
    libcloud/trunk/libcloud/compute/drivers/ecp.py
    libcloud/trunk/libcloud/compute/drivers/elasticstack.py
    libcloud/trunk/libcloud/compute/drivers/gogrid.py
    libcloud/trunk/libcloud/compute/drivers/ibm_sbc.py
    libcloud/trunk/libcloud/compute/drivers/linode.py
    libcloud/trunk/libcloud/compute/drivers/opennebula.py
    libcloud/trunk/libcloud/compute/drivers/openstack.py
    libcloud/trunk/libcloud/compute/drivers/opsource.py
    libcloud/trunk/libcloud/compute/drivers/slicehost.py
    libcloud/trunk/libcloud/compute/drivers/softlayer.py
    libcloud/trunk/libcloud/compute/drivers/vcloud.py
    libcloud/trunk/libcloud/compute/drivers/voxel.py
    libcloud/trunk/libcloud/compute/drivers/vpsnet.py
    libcloud/trunk/libcloud/compute/providers.py
    libcloud/trunk/libcloud/dns/drivers/linode.py
    libcloud/trunk/libcloud/dns/drivers/rackspace.py
    libcloud/trunk/libcloud/dns/drivers/zerigo.py
    libcloud/trunk/libcloud/dns/providers.py
    libcloud/trunk/libcloud/httplib_ssl.py
    libcloud/trunk/libcloud/loadbalancer/drivers/cloudstack.py
    libcloud/trunk/libcloud/loadbalancer/drivers/gogrid.py
    libcloud/trunk/libcloud/loadbalancer/drivers/rackspace.py
    libcloud/trunk/libcloud/loadbalancer/providers.py
    libcloud/trunk/libcloud/storage/base.py
    libcloud/trunk/libcloud/storage/drivers/atmos.py
    libcloud/trunk/libcloud/storage/drivers/cloudfiles.py
    libcloud/trunk/libcloud/storage/drivers/dummy.py
    libcloud/trunk/libcloud/storage/drivers/google_storage.py
    libcloud/trunk/libcloud/storage/drivers/s3.py
    libcloud/trunk/libcloud/storage/providers.py
    libcloud/trunk/setup.py
    libcloud/trunk/test/compute/test_cloudsigma.py
    libcloud/trunk/test/storage/test_atmos.py
    libcloud/trunk/test/storage/test_cloudfiles.py
    libcloud/trunk/test/test_utils.py

Modified: libcloud/trunk/CHANGES
URL: http://svn.apache.org/viewvc/libcloud/trunk/CHANGES?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/CHANGES (original)
+++ libcloud/trunk/CHANGES Sun Dec  4 01:59:15 2011
@@ -1,4 +1,4 @@
-                                                        -*- coding: utf-8 -*-
+                                    -*- coding: utf-8 -*-
 
 Changes with Apache Libcloud in development:
   *) General:
@@ -62,7 +62,7 @@ Changes with Apache Libcloud in developm
        additional compute tests validating functionality; LIBCLOUD-121
        [Hutson Betts]
 
-  *) Load-baancer:
+  *) Load-balancer:
 
     - Add ex_member_address argument to the Rackspace driver list_balancers
       method. If this argument is provided, only loadbalancers which have a

Modified: libcloud/trunk/libcloud/common/base.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/common/base.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/common/base.py (original)
+++ libcloud/trunk/libcloud/common/base.py Sun Dec  4 01:59:15 2011
@@ -27,12 +27,12 @@ except:
 
 import libcloud
 
-from libcloud.py3 import urllib
-from libcloud.py3 import httplib
-from libcloud.py3 import urlparse
-from libcloud.py3 import urlencode
-from libcloud.py3 import StringIO
-from libcloud.py3 import u
+from libcloud.utils.py3 import urllib
+from libcloud.utils.py3 import httplib
+from libcloud.utils.py3 import urlparse
+from libcloud.utils.py3 import urlencode
+from libcloud.utils.py3 import StringIO
+from libcloud.utils.py3 import u
 
 from libcloud.common.types import LibcloudError, MalformedResponseError
 

Modified: libcloud/trunk/libcloud/common/cloudstack.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/common/cloudstack.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/common/cloudstack.py (original)
+++ libcloud/trunk/libcloud/common/cloudstack.py Sun Dec  4 01:59:15 2011
@@ -17,8 +17,8 @@ import base64
 import hashlib
 import hmac
 
-from libcloud.py3 import urlencode
-from libcloud.py3 import b
+from libcloud.utils.py3 import urlencode
+from libcloud.utils.py3 import b
 
 from libcloud.common.base import ConnectionUserAndKey, PollingConnection
 from libcloud.common.base import JsonResponse

Modified: libcloud/trunk/libcloud/common/gandi.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/common/gandi.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/common/gandi.py (original)
+++ libcloud/trunk/libcloud/common/gandi.py Sun Dec  4 01:59:15 2011
@@ -19,8 +19,8 @@ Gandi driver base classes
 import time
 import hashlib
 
-from libcloud.py3 import xmlrpclib
-from libcloud.py3 import b
+from libcloud.utils.py3 import xmlrpclib
+from libcloud.utils.py3 import b
 
 import libcloud
 from libcloud.common.base import ConnectionKey

Modified: libcloud/trunk/libcloud/common/gogrid.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/common/gogrid.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/common/gogrid.py (original)
+++ libcloud/trunk/libcloud/common/gogrid.py Sun Dec  4 01:59:15 2011
@@ -16,7 +16,7 @@
 import hashlib
 import time
 
-from libcloud.py3 import b
+from libcloud.utils.py3 import b
 
 from libcloud.common.types import InvalidCredsError, LibcloudError
 from libcloud.common.types import MalformedResponseError

Modified: libcloud/trunk/libcloud/common/openstack.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/common/openstack.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/common/openstack.py (original)
+++ libcloud/trunk/libcloud/common/openstack.py Sun Dec  4 01:59:15 2011
@@ -18,8 +18,8 @@ Common utilities for OpenStack
 """
 import sys
 
-from libcloud.py3 import httplib
-from libcloud.py3 import urlparse
+from libcloud.utils.py3 import httplib
+from libcloud.utils.py3 import urlparse
 
 from libcloud.common.base import ConnectionUserAndKey, Response
 from libcloud.compute.types import LibcloudError, InvalidCredsError, MalformedResponseError

Modified: libcloud/trunk/libcloud/compute/base.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/base.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/base.py (original)
+++ libcloud/trunk/libcloud/compute/base.py Sun Dec  4 01:59:15 2011
@@ -25,7 +25,7 @@ import socket
 import struct
 import binascii
 
-from libcloud.py3 import b
+from libcloud.utils.py3 import b
 
 import libcloud.compute.ssh
 from libcloud.pricing import get_size_price

Modified: libcloud/trunk/libcloud/compute/deployment.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/deployment.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/deployment.py (original)
+++ libcloud/trunk/libcloud/compute/deployment.py Sun Dec  4 01:59:15 2011
@@ -19,7 +19,7 @@ Provides generic deployment steps for ma
 import os
 import binascii
 
-from libcloud.py3 import basestring
+from libcloud.utils.py3 import basestring
 
 class Deployment(object):
     """

Modified: libcloud/trunk/libcloud/compute/drivers/bluebox.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/bluebox.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/bluebox.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/bluebox.py Sun Dec  4 01:59:15 2011
@@ -23,11 +23,11 @@ Blue Box API documentation    https://bo
 """
 
 import copy
-from libcloud.py3 import urllib
+from libcloud.utils.py3 import urllib
 import base64
 
-from libcloud.py3 import urlencode
-from libcloud.py3 import b
+from libcloud.utils.py3 import urlencode
+from libcloud.utils.py3 import b
 
 from libcloud.common.base import JsonResponse, ConnectionUserAndKey
 from libcloud.compute.providers import Provider

Modified: libcloud/trunk/libcloud/compute/drivers/brightbox.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/brightbox.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/brightbox.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/brightbox.py Sun Dec  4 01:59:15 2011
@@ -15,10 +15,10 @@
 """
 Brightbox Driver
 """
-from libcloud.py3 import httplib
+from libcloud.utils.py3 import httplib
 import base64
 
-from libcloud.py3 import b
+from libcloud.utils.py3 import b
 
 from libcloud.common.base import ConnectionUserAndKey, JsonResponse
 from libcloud.compute.types import Provider, NodeState, InvalidCredsError

Modified: libcloud/trunk/libcloud/compute/drivers/cloudsigma.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/cloudsigma.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/cloudsigma.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/cloudsigma.py Sun Dec  4 01:59:15 2011
@@ -20,10 +20,10 @@ import re
 import time
 import base64
 
-from libcloud.py3 import b
+from libcloud.utils.py3 import b
 
 
-from libcloud.utils import str2dicts, str2list, dict2str
+from libcloud.utils.misc import str2dicts, str2list, dict2str
 from libcloud.common.base import ConnectionUserAndKey, Response
 from libcloud.common.types import InvalidCredsError
 from libcloud.compute.types import NodeState, Provider

Modified: libcloud/trunk/libcloud/compute/drivers/ec2.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/ec2.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/ec2.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/ec2.py Sun Dec  4 01:59:15 2011
@@ -28,10 +28,10 @@ import copy
 from hashlib import sha256
 from xml.etree import ElementTree as ET
 
-from libcloud.py3 import urlquote
-from libcloud.py3 import b
+from libcloud.utils.py3 import urlquote
+from libcloud.utils.py3 import b
 
-from libcloud.utils import fixxpath, findtext, findattr, findall
+from libcloud.utils.xml import fixxpath, findtext, findattr, findall
 from libcloud.common.base import ConnectionUserAndKey
 from libcloud.common.aws import AWSBaseResponse
 from libcloud.common.types import (InvalidCredsError, MalformedResponseError,

Modified: libcloud/trunk/libcloud/compute/drivers/ecp.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/ecp.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/ecp.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/ecp.py Sun Dec  4 01:59:15 2011
@@ -22,9 +22,9 @@ import os
 import socket
 import binascii
 
-from libcloud.py3 import httplib
-from libcloud.py3 import b
-from libcloud.py3 import u
+from libcloud.utils.py3 import httplib
+from libcloud.utils.py3 import b
+from libcloud.utils.py3 import u
 
 # JSON is included in the standard library starting with Python 2.6.  For 2.5
 # and 2.4, there's a simplejson egg at: http://pypi.python.org/pypi/simplejson

Modified: libcloud/trunk/libcloud/compute/drivers/elasticstack.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/elasticstack.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/elasticstack.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/elasticstack.py Sun Dec  4 01:59:15 2011
@@ -22,8 +22,8 @@ import re
 import time
 import base64
 
-from libcloud.py3 import httplib
-from libcloud.py3 import b
+from libcloud.utils.py3 import httplib
+from libcloud.utils.py3 import b
 
 try:
     import simplejson as json

Modified: libcloud/trunk/libcloud/compute/drivers/gogrid.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/gogrid.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/gogrid.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/gogrid.py Sun Dec  4 01:59:15 2011
@@ -19,7 +19,7 @@ import time
 import hashlib
 import copy
 
-from libcloud.py3 import b
+from libcloud.utils.py3 import b
 
 from libcloud.common.types import InvalidCredsError, LibcloudError
 from libcloud.common.gogrid import GoGridConnection, BaseGoGridDriver

Modified: libcloud/trunk/libcloud/compute/drivers/ibm_sbc.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/ibm_sbc.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/ibm_sbc.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/ibm_sbc.py Sun Dec  4 01:59:15 2011
@@ -17,8 +17,8 @@ Driver for the IBM Developer Cloud.
 """
 import base64, urllib
 
-from libcloud.py3 import urlencode
-from libcloud.py3 import b
+from libcloud.utils.py3 import urlencode
+from libcloud.utils.py3 import b
 
 from libcloud.common.base import XmlResponse, ConnectionUserAndKey
 from libcloud.common.types import InvalidCredsError

Modified: libcloud/trunk/libcloud/compute/drivers/linode.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/linode.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/linode.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/linode.py Sun Dec  4 01:59:15 2011
@@ -38,8 +38,8 @@ import binascii
 
 from copy import copy
 
-from libcloud.py3 import PY3
-from libcloud.py3 import u
+from libcloud.utils.py3 import PY3
+from libcloud.utils.py3 import u
 
 from libcloud.common.linode import (API_ROOT, LinodeException, LinodeConnection,
     LINODE_PLAN_IDS)

Modified: libcloud/trunk/libcloud/compute/drivers/opennebula.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/opennebula.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/opennebula.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/opennebula.py Sun Dec  4 01:59:15 2011
@@ -31,9 +31,9 @@ from xml.etree import ElementTree as ET
 from base64 import b64encode
 import hashlib
 
-from libcloud.py3 import httplib
-from libcloud.py3 import next
-from libcloud.py3 import b
+from libcloud.utils.py3 import httplib
+from libcloud.utils.py3 import next
+from libcloud.utils.py3 import b
 
 from libcloud.compute.base import NodeState, NodeDriver, Node, NodeLocation
 from libcloud.common.base import ConnectionUserAndKey, XmlResponse

Modified: libcloud/trunk/libcloud/compute/drivers/openstack.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/openstack.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/openstack.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/openstack.py Sun Dec  4 01:59:15 2011
@@ -27,9 +27,9 @@ import os
 
 import warnings
 
-from libcloud.py3 import httplib
-from libcloud.py3 import b
-from libcloud.py3 import next
+from libcloud.utils.py3 import httplib
+from libcloud.utils.py3 import b
+from libcloud.utils.py3 import next
 
 import base64
 
@@ -42,7 +42,7 @@ from libcloud.compute.base import NodeSi
 from libcloud.compute.base import NodeDriver, Node, NodeLocation
 from libcloud.pricing import get_size_price
 from libcloud.common.base import Response
-from libcloud.utils import findall
+from libcloud.utils.xml import findall
 
 __all__ = [
     'OpenStack_1_0_Response',

Modified: libcloud/trunk/libcloud/compute/drivers/opsource.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/opsource.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/opsource.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/opsource.py Sun Dec  4 01:59:15 2011
@@ -18,14 +18,14 @@ Opsource Driver
 from xml.etree import ElementTree as ET
 from base64 import b64encode
 
-from libcloud.py3 import httplib
-from libcloud.py3 import b
+from libcloud.utils.py3 import httplib
+from libcloud.utils.py3 import b
 
 from libcloud.compute.base import NodeDriver, Node, NodeAuthPassword
 from libcloud.compute.base import NodeSize, NodeImage, NodeLocation
 from libcloud.common.types import LibcloudError, InvalidCredsError
 from libcloud.common.base import ConnectionUserAndKey, XmlResponse
-from libcloud.utils import fixxpath, findtext, findall
+from libcloud.utils.xml import fixxpath, findtext, findall
 from libcloud.compute.types import NodeState, Provider
 
 # Roadmap / TODO:

Modified: libcloud/trunk/libcloud/compute/drivers/slicehost.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/slicehost.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/slicehost.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/slicehost.py Sun Dec  4 01:59:15 2011
@@ -21,7 +21,7 @@ import socket
 from xml.etree import ElementTree as ET
 from xml.parsers.expat import ExpatError
 
-from libcloud.py3 import b
+from libcloud.utils.py3 import b
 
 from libcloud.common.base import ConnectionKey, XmlResponse
 from libcloud.compute.types import NodeState, Provider, InvalidCredsError

Modified: libcloud/trunk/libcloud/compute/drivers/softlayer.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/softlayer.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/softlayer.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/softlayer.py Sun Dec  4 01:59:15 2011
@@ -20,7 +20,7 @@ import time
 
 import libcloud
 
-from libcloud.py3 import xmlrpclib
+from libcloud.utils.py3 import xmlrpclib
 
 from libcloud.common.types import InvalidCredsError, LibcloudError
 from libcloud.compute.types import Provider, NodeState

Modified: libcloud/trunk/libcloud/compute/drivers/vcloud.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/vcloud.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/vcloud.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/vcloud.py Sun Dec  4 01:59:15 2011
@@ -16,9 +16,9 @@
 VMware vCloud driver.
 """
 import base64
-from libcloud.py3 import httplib
-from libcloud.py3 import urlparse
-from libcloud.py3 import b
+from libcloud.utils.py3 import httplib
+from libcloud.utils.py3 import urlparse
+from libcloud.utils.py3 import b
 
 urlparse = urlparse.urlparse
 
@@ -42,9 +42,6 @@ VIRTUAL_MEMORY_VALS = [512] + [1024 * i 
 
 DEFAULT_TASK_COMPLETION_TIMEOUT = 600
 
-def get_url_path(url):
-    return urlparse(url.strip()).path
-
 def fixxpath(root, xpath):
     """ElementTree wants namespaces in its xpaths, so here we add them."""
     namespace, root_tag = root.tag[1:].split("}", 1)
@@ -52,6 +49,9 @@ def fixxpath(root, xpath):
                             for e in xpath.split("/")])
     return fixed_xpath
 
+def get_url_path(url):
+    return urlparse(url.strip()).path
+
 class InstantiateVAppXML(object):
 
     def __init__(self, name, template, net_href, cpus, memory,

Modified: libcloud/trunk/libcloud/compute/drivers/voxel.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/voxel.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/voxel.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/voxel.py Sun Dec  4 01:59:15 2011
@@ -19,7 +19,7 @@ Voxel VoxCloud driver
 import datetime
 import hashlib
 
-from libcloud.py3 import b
+from libcloud.utils.py3 import b
 
 from libcloud.common.base import XmlResponse, ConnectionUserAndKey
 from libcloud.common.types import InvalidCredsError

Modified: libcloud/trunk/libcloud/compute/drivers/vpsnet.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/vpsnet.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/vpsnet.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/vpsnet.py Sun Dec  4 01:59:15 2011
@@ -22,7 +22,7 @@ try:
 except ImportError:
     import json
 
-from libcloud.py3 import b
+from libcloud.utils.py3 import b
 
 from libcloud.common.base import ConnectionUserAndKey, JsonResponse
 from libcloud.common.types import InvalidCredsError, MalformedResponseError

Modified: libcloud/trunk/libcloud/compute/providers.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/providers.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/providers.py (original)
+++ libcloud/trunk/libcloud/compute/providers.py Sun Dec  4 01:59:15 2011
@@ -16,7 +16,7 @@
 Provider related utilities
 """
 
-from libcloud.utils import get_driver as _get_provider_driver
+from libcloud.utils.misc import get_driver as _get_provider_driver
 from libcloud.compute.types import Provider
 
 __all__ = [

Modified: libcloud/trunk/libcloud/dns/drivers/linode.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/dns/drivers/linode.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/dns/drivers/linode.py (original)
+++ libcloud/trunk/libcloud/dns/drivers/linode.py Sun Dec  4 01:59:15 2011
@@ -18,7 +18,7 @@ __all__ = [
 ]
 
 
-from libcloud.utils import merge_valid_keys, get_new_obj
+from libcloud.utils.misc import merge_valid_keys, get_new_obj
 from libcloud.common.linode import (API_ROOT, LinodeException,
                                     LinodeConnection, LinodeResponse,
                                     LINODE_PLAN_IDS)

Modified: libcloud/trunk/libcloud/dns/drivers/rackspace.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/dns/drivers/rackspace.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/dns/drivers/rackspace.py (original)
+++ libcloud/trunk/libcloud/dns/drivers/rackspace.py Sun Dec  4 01:59:15 2011
@@ -18,12 +18,12 @@ __all__ = [
     'RackspaceUKDNSDriver'
 ]
 
-from libcloud.py3 import httplib
+from libcloud.utils.py3 import httplib
 import copy
 
 from libcloud.common.base import PollingConnection
 from libcloud.common.types import LibcloudError
-from libcloud.utils import merge_valid_keys, get_new_obj
+from libcloud.utils.misc import merge_valid_keys, get_new_obj
 from libcloud.common.rackspace import AUTH_URL_US, AUTH_URL_UK
 from libcloud.compute.drivers.openstack import OpenStack_1_1_Connection
 from libcloud.compute.drivers.openstack import OpenStack_1_1_Response

Modified: libcloud/trunk/libcloud/dns/drivers/zerigo.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/dns/drivers/zerigo.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/dns/drivers/zerigo.py (original)
+++ libcloud/trunk/libcloud/dns/drivers/zerigo.py Sun Dec  4 01:59:15 2011
@@ -21,13 +21,13 @@ __all__ = [
 import copy
 import base64
 
-from libcloud.py3 import httplib
-from libcloud.py3 import b
+from libcloud.utils.py3 import httplib
+from libcloud.utils.py3 import b
 
 from xml.etree import ElementTree as ET
 
-from libcloud.utils import fixxpath, findtext, findattr, findall
-from libcloud.utils import merge_valid_keys, get_new_obj
+from libcloud.utils.misc import merge_valid_keys, get_new_obj
+from libcloud.utils.xml import findtext, findall
 from libcloud.common.base import XmlResponse, ConnectionUserAndKey
 from libcloud.common.types import InvalidCredsError, LibcloudError
 from libcloud.common.types import MalformedResponseError, LazyList

Modified: libcloud/trunk/libcloud/dns/providers.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/dns/providers.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/dns/providers.py (original)
+++ libcloud/trunk/libcloud/dns/providers.py Sun Dec  4 01:59:15 2011
@@ -13,7 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from libcloud.utils import get_driver as get_provider_driver
+from libcloud.utils.misc import get_driver as get_provider_driver
 from libcloud.dns.types import Provider
 
 DRIVERS = {

Modified: libcloud/trunk/libcloud/httplib_ssl.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/httplib_ssl.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/httplib_ssl.py (original)
+++ libcloud/trunk/libcloud/httplib_ssl.py Sun Dec  4 01:59:15 2011
@@ -23,7 +23,7 @@ import ssl
 import warnings
 
 import libcloud.security
-from libcloud.py3 import httplib
+from libcloud.utils.py3 import httplib
 
 class LibcloudHTTPSConnection(httplib.HTTPSConnection):
     """LibcloudHTTPSConnection

Modified: libcloud/trunk/libcloud/loadbalancer/drivers/cloudstack.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/loadbalancer/drivers/cloudstack.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/loadbalancer/drivers/cloudstack.py (original)
+++ libcloud/trunk/libcloud/loadbalancer/drivers/cloudstack.py Sun Dec  4 01:59:15 2011
@@ -18,7 +18,7 @@ from libcloud.common.cloudstack import C
 from libcloud.loadbalancer.base import LoadBalancer, Member, Driver, Algorithm
 from libcloud.loadbalancer.base import DEFAULT_ALGORITHM
 from libcloud.loadbalancer.types import State, LibcloudLBImmutableError
-from libcloud.utils import reverse_dict
+from libcloud.utils.misc import reverse_dict
 
 class CloudStackLBDriver(CloudStackDriverMixIn, Driver):
     """Driver for CloudStack load balancers."""

Modified: libcloud/trunk/libcloud/loadbalancer/drivers/gogrid.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/loadbalancer/drivers/gogrid.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/loadbalancer/drivers/gogrid.py (original)
+++ libcloud/trunk/libcloud/loadbalancer/drivers/gogrid.py Sun Dec  4 01:59:15 2011
@@ -14,15 +14,15 @@
 # limitations under the License.
 
 import time
-from libcloud.py3 import httplib
+from libcloud.utils.py3 import httplib
 
 try:
     import simplejson as json
 except ImportError:
     import json
 
+from libcloud.utils.misc import reverse_dict
 from libcloud.common.types import LibcloudError
-from libcloud.utils import reverse_dict
 from libcloud.common.gogrid import GoGridConnection, GoGridResponse, BaseGoGridDriver
 from libcloud.loadbalancer.base import LoadBalancer, Member, Driver, Algorithm
 from libcloud.loadbalancer.base import DEFAULT_ALGORITHM

Modified: libcloud/trunk/libcloud/loadbalancer/drivers/rackspace.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/loadbalancer/drivers/rackspace.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/loadbalancer/drivers/rackspace.py (original)
+++ libcloud/trunk/libcloud/loadbalancer/drivers/rackspace.py Sun Dec  4 01:59:15 2011
@@ -21,7 +21,7 @@ try:
 except ImportError:
     import json
 
-from libcloud.utils import reverse_dict
+from libcloud.utils.misc import reverse_dict
 from libcloud.common.base import JsonResponse
 from libcloud.loadbalancer.base import LoadBalancer, Member, Driver, Algorithm
 from libcloud.loadbalancer.base import DEFAULT_ALGORITHM

Modified: libcloud/trunk/libcloud/loadbalancer/providers.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/loadbalancer/providers.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/loadbalancer/providers.py (original)
+++ libcloud/trunk/libcloud/loadbalancer/providers.py Sun Dec  4 01:59:15 2011
@@ -13,7 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from libcloud.utils import get_driver as get_provider_driver
+from libcloud.utils.misc import get_driver as get_provider_driver
 from libcloud.loadbalancer.types import Provider
 
 __all__ = [

Modified: libcloud/trunk/libcloud/storage/base.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/storage/base.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/storage/base.py (original)
+++ libcloud/trunk/libcloud/storage/base.py Sun Dec  4 01:59:15 2011
@@ -24,11 +24,11 @@ import os.path                          
 import hashlib
 from os.path import join as pjoin
 
-from libcloud.py3 import httplib
-from libcloud.py3 import next
-from libcloud.py3 import b
+from libcloud.utils.py3 import httplib
+from libcloud.utils.py3 import next
+from libcloud.utils.py3 import b
 
-from libcloud import utils
+import libcloud.utils.files
 from libcloud.common.types import LibcloudError
 from libcloud.common.base import ConnectionUserAndKey, BaseDriver
 from libcloud.storage.types import ObjectDoesNotExistError
@@ -466,7 +466,7 @@ class StorageDriver(BaseDriver):
                 'overwrite_existing=False',
                 driver=self)
 
-        stream = utils.read_in_chunks(response, chunk_size)
+        stream = libcloud.utils.files.read_in_chunks(response, chunk_size)
 
         try:
             data_read = next(stream)
@@ -520,7 +520,7 @@ class StorageDriver(BaseDriver):
                 name = file_path
             else:
                 name = object_name
-            content_type, _ = utils.guess_file_mime_type(name)
+            content_type, _ = libcloud.utils.files.guess_file_mime_type(name)
 
             if not content_type:
                 raise AttributeError(
@@ -536,8 +536,8 @@ class StorageDriver(BaseDriver):
             else:
                 # Chunked transfer encoding is not supported. Need to buffer all
                 # the data in memory so we can determine file size.
-                iterator = utils.read_in_chunks(iterator=iterator)
-                data = utils.exhaust_iterator(iterator=iterator)
+                iterator = libcloud.utils.files.read_in_chunks(iterator=iterator)
+                data = libcloud.utils.files.exhaust_iterator(iterator=iterator)
 
                 file_size = len(data)
                 upload_func_kwargs['data'] = data
@@ -639,7 +639,7 @@ class StorageDriver(BaseDriver):
         if calculate_hash:
             data_hash = self._get_hash_function()
 
-        generator = utils.read_in_chunks(iterator, chunk_size)
+        generator = libcloud.utils.files.read_in_chunks(iterator, chunk_size)
 
         bytes_transferred = 0
         try:

Modified: libcloud/trunk/libcloud/storage/drivers/atmos.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/storage/drivers/atmos.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/storage/drivers/atmos.py (original)
+++ libcloud/trunk/libcloud/storage/drivers/atmos.py Sun Dec  4 01:59:15 2011
@@ -19,18 +19,18 @@ import hashlib
 import hmac
 import time
 
-from libcloud.py3 import PY3
-from libcloud.py3 import httplib
-from libcloud.py3 import urllib
-from libcloud.py3 import urlparse
-from libcloud.py3 import urlencode
-from libcloud.py3 import next
-from libcloud.py3 import b
+from libcloud.utils.py3 import PY3
+from libcloud.utils.py3 import httplib
+from libcloud.utils.py3 import urllib
+from libcloud.utils.py3 import urlparse
+from libcloud.utils.py3 import urlencode
+from libcloud.utils.py3 import next
+from libcloud.utils.py3 import b
 
 if PY3:
     from io import FileIO as file
 
-from libcloud import utils
+from libcloud.utils.files import read_in_chunks
 from libcloud.common.base import ConnectionUserAndKey, XmlResponse
 from libcloud.common.types import LazyList
 
@@ -257,7 +257,7 @@ class AtmosDriver(StorageDriver):
             iterator = iter(iterator)
 
         data_hash = hashlib.md5()
-        generator = utils.read_in_chunks(iterator, CHUNK_SIZE, True)
+        generator = read_in_chunks(iterator, CHUNK_SIZE, True)
         bytes_transferred = 0
         try:
             chunk = next(generator)
@@ -327,7 +327,7 @@ class AtmosDriver(StorageDriver):
         path = self._namespace_path(obj.container.name + '/' + obj.name)
         response = self.connection.request(path, method='GET', raw=True)
 
-        return self._get_object(obj=obj, callback=utils.read_in_chunks,
+        return self._get_object(obj=obj, callback=read_in_chunks,
                                 response=response,
                                 callback_kwargs={
                                     'iterator': response.response,

Modified: libcloud/trunk/libcloud/storage/drivers/cloudfiles.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/storage/drivers/cloudfiles.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/storage/drivers/cloudfiles.py (original)
+++ libcloud/trunk/libcloud/storage/drivers/cloudfiles.py Sun Dec  4 01:59:15 2011
@@ -13,22 +13,21 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from libcloud.py3 import httplib
-from libcloud.py3 import urllib
+from libcloud.utils.py3 import httplib
 
 try:
     import simplejson as json
 except ImportError:
     import json
 
-from libcloud.py3 import PY3
-from libcloud.py3 import urlquote
+from libcloud.utils.py3 import PY3
+from libcloud.utils.py3 import urlquote
 
 if PY3:
     from io import FileIO as file
 
 
-from libcloud.utils import read_in_chunks
+from libcloud.utils.files import read_in_chunks
 from libcloud.common.types import MalformedResponseError, LibcloudError
 from libcloud.common.base import Response, RawResponse
 

Modified: libcloud/trunk/libcloud/storage/drivers/dummy.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/storage/drivers/dummy.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/storage/drivers/dummy.py (original)
+++ libcloud/trunk/libcloud/storage/drivers/dummy.py Sun Dec  4 01:59:15 2011
@@ -17,8 +17,8 @@ import os.path
 import random
 import hashlib
 
-from libcloud.py3 import PY3
-from libcloud.py3 import b
+from libcloud.utils.py3 import PY3
+from libcloud.utils.py3 import b
 
 if PY3:
     from io import FileIO as file

Modified: libcloud/trunk/libcloud/storage/drivers/google_storage.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/storage/drivers/google_storage.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/storage/drivers/google_storage.py (original)
+++ libcloud/trunk/libcloud/storage/drivers/google_storage.py Sun Dec  4 01:59:15 2011
@@ -21,7 +21,7 @@ import hmac
 from hashlib import sha1
 from email.utils import formatdate
 
-from libcloud.py3 import b
+from libcloud.utils.py3 import b
 
 from libcloud.common.base import ConnectionUserAndKey
 

Modified: libcloud/trunk/libcloud/storage/drivers/s3.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/storage/drivers/s3.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/storage/drivers/s3.py (original)
+++ libcloud/trunk/libcloud/storage/drivers/s3.py Sun Dec  4 01:59:15 2011
@@ -21,14 +21,13 @@ import hmac
 from hashlib import sha1
 from xml.etree.ElementTree import Element, SubElement, tostring
 
-from libcloud.py3 import PY3
-from libcloud.py3 import httplib
-from libcloud.py3 import urllib
-from libcloud.py3 import urlquote
-from libcloud.py3 import b
+from libcloud.utils.py3 import PY3
+from libcloud.utils.py3 import httplib
+from libcloud.utils.py3 import urlquote
+from libcloud.utils.py3 import b
 
-from libcloud.utils import fixxpath, findtext, in_development_warning
-from libcloud.utils import read_in_chunks
+from libcloud.utils.xml import fixxpath, findtext
+from libcloud.utils.files import read_in_chunks
 from libcloud.common.types import InvalidCredsError, LibcloudError
 from libcloud.common.base import ConnectionUserAndKey, RawResponse
 from libcloud.common.aws import AWSBaseResponse

Modified: libcloud/trunk/libcloud/storage/providers.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/storage/providers.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/libcloud/storage/providers.py (original)
+++ libcloud/trunk/libcloud/storage/providers.py Sun Dec  4 01:59:15 2011
@@ -13,7 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from libcloud.utils import get_driver as get_provider_driver
+from libcloud.utils.misc import get_driver as get_provider_driver
 from libcloud.storage.types import Provider
 
 DRIVERS = {

Added: libcloud/trunk/libcloud/utils/__init__.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/utils/__init__.py?rev=1210045&view=auto
==============================================================================
--- libcloud/trunk/libcloud/utils/__init__.py (added)
+++ libcloud/trunk/libcloud/utils/__init__.py Sun Dec  4 01:59:15 2011
@@ -0,0 +1,47 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import warnings
+
+__all__ = [
+    'SHOW_DEPRECATION_WARNING',
+    'SHOW_IN_DEVELOPMENT_WARNING',
+    'OLD_API_REMOVE_VERSION',
+    'deprecated_warning',
+    'in_development_warning'
+]
+
+
+SHOW_DEPRECATION_WARNING = True
+SHOW_IN_DEVELOPMENT_WARNING = True
+OLD_API_REMOVE_VERSION = '0.7.0'
+
+def deprecated_warning(module):
+    if SHOW_DEPRECATION_WARNING:
+        warnings.warn('This path has been deprecated and the module'
+                      ' is now available at "libcloud.compute.%s".'
+                      ' This path will be fully removed in libcloud %s.' %
+                      (module, OLD_API_REMOVE_VERSION),
+                      category=DeprecationWarning)
+
+
+def in_development_warning(module):
+    if SHOW_IN_DEVELOPMENT_WARNING:
+        warnings.warn('The module %s is in development and your are advised '
+                      'against using it in production.' % (module),
+                      category=FutureWarning)
+
+
+

Added: libcloud/trunk/libcloud/utils/files.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/utils/files.py?rev=1210045&view=auto
==============================================================================
--- libcloud/trunk/libcloud/utils/files.py (added)
+++ libcloud/trunk/libcloud/utils/files.py Sun Dec  4 01:59:15 2011
@@ -0,0 +1,111 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import mimetypes
+
+from libcloud.utils.py3 import PY3
+from libcloud.utils.py3 import httplib
+from libcloud.utils.py3 import next
+
+CHUNK_SIZE = 8096
+
+if PY3:
+    from io import FileIO as file
+
+
+def read_in_chunks(iterator, chunk_size=None, fill_size=False):
+    """
+    Return a generator which yields data in chunks.
+
+    @type iterator: C{Iterator}
+    @param response: An object which implements an iterator interface
+                     or a File like object with read method.
+
+    @type chunk_size: C{int}
+    @param chunk_size: Optional chunk size (defaults to CHUNK_SIZE)
+
+    @type fill_size: C{bool}
+    @param fill_size: If True, make sure chunks are chunk_size in length
+                      (except for last chunk).
+    """
+    chunk_size = chunk_size or CHUNK_SIZE
+
+    if isinstance(iterator, (file, httplib.HTTPResponse)):
+        get_data = iterator.read
+        args = (chunk_size, )
+    else:
+        get_data = next
+        args = (iterator, )
+
+    data = ''
+    empty = False
+
+    while not empty or len(data) > 0:
+        if not empty:
+            try:
+                chunk = str(get_data(*args))
+                if len(chunk) > 0:
+                    data += chunk
+                else:
+                    empty = True
+            except StopIteration:
+                empty = True
+
+        if len(data) == 0:
+            raise StopIteration
+
+        if fill_size:
+            if empty or len(data) >= chunk_size:
+                yield data[:chunk_size]
+                data = data[chunk_size:]
+        else:
+            yield data
+            data = ''
+
+
+def exhaust_iterator(iterator):
+    """
+    Exhaust an iterator and return all data returned by it.
+
+    @type iterator: C{Iterator}
+    @param response: An object which implements an iterator interface
+                     or a File like object with read method.
+
+    @rtype C{str}
+    @return Data returned by the iterator.
+    """
+    data = ''
+
+    try:
+        chunk = str(next(iterator))
+    except StopIteration:
+        chunk = ''
+
+    while len(chunk) > 0:
+        data += chunk
+
+        try:
+            chunk = str(next(iterator))
+        except StopIteration:
+            chunk = ''
+
+    return data
+
+
+def guess_file_mime_type(file_path):
+    filename = os.path.basename(file_path)
+    (mimetype, encoding) = mimetypes.guess_type(filename)
+    return mimetype, encoding

Added: libcloud/trunk/libcloud/utils/misc.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/utils/misc.py?rev=1210045&view=auto
==============================================================================
--- libcloud/trunk/libcloud/utils/misc.py (added)
+++ libcloud/trunk/libcloud/utils/misc.py Sun Dec  4 01:59:15 2011
@@ -0,0 +1,186 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+def get_driver(drivers, provider):
+    """
+    Get a driver.
+
+    @param drivers: Dictionary containing valid providers.
+    @param provider: Id of provider to get driver
+    @type provider: L{libcloud.types.Provider}
+    """
+    if provider in drivers:
+        mod_name, driver_name = drivers[provider]
+        _mod = __import__(mod_name, globals(), locals(), [driver_name])
+        return getattr(_mod, driver_name)
+
+    raise AttributeError('Provider %s does not exist' % (provider))
+
+
+def merge_valid_keys(params, valid_keys, extra):
+    """
+    Merge valid keys from extra into params dictionary and return
+    dictionary with keys which have been merged.
+
+    Note: params is modified in place.
+    """
+    merged = {}
+    if not extra:
+        return merged
+
+    for key in valid_keys:
+        if key in extra:
+            params[key] = extra[key]
+            merged[key] = extra[key]
+
+    return merged
+
+
+def get_new_obj(obj, klass, attributes):
+    """
+    Pass attributes from the existing object 'obj' and attributes
+    dictionary to a 'klass' constructor.
+    Attributes from 'attributes' dictionary are only passed to the
+    constructor if they are not None.
+    """
+    kwargs = {}
+    for key, value in obj.__dict__.items():
+        if isinstance(value, dict):
+            kwargs[key] = value.copy()
+        elif isinstance(value, (tuple, list)):
+            kwargs[key] = value[:]
+        else:
+            kwargs[key] = value
+
+    for key, value in attributes.items():
+        if value is None:
+            continue
+
+        if isinstance(value, dict):
+            kwargs_value = kwargs.get(key, {})
+            for key1, value2 in value.items():
+                if value2 is None:
+                    continue
+
+                kwargs_value[key1] = value2
+            kwargs[key] = kwargs_value
+        else:
+            kwargs[key] = value
+
+    return klass(**kwargs)
+
+def str2dicts(data):
+    """
+    Create a list of dictionaries from a whitespace and newline delimited text.
+
+    For example, this:
+    cpu 1100
+    ram 640
+
+    cpu 2200
+    ram 1024
+
+    becomes:
+    [{'cpu': '1100', 'ram': '640'}, {'cpu': '2200', 'ram': '1024'}]
+    """
+    list_data = []
+    list_data.append({})
+    d = list_data[-1]
+
+    lines = data.split('\n')
+    for line in lines:
+        line = line.strip()
+
+        if not line:
+            d = {}
+            list_data.append(d)
+            d = list_data[-1]
+            continue
+
+        whitespace = line.find(' ')
+
+        if not whitespace:
+            continue
+
+        key = line[0:whitespace]
+        value = line[whitespace + 1:]
+        d.update({key: value})
+
+    list_data = [value for value in list_data if value != {}]
+    return list_data
+
+
+def str2list(data):
+    """
+    Create a list of values from a whitespace and newline delimited text
+    (keys are ignored).
+
+    For example, this:
+    ip 1.2.3.4
+    ip 1.2.3.5
+    ip 1.2.3.6
+
+    becomes:
+    ['1.2.3.4', '1.2.3.5', '1.2.3.6']
+    """
+    list_data = []
+
+    for line in data.split('\n'):
+        line = line.strip()
+
+        if not line:
+            continue
+
+        try:
+            splitted = line.split(' ')
+            # key = splitted[0]
+            value = splitted[1]
+        except Exception:
+            continue
+
+        list_data.append(value)
+
+    return list_data
+
+
+def dict2str(data):
+    """
+    Create a string with a whitespace and newline delimited text from a
+    dictionary.
+
+    For example, this:
+    {'cpu': '1100', 'ram': '640', 'smp': 'auto'}
+
+    becomes:
+    cpu 1100
+    ram 640
+    smp auto
+
+    cpu 2200
+    ram 1024
+    """
+    result = ''
+    for k in data:
+        if data[k] != None:
+            result += '%s %s\n' % (str(k), str(data[k]))
+        else:
+            result += '%s\n' % str(k)
+
+    return result
+
+
+def reverse_dict(dictionary):
+    return dict([(value, key) for key, value in dictionary.items()])

Added: libcloud/trunk/libcloud/utils/py3.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/utils/py3.py?rev=1210045&view=auto
==============================================================================
--- libcloud/trunk/libcloud/utils/py3.py (added)
+++ libcloud/trunk/libcloud/utils/py3.py Sun Dec  4 01:59:15 2011
@@ -0,0 +1,86 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Libcloud Python 2.x and 3.x compatibility layer
+# Some methods bellow are taken from Django PYK3 port which is licensed under 3
+# clause BSD license
+# https://bitbucket.org/loewis/django-3k
+
+from __future__ import absolute_import
+
+import sys
+import types
+
+PY3 = False
+PY2 = False
+PY25 = False
+
+if sys.version_info >= (3, 0):
+    PY3 = True
+    import http.client as httplib
+    from io import StringIO
+    import urllib
+    import urllib as urllib2
+    import urllib.parse as urlparse
+    import xmlrpc.client as xmlrpclib
+    from urllib.parse import quote as urlquote
+    from urllib.parse import urlencode as urlencode
+
+    basestring = str
+
+    def method_type(callable, instance, klass):
+        return types.MethodType(callable, instance or klass())
+
+    bytes = __builtins__['bytes']
+    def b(s):
+        if isinstance(s, str):
+            return s.encode("ascii")
+        elif isinstance(s, bytes):
+            return s
+        else:
+            raise TypeError("Invalid argument %r for b()" % (s,))
+    def byte(n):
+        # assume n is a Latin-1 string of length 1
+        return ord(n)
+    u = str
+    next = __builtins__['next']
+    def dictvalues(d):
+        return list(d.values())
+else:
+    PY2 = True
+    import httplib
+    from StringIO import StringIO
+    import urllib
+    import urllib2
+    import urlparse
+    import xmlrpclib
+    from urllib import quote as urlquote
+    from urllib import urlencode as urlencode
+
+    basestring = unicode = str
+
+    method_type = types.MethodType
+
+    b = bytes = str
+    def byte(n):
+        return n
+    u = unicode
+    def next(i):
+        return i.next()
+    def dictvalues(d):
+        return d.values()
+
+if sys.version_info >= (2, 5) and sys.version_info <= (2, 6):
+    PY25 = True

Added: libcloud/trunk/libcloud/utils/xml.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/utils/xml.py?rev=1210045&view=auto
==============================================================================
--- libcloud/trunk/libcloud/utils/xml.py (added)
+++ libcloud/trunk/libcloud/utils/xml.py Sun Dec  4 01:59:15 2011
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+def fixxpath(xpath, namespace=None):
+    # ElementTree wants namespaces in its xpaths, so here we add them.
+    if not namespace:
+        return xpath
+
+    return '/'.join(['{%s}%s' % (namespace, e) for e in xpath.split('/')])
+
+
+def findtext(element, xpath, namespace=None):
+    return element.findtext(fixxpath(xpath=xpath, namespace=namespace))
+
+
+def findattr(element, xpath, namespace=None):
+    return element.findtext(fixxpath(xpath=xpath, namespace=namespace))
+
+
+def findall(element, xpath, namespace=None):
+    return element.findall(fixxpath(xpath=xpath, namespace=namespace))

Modified: libcloud/trunk/setup.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/setup.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/setup.py (original)
+++ libcloud/trunk/setup.py Sun Dec  4 01:59:15 2011
@@ -23,8 +23,8 @@ from glob import glob
 from subprocess import call
 from os.path import splitext, basename, join as pjoin
 
-import libcloud.utils
-libcloud.utils.SHOW_DEPRECATION_WARNING = False
+import libcloud.utils.misc
+libcloud.utils.misc.SHOW_DEPRECATION_WARNING = False
 
 
 HTML_VIEWSOURCE_BASE = 'https://svn.apache.org/viewvc/libcloud/trunk'
@@ -207,6 +207,7 @@ setup(
     requires=([], ['ssl', 'simplejson'],)[pre_python26],
     packages=[
         'libcloud',
+        'libcloud.utils',
         'libcloud.common',
         'libcloud.compute',
         'libcloud.compute.drivers',

Modified: libcloud/trunk/test/compute/test_cloudsigma.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/test_cloudsigma.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/test/compute/test_cloudsigma.py (original)
+++ libcloud/trunk/test/compute/test_cloudsigma.py Sun Dec  4 01:59:15 2011
@@ -19,7 +19,7 @@ from libcloud.py3 import httplib
 
 from libcloud.compute.base import Node
 from libcloud.compute.drivers.cloudsigma import CloudSigmaZrhNodeDriver
-from libcloud.utils import str2dicts, str2list, dict2str
+from libcloud.utils.misc import str2dicts, str2list, dict2str
 
 from test import MockHttp               # pylint: disable-msg=E0611
 from test.compute import TestCaseMixin  # pylint: disable-msg=E0611

Modified: libcloud/trunk/test/storage/test_atmos.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/storage/test_atmos.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/test/storage/test_atmos.py (original)
+++ libcloud/trunk/test/storage/test_atmos.py Sun Dec  4 01:59:15 2011
@@ -22,7 +22,7 @@ from libcloud.py3 import httplib
 from libcloud.py3 import urlparse
 from libcloud.py3 import b
 
-import libcloud.utils
+import libcloud.utils.files
 
 from libcloud.common.types import LibcloudError
 from libcloud.storage.base import Container, Object
@@ -256,8 +256,8 @@ class AtmosTests(unittest.TestCase):
         def no_content_type(name):
             return None, None
 
-        old_func = libcloud.utils.guess_file_mime_type
-        libcloud.utils.guess_file_mime_type = no_content_type
+        old_func = libcloud.utils.files.guess_file_mime_type
+        libcloud.utils.files.guess_file_mime_type = no_content_type
         file_path = os.path.abspath(__file__)
         container = Container(name='fbc', extra={}, driver=self)
         object_name = 'ftu'
@@ -271,7 +271,7 @@ class AtmosTests(unittest.TestCase):
                 'File content type not provided'
                 ' but an exception was not thrown')
         finally:
-            libcloud.utils.guess_file_mime_type = old_func
+            libcloud.utils.files.guess_file_mime_type = old_func
 
     def test_upload_object_error(self):
         def dummy_content_type(name):
@@ -280,8 +280,8 @@ class AtmosTests(unittest.TestCase):
         def send(instance):
             raise Exception('')
 
-        old_func1 = libcloud.utils.guess_file_mime_type
-        libcloud.utils.guess_file_mime_type = dummy_content_type
+        old_func1 = libcloud.utils.files.guess_file_mime_type
+        libcloud.utils.files.guess_file_mime_type = dummy_content_type
         old_func2 = AtmosMockHttp.send
         AtmosMockHttp.send = send
 
@@ -298,15 +298,15 @@ class AtmosTests(unittest.TestCase):
         else:
             self.fail('Timeout while uploading but an exception was not thrown')
         finally:
-            libcloud.utils.guess_file_mime_type = old_func1
+            libcloud.utils.files.guess_file_mime_type = old_func1
             AtmosMockHttp.send = old_func2
 
     def test_upload_object_nonexistent_file(self):
         def dummy_content_type(name):
             return 'application/zip', None
 
-        old_func = libcloud.utils.guess_file_mime_type
-        libcloud.utils.guess_file_mime_type = dummy_content_type
+        old_func = libcloud.utils.files.guess_file_mime_type
+        libcloud.utils.files.guess_file_mime_type = dummy_content_type
 
         file_path = os.path.abspath(__file__ + '.inexistent')
         container = Container(name='fbc', extra={}, driver=self)
@@ -321,14 +321,14 @@ class AtmosTests(unittest.TestCase):
         else:
             self.fail('Inesitent but an exception was not thrown')
         finally:
-            libcloud.utils.guess_file_mime_type = old_func
+            libcloud.utils.files.guess_file_mime_type = old_func
 
     def test_upload_object_via_stream(self):
         def dummy_content_type(name):
             return 'application/zip', None
 
-        old_func = libcloud.utils.guess_file_mime_type
-        libcloud.utils.guess_file_mime_type = dummy_content_type
+        old_func = libcloud.utils.files.guess_file_mime_type
+        libcloud.utils.files.guess_file_mime_type = dummy_content_type
 
         container = Container(name='fbc', extra={}, driver=self)
         object_name = 'ftsd'
@@ -338,7 +338,7 @@ class AtmosTests(unittest.TestCase):
                                                  object_name=object_name,
                                                  iterator=iterator)
         finally:
-            libcloud.utils.guess_file_mime_type = old_func
+            libcloud.utils.files.guess_file_mime_type = old_func
 
     def test_signature_algorithm(self):
         test_uid = 'fredsmagicuid'

Modified: libcloud/trunk/test/storage/test_cloudfiles.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/storage/test_cloudfiles.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/test/storage/test_cloudfiles.py (original)
+++ libcloud/trunk/test/storage/test_cloudfiles.py Sun Dec  4 01:59:15 2011
@@ -18,7 +18,7 @@ import sys
 import copy
 import unittest
 
-import libcloud.utils
+import libcloud.utils.files
 
 from libcloud.py3 import PY3
 from libcloud.py3 import httplib
@@ -308,8 +308,8 @@ class CloudFilesTests(unittest.TestCase)
         def no_content_type(name):
             return None, None
 
-        old_func = libcloud.utils.guess_file_mime_type
-        libcloud.utils.guess_file_mime_type = no_content_type
+        old_func = libcloud.utils.files.guess_file_mime_type
+        libcloud.utils.files.guess_file_mime_type = no_content_type
         file_path = os.path.abspath(__file__)
         container = Container(name='foo_bar_container', extra={}, driver=self)
         object_name = 'foo_test_upload'
@@ -323,7 +323,7 @@ class CloudFilesTests(unittest.TestCase)
                 'File content type not provided'
                 ' but an exception was not thrown')
         finally:
-            libcloud.utils.guess_file_mime_type = old_func
+            libcloud.utils.files.guess_file_mime_type = old_func
 
     def test_upload_object_error(self):
         def dummy_content_type(name):
@@ -332,8 +332,8 @@ class CloudFilesTests(unittest.TestCase)
         def send(instance):
             raise Exception('')
 
-        old_func1 = libcloud.utils.guess_file_mime_type
-        libcloud.utils.guess_file_mime_type = dummy_content_type
+        old_func1 = libcloud.utils.files.guess_file_mime_type
+        libcloud.utils.files.guess_file_mime_type = dummy_content_type
         old_func2 = CloudFilesMockHttp.send
         CloudFilesMockHttp.send = send
 
@@ -350,15 +350,15 @@ class CloudFilesTests(unittest.TestCase)
         else:
             self.fail('Timeout while uploading but an exception was not thrown')
         finally:
-            libcloud.utils.guess_file_mime_type = old_func1
+            libcloud.utils.files.guess_file_mime_type = old_func1
             CloudFilesMockHttp.send = old_func2
 
     def test_upload_object_inexistent_file(self):
         def dummy_content_type(name):
             return 'application/zip', None
 
-        old_func = libcloud.utils.guess_file_mime_type
-        libcloud.utils.guess_file_mime_type = dummy_content_type
+        old_func = libcloud.utils.files.guess_file_mime_type
+        libcloud.utils.files.guess_file_mime_type = dummy_content_type
 
         file_path = os.path.abspath(__file__ + '.inexistent')
         container = Container(name='foo_bar_container', extra={}, driver=self)
@@ -373,14 +373,14 @@ class CloudFilesTests(unittest.TestCase)
         else:
             self.fail('Inesitent but an exception was not thrown')
         finally:
-            libcloud.utils.guess_file_mime_type = old_func
+            libcloud.utils.files.guess_file_mime_type = old_func
 
     def test_upload_object_via_stream(self):
         def dummy_content_type(name):
             return 'application/zip', None
 
-        old_func = libcloud.utils.guess_file_mime_type
-        libcloud.utils.guess_file_mime_type = dummy_content_type
+        old_func = libcloud.utils.files.guess_file_mime_type
+        libcloud.utils.files.guess_file_mime_type = dummy_content_type
 
         container = Container(name='foo_bar_container', extra={}, driver=self)
         object_name = 'foo_test_stream_data'
@@ -390,7 +390,7 @@ class CloudFilesTests(unittest.TestCase)
                                                  object_name=object_name,
                                                  iterator=iterator)
         finally:
-            libcloud.utils.guess_file_mime_type = old_func
+            libcloud.utils.files.guess_file_mime_type = old_func
 
     def test_delete_object_success(self):
         container = Container(name='foo_bar_container', extra={}, driver=self)

Modified: libcloud/trunk/test/test_utils.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/test_utils.py?rev=1210045&r1=1210044&r2=1210045&view=diff
==============================================================================
--- libcloud/trunk/test/test_utils.py (original)
+++ libcloud/trunk/test/test_utils.py Sun Dec  4 01:59:15 2011
@@ -22,7 +22,10 @@ import os.path
 # In Python > 2.7 DeprecationWarnings are disabled by default
 warnings.simplefilter('default')
 
-import libcloud.utils
+import libcloud.utils.files
+
+from libcloud.utils.misc import get_driver
+
 from libcloud.py3 import StringIO
 from libcloud.py3 import PY3
 from libcloud.compute.types import Provider
@@ -52,19 +55,17 @@ class TestUtils(unittest.TestCase):
 
     def test_guess_file_mime_type(self):
         file_path = os.path.abspath(__file__)
-        mimetype, encoding = libcloud.utils.guess_file_mime_type(
+        mimetype, encoding = libcloud.utils.files.guess_file_mime_type(
                 file_path=file_path)
 
         self.assertTrue(mimetype.find('python') != -1)
 
     def test_get_driver(self):
-        driver = libcloud.utils.get_driver(drivers=DRIVERS,
-                                           provider=Provider.DUMMY)
+        driver = get_driver(drivers=DRIVERS, provider=Provider.DUMMY)
         self.assertTrue(driver is not None)
 
         try:
-            driver = libcloud.utils.get_driver(drivers=DRIVERS,
-                                               provider='fooba')
+            driver = get_driver(drivers=DRIVERS, provider='fooba')
         except AttributeError:
             pass
         else:
@@ -101,12 +102,13 @@ class TestUtils(unittest.TestCase):
             for x in range(0, 1000):
                 yield 'aa'
 
-        for result in libcloud.utils.read_in_chunks(iterator(), chunk_size=10,
-                                                    fill_size=False):
+        for result in libcloud.utils.files.read_in_chunks(iterator(), 
+                                                          chunk_size=10,
+                                                          fill_size=False):
             self.assertEqual(result, 'aa')
 
-        for result in libcloud.utils.read_in_chunks(iterator(), chunk_size=10,
-                                                    fill_size=True):
+        for result in libcloud.utils.files.read_in_chunks(iterator(), chunk_size=10,
+                                                          fill_size=True):
             self.assertEqual(result, 'aaaaaaaaaa')
 
     def test_read_in_chunks_filelike(self):
@@ -120,14 +122,14 @@ class TestUtils(unittest.TestCase):
                         return ''
                     return 'b' * (size + 1)
 
-            for index, result in enumerate(libcloud.utils.read_in_chunks(
+            for index, result in enumerate(libcloud.utils.files.read_in_chunks(
                                            FakeFile(), chunk_size=10,
                                            fill_size=False)):
                 self.assertEqual(result, 'b' * 11)
 
             self.assertEqual(index, 498)
 
-            for index, result in enumerate(libcloud.utils.read_in_chunks(
+            for index, result in enumerate(libcloud.utils.files.read_in_chunks(
                                            FakeFile(), chunk_size=10,
                                            fill_size=True)):
                 if index != 548:
@@ -143,22 +145,22 @@ class TestUtils(unittest.TestCase):
                 yield 'aa'
 
         data = 'aa' * 1000
-        iterator = libcloud.utils.read_in_chunks(iterator=iterator_func())
-        result = libcloud.utils.exhaust_iterator(iterator=iterator)
+        iterator = libcloud.utils.files.read_in_chunks(iterator=iterator_func())
+        result = libcloud.utils.files.exhaust_iterator(iterator=iterator)
         self.assertEqual(result, data)
 
-        result = libcloud.utils.exhaust_iterator(iterator=iterator_func())
+        result = libcloud.utils.files.exhaust_iterator(iterator=iterator_func())
         self.assertEqual(result, data)
 
         data = '12345678990'
         iterator = StringIO(data)
-        result = libcloud.utils.exhaust_iterator(iterator=iterator)
+        result = libcloud.utils.files.exhaust_iterator(iterator=iterator)
         self.assertEqual(result, data)
 
     def test_exhaust_iterator_empty_iterator(self):
         data = ''
         iterator = StringIO(data)
-        result = libcloud.utils.exhaust_iterator(iterator=iterator)
+        result = libcloud.utils.files.exhaust_iterator(iterator=iterator)
         self.assertEqual(result, data)
 
 



Mime
View raw message