Make it work on Python 3
Change-Id: Ia8eedf699e988a199520c48e21c9731af912003c
This commit is contained in:
parent
9424023180
commit
5d7ecd43e0
@ -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'])
|
||||
|
||||
|
6
tox.ini
6
tox.ini
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user