Make it work on Python 3

Change-Id: Ia8eedf699e988a199520c48e21c9731af912003c
This commit is contained in:
Marc Abramowitz 2014-04-06 08:34:22 -07:00 committed by Marc Abramowitz
parent 9424023180
commit 5d7ecd43e0
5 changed files with 52 additions and 24 deletions

@ -46,10 +46,13 @@ See examples at :doc:`example`
'''
import base64
from httplib import BadStatusLine
import json
import urllib
from urllib2 import Request, HTTPError, urlopen
import six
from six.moves.http_client import BadStatusLine
from six.moves.urllib.error import HTTPError
from six.moves.urllib.parse import quote, urlencode
from six.moves.urllib.request import Request, urlopen
LAUNCHER_SSH = 'hudson.plugins.sshslaves.SSHLauncher'
LAUNCHER_COMMAND = 'hudson.slaves.CommandLauncher'
@ -129,7 +132,10 @@ def auth_headers(username, password):
Simple implementation of HTTP Basic Authentication. Returns the
'Authentication' header value.
'''
return 'Basic ' + base64.encodestring('%s:%s' % (username, password))[:-1]
auth = '%s:%s' % (username, password)
if isinstance(auth, six.text_type):
auth = auth.encode('utf-8')
return b'Basic ' + base64.encodestring(auth)[:-1]
class Jenkins(object):
@ -160,7 +166,7 @@ class Jenkins(object):
response = self.jenkins_open(Request(
self.server + CRUMB_URL), add_crumb=False)
if response:
self.crumb = json.loads(response)
self.crumb = json.loads(response.decode('utf-8'))
else:
# Don't need crumbs
self.crumb = False
@ -212,8 +218,8 @@ class Jenkins(object):
'''
Print out job info in more readable format
'''
for k, v in self.get_job_info(job_name).iteritems():
print k, v
for k, v in self.get_job_info(job_name).items():
print(k, v)
def jenkins_open(self, req, add_crumb=True):
'''
@ -227,7 +233,7 @@ class Jenkins(object):
if add_crumb:
self.maybe_add_crumb(req)
return urlopen(req).read()
except HTTPError, e:
except HTTPError as e:
# Jenkins's funky authentication means its nigh impossible to
# distinguish errors.
if e.code in [401, 403, 500]:
@ -425,7 +431,7 @@ class Jenkins(object):
:returns: job configuration (XML format)
'''
request = Request(self.server + CONFIG_JOB %
{"name": urllib.quote(name)})
{"name": quote(name)})
return self.jenkins_open(request)
def reconfig_job(self, name, config_xml):
@ -454,10 +460,10 @@ class Jenkins(object):
if token:
parameters['token'] = token
return (self.server + BUILD_WITH_PARAMS_JOB % locals() +
'?' + urllib.urlencode(parameters))
'?' + urlencode(parameters))
elif token:
return (self.server + BUILD_JOB % locals() +
'?' + urllib.urlencode({'token': token}))
'?' + urlencode({'token': token}))
else:
return self.server + BUILD_JOB % locals()
@ -597,7 +603,7 @@ class Jenkins(object):
}
self.jenkins_open(Request(
self.server + CREATE_NODE % urllib.urlencode(params)))
self.server + CREATE_NODE % urlencode(params)))
if not self.node_exists(name):
raise JenkinsException('create[%s] failed' % (name))

@ -2,4 +2,4 @@ coverage>=3.6
discover
flake8
mock
unittest2
six

@ -3,4 +3,3 @@ import sys
sys.path.insert(0, os.path.abspath('..'))
import jenkins # noqa
from StringIO import StringIO # noqa

@ -1,9 +1,20 @@
import json
import unittest2 as unittest
import sys
if sys.version_info < (2, 7):
import unittest2 as unittest
else:
import unittest
from mock import patch
import six
from tests.helper import jenkins, StringIO
from tests.helper import jenkins
def get_mock_urlopen_return_value(a_dict=None):
if a_dict is None:
a_dict = {}
return six.BytesIO(json.dumps(a_dict).encode('utf-8'))
class JenkinsTest(unittest.TestCase):
@ -11,13 +22,13 @@ class JenkinsTest(unittest.TestCase):
def test_constructor_url_with_trailing_slash(self):
j = jenkins.Jenkins('http://example.com/', 'test', 'test')
self.assertEqual(j.server, 'http://example.com/')
self.assertEqual(j.auth, 'Basic dGVzdDp0ZXN0')
self.assertEqual(j.auth, b'Basic dGVzdDp0ZXN0')
self.assertEqual(j.crumb, None)
def test_constructor_url_without_trailing_slash(self):
j = jenkins.Jenkins('http://example.com', 'test', 'test')
self.assertEqual(j.server, 'http://example.com/')
self.assertEqual(j.auth, 'Basic dGVzdDp0ZXN0')
self.assertEqual(j.auth, b'Basic dGVzdDp0ZXN0')
self.assertEqual(j.crumb, None)
def test_constructor_without_user_or_password(self):
@ -26,6 +37,14 @@ class JenkinsTest(unittest.TestCase):
self.assertEqual(j.auth, None)
self.assertEqual(j.crumb, None)
def test_constructor_unicode_password(self):
j = jenkins.Jenkins('http://example.com',
six.u('nonascii'),
six.u('\xe9\u20ac'))
self.assertEqual(j.server, 'http://example.com/')
self.assertEqual(j.auth, b'Basic bm9uYXNjaWk6w6nigqw=')
self.assertEqual(j.crumb, None)
@patch.object(jenkins.Jenkins, 'jenkins_open')
def test_get_job_config_encodes_job_name(self, jenkins_mock):
"""
@ -40,7 +59,7 @@ class JenkinsTest(unittest.TestCase):
@patch('jenkins.urlopen')
def test_maybe_add_crumb(self, jenkins_mock):
jenkins_mock.return_value = StringIO()
jenkins_mock.return_value = get_mock_urlopen_return_value()
j = jenkins.Jenkins('http://example.com/', 'test', 'test')
request = jenkins.Request('http://example.com/job/TestJob')
@ -58,7 +77,7 @@ class JenkinsTest(unittest.TestCase):
"crumb": "dab177f483b3dd93483ef6716d8e792d",
"crumbRequestField": ".crumb",
}
jenkins_mock.return_value = StringIO(json.dumps(crumb_data))
jenkins_mock.return_value = get_mock_urlopen_return_value(crumb_data)
j = jenkins.Jenkins('http://example.com/', 'test', 'test')
request = jenkins.Request('http://example.com/job/TestJob')
@ -78,8 +97,8 @@ class JenkinsTest(unittest.TestCase):
}
data = {'foo': 'bar'}
jenkins_mock.side_effect = [
StringIO(json.dumps(crumb_data)),
StringIO(json.dumps(data)),
get_mock_urlopen_return_value(crumb_data),
get_mock_urlopen_return_value(data),
]
j = jenkins.Jenkins('http://example.com/', 'test', 'test')
request = jenkins.Request('http://example.com/job/TestJob')
@ -89,7 +108,7 @@ class JenkinsTest(unittest.TestCase):
self.assertEqual(
jenkins_mock.call_args[0][0].get_full_url(),
'http://example.com/job/TestJob')
self.assertEqual(response, json.dumps(data))
self.assertEqual(response, json.dumps(data).encode('utf-8'))
self.assertEqual(j.crumb, crumb_data)
self.assertEqual(request.headers['.crumb'], crumb_data['crumb'])

@ -1,7 +1,7 @@
[tox]
minversion = 1.6
skipsdist = True
envlist = pep8, py26, py27
envlist = pep8, py26, py27, pypy, py33, py34
[testenv]
setenv VIRTUAL_ENV={envdir}
@ -15,6 +15,10 @@ commands =
coverage run -m discover
coverage report --show-missing
[testenv:py26]
deps = -r{toxinidir}/test-requirements.txt
unittest2
[tox:jenkins]
downloadcache = ~/cache/pip