Skip to content

Commit

Permalink
Merge pull request #89 from vmware/python3
Browse files Browse the repository at this point in the history
Support for Python 3
  • Loading branch information
Shawn Hartsock committed Jul 28, 2014
2 parents 9dabaa0 + d3f819e commit 9cb5349
Show file tree
Hide file tree
Showing 17 changed files with 605 additions and 300 deletions.
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ python:
- "2.6"
- "2.7"
- "pypy"
- "3.3"
- "3.4"

before_install:
- if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install unittest2; fi
- pip install -r requirements.txt
- pip install -r test-requirements.txt

install:
- python setup.py -q install
- python setup.py install

script: python setup.py test
79 changes: 35 additions & 44 deletions pyVim/connect.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,19 @@
"""
from six import reraise
import sys
import threading
import thread
import types
import httplib
import socket
import time
import itertools
import re
from pyVmomi import vim, vmodl, SoapStubAdapter, SessionOrientedStub
from pyVmomi.VmomiSupport import nsMap, versionIdMap, versionMap, IsChildVersion
from pyVmomi.VmomiSupport import GetServiceVersions
try:
from xml.etree.ElementTree import ElementTree
from xml.etree import ElementTree
except ImportError:
from elementtree.ElementTree import ElementTree
from elementtree import ElementTree
from xml.parsers.expat import ExpatError
import urllib2

import requests
from requests.auth import HTTPBasicAuth

from pyVmomi import vim, vmodl, SoapStubAdapter, SessionOrientedStub
from pyVmomi.VmomiSupport import nsMap, versionIdMap, versionMap, IsChildVersion
from pyVmomi.VmomiSupport import GetServiceVersions


"""
Expand All @@ -57,7 +53,6 @@
@todo: Get rid of me?
"""


class closing(object):
"""
Helper class for using closable objects in a 'with' statement,
Expand Down Expand Up @@ -227,7 +222,7 @@ def Connect(host='localhost', port=443, user='root', pwd='',
host = info.group(1)[1:-1]
if info.group(2) is not None:
port = int(info.group(2)[1:])
except ValueError, ve:
except ValueError as ve:
pass

if namespace:
Expand Down Expand Up @@ -256,7 +251,7 @@ def Disconnect(si):
def GetLocalTicket(si, user):
try:
sessionManager = si.content.sessionManager
except Exception, e:
except Exception as e:
if type(e).__name__ == 'ExpatError':
msg = 'Malformed response while querying for local ticket: "%s"' % e
raise vim.fault.HostConnectFault(msg=msg)
Expand Down Expand Up @@ -312,14 +307,17 @@ def __Login(host, port, user, pwd, service, adapter, version, path,
content = si.RetrieveContent()
except vmodl.MethodFault:
raise
except Exception, e:
except Exception as e:
# NOTE (hartsock): preserve the traceback for diagnostics
# pulling and preserving the traceback makes diagnosing connection
# failures easier since the fault will also include where inside the
# library the fault occurred. Without the traceback we have no idea
# why the connection failed beyond the message string.
(type, value, traceback) = sys.exc_info()
reraise(vim.fault.HostConnectFault(msg=str(e)), None, traceback)
if traceback:
reraise(vim.fault.HostConnectFault(msg=str(e)), None, traceback)
else:
raise vim.fault.HostConnectFault(msg=str(e))

# Get a ticket if we're connecting to localhost and password is not specified
if host == 'localhost' and not pwd:
Expand All @@ -334,7 +332,7 @@ def __Login(host, port, user, pwd, service, adapter, version, path,
x = content.sessionManager.Login(user, pwd, None)
except vim.fault.InvalidLogin:
raise
except Exception, e:
except Exception as e:
raise
return si, stub

Expand All @@ -350,7 +348,7 @@ def __Logout(si):
if si:
content = si.RetrieveContent()
content.sessionManager.Logout()
except Exception, e:
except Exception as e:
pass


Expand Down Expand Up @@ -417,7 +415,7 @@ def __exit__(self, *exc_info):

def __GetServiceVersionDescription(protocol, server, port, path):
"""
Private method that returns an ElementTree describing the API versions
Private method that returns a root from an ElementTree describing the API versions
supported by the specified server. The result will be vimServiceVersions.xml
if it exists, otherwise vimService.wsdl if it exists, otherwise None.
Expand All @@ -431,26 +429,23 @@ def __GetServiceVersionDescription(protocol, server, port, path):
@type path: string
"""

tree = ElementTree()

url = "%s://%s:%s/%s/vimServiceVersions.xml" % (protocol, server, port, path)
try:
with closing(urllib2.urlopen(url)) as sock:
if sock.getcode() == 200:
tree.parse(sock)
return tree
sock = requests.get(url, verify=False)
if sock.status_code == 200:
tree = ElementTree.fromstring(sock.content)
return tree
except ExpatError:
pass

url = "%s://%s:%s/%s/vimService.wsdl" % (protocol, server, port, path)
try:
with closing(urllib2.urlopen(url)) as sock:
if sock.getcode() == 200:
tree.parse(sock)
return tree
sock = requests.get(url, verify=False)
if sock.status_code == 200:
tree = ElementTree.fromstring(sock.content)
return tree
except ExpatError:
pass

return None


Expand All @@ -465,15 +460,15 @@ def __VersionIsSupported(desiredVersion, serviceVersionDescription):
@param desiredVersion: The version we want to see if the server supports
(eg. vim.version.version2.
@type desiredVersion: string
@param serviceVersionDescription: An ElementTree for vimServiceVersions.xml
@param serviceVersionDescription: A root ElementTree for vimServiceVersions.xml
or vimService.wsdl.
@type serviceVersionDescription: ElementTree
@type serviceVersionDescription: root ElementTree
"""

root = serviceVersionDescription.getroot()
root = serviceVersionDescription
if root.tag == 'namespaces':
# serviceVersionDescription appears to be a vimServiceVersions.xml document
if root.get('version') <> '1.0':
if root.get('version') != '1.0':
raise RuntimeError('vimServiceVersions.xml has version %s,' \
' which is not understood' % (root.get('version')))
desiredVersionId = versionIdMap[desiredVersion]
Expand Down Expand Up @@ -599,11 +594,7 @@ def OpenUrlWithBasicAuth(url, user='root', pwd=''):
the specified credentials to the server as part of the request.
Returns the response as a file-like object.
"""
pwMgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
pwMgr.add_password(None, url, user, pwd)
handler = urllib2.HTTPBasicAuthHandler(pwMgr)
opener = urllib2.build_opener(handler)
return opener.open(url)
return requests.get(url, auth=HTTPBasicAuth(user, pwd), verify=False)

def OpenPathWithStub(path, stub):
"""
Expand All @@ -623,8 +614,8 @@ def OpenPathWithStub(path, stub):
raise vmodl.fault.NotSupported()
hostPort = stub.host
url = '%s://%s%s' % (protocol, hostPort, path)
request = urllib2.Request(url)
headers = {}
if stub.cookie:
request.add_header('Cookie', stub.cookie)
return urllib2.urlopen(request)
headers["Cookie"] = stub.cookie
return requests.get(url, headers=headers, verify=False)

3 changes: 2 additions & 1 deletion pyVmomi/CoreTypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
# 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.
from __future__ import absolute_import

# ******* WARNING - AUTO GENERATED CODE - DO NOT EDIT *******
from VmomiSupport import CreateDataType, CreateManagedType, CreateEnumType, AddVersion, AddVersionParent, F_LINK, F_LINKABLE, F_OPTIONAL
from pyVmomi.VmomiSupport import CreateDataType, CreateManagedType, CreateEnumType, AddVersion, AddVersionParent, F_LINK, F_LINKABLE, F_OPTIONAL

AddVersion("vmodl.query.version.version1", "", "", 0, "vim25")
AddVersion("vmodl.query.version.version2", "", "", 0, "vim25")
Expand Down
4 changes: 3 additions & 1 deletion pyVmomi/Differ.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
# limitations under the License.

## Diff any two objects
from six import text_type
from six import u

from pyVmomi import VmomiSupport, types
import itertools
Expand All @@ -33,7 +35,7 @@ def IsPrimitiveType(obj):
isinstance(obj, types.short) or isinstance(obj, types.int) or
isinstance(obj, types.double) or isinstance(obj, types.float) or
isinstance(obj, types.long) or isinstance(obj, types.str) or
isinstance(obj, unicode) or
isinstance(obj, text_type) or
isinstance(obj, types.PropertyPath) or
isinstance(obj, types.ManagedMethod) or
isinstance(obj, types.datetime) or
Expand Down
4 changes: 2 additions & 2 deletions pyVmomi/DynamicTypeManagerHelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def GetTypeManager(self):
if self.hostSystem:
try:
dynTypeMgr = self.hostSystem.RetrieveDynamicTypeManager()
except vmodl.fault.MethodNotFound, err:
except vmodl.fault.MethodNotFound as err:
pass

if not dynTypeMgr:
Expand Down Expand Up @@ -139,7 +139,7 @@ def _CreateAllTypes(self, enumTypes, dataTypes, managedTypes):
for typeInfo in infos:
try:
fn(*typeInfo)
except Exception, err:
except Exception as err:
#Ignore errors due to duplicate importing
pass

Expand Down
20 changes: 11 additions & 9 deletions pyVmomi/Iso8601.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
# 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.

from __future__ import print_function
# TODO (hartsocks): Introduce logging to remove the need for print function.
"""
This module is for ISO 8601 parsing
"""
__author__ = 'VMware, Inc.'

from six import iteritems
import time
from datetime import datetime, timedelta, tzinfo
import re
Expand Down Expand Up @@ -118,7 +120,7 @@ def ParseISO8601(datetimeStr):
if match:
try:
dt = {}
for key, defaultVal in _dtExprKeyDefValMap.iteritems():
for key, defaultVal in iteritems(_dtExprKeyDefValMap):
val = match.group(key)
if val:
if key == 'microsecond':
Expand Down Expand Up @@ -176,7 +178,7 @@ def ParseISO8601(datetimeStr):
datetimeVal = datetime(**dt)
if delta:
datetimeVal += delta
except Exception, e:
except Exception as e:
pass
return datetimeVal

Expand Down Expand Up @@ -253,7 +255,7 @@ def ISO8601Format(dt):
]:
dt = ParseISO8601(testStr)
if dt == None:
print 'Failed to parse (%s)' % testStr
print('Failed to parse ({0})'.format(testStr))
assert(False)

# Make sure we can translate back
Expand All @@ -262,16 +264,16 @@ def ISO8601Format(dt):
if dt.tzinfo is None:
dt = dt.replace(tzinfo=dt1.tzinfo)
if dt1 != dt:
print 'ParseISO8601 -> ISO8601Format -> ParseISO8601 failed (%s)' % testStr
print('ParseISO8601 -> ISO8601Format -> ParseISO8601 failed ({0})'.format(testStr))
assert(False)

# Make sure we can parse python isoformat()
dt2 = ParseISO8601(dt.isoformat())
if dt2 == None:
print 'ParseISO8601("%s".isoformat()) failed' % testStr
print('ParseISO8601("{0}".isoformat()) failed'.format(testStr))
assert(False)

print testStr, '->', dt, isoformat
print(testStr, '->', dt, isoformat)

# Basic form
for testStr in [
Expand All @@ -293,7 +295,7 @@ def ISO8601Format(dt):
# Reject for now
dt = ParseISO8601(testStr)
if dt != None:
print 'ParseISO8601 (%s) should fail, but it did not' % testStr
print('ParseISO8601 ({0}) should fail, but it did not'.format(testStr))
assert(False)
#print testStr, '->', dt
#assert(dt != None)
Expand Down Expand Up @@ -352,5 +354,5 @@ def ISO8601Format(dt):
]:
dt = ParseISO8601(testStr)
if dt != None:
print 'ParseISO8601 (%s) should fail, but it did not' % testStr
print('ParseISO8601 ({0}) should fail, but it did not'.format(testStr))
assert(False)
3 changes: 2 additions & 1 deletion pyVmomi/ServerObjects.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
# 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.
from __future__ import absolute_import

# ******* WARNING - AUTO GENERATED CODE - DO NOT EDIT *******
from VmomiSupport import CreateDataType, CreateManagedType, CreateEnumType, AddVersion, AddVersionParent, F_LINK, F_LINKABLE, F_OPTIONAL
from pyVmomi.VmomiSupport import CreateDataType, CreateManagedType, CreateEnumType, AddVersion, AddVersionParent, F_LINK, F_LINKABLE, F_OPTIONAL

AddVersion("vim.version.version1", "vim2", "2.0", 1, "vim25")
AddVersion("vim.version.version2", "vim25", "2.5", 0, "vim25")
Expand Down
Loading

0 comments on commit 9cb5349

Please sign in to comment.