python-jenkins-developers team mailing list archive
-
python-jenkins-developers team
-
Mailing list archive
-
Message #00105
[Merge] lp:~msabramo/python-jenkins/python3 into lp:python-jenkins
Marc Abramowitz has proposed merging lp:~msabramo/python-jenkins/python3 into lp:python-jenkins.
Requested reviews:
Python Jenkins Developers (python-jenkins-developers)
For more details, see:
https://code.launchpad.net/~msabramo/python-jenkins/python3/+merge/214664
This builds on https://code.launchpad.net/~msabramo/python-jenkins/python3_small_tweaks/+merge/214584 and adds some more aggressive changes to make the tests pass in Python 3.
Of course, there is only 1 test and the coverage is only 35% so we should temper our enthusiasm and work on adding more tests before merging.
```
$ tox
...
py26: commands succeeded
py27: commands succeeded
pypy: commands succeeded
py33: commands succeeded
congratulations :)
```
--
https://code.launchpad.net/~msabramo/python-jenkins/python3/+merge/214664
Your team Python Jenkins Developers is requested to review the proposed merge of lp:~msabramo/python-jenkins/python3 into lp:python-jenkins.
=== added file '.bzrignore'
--- .bzrignore 1970-01-01 00:00:00 +0000
+++ .bzrignore 2014-04-08 06:02:58 +0000
@@ -0,0 +1,10 @@
+.tox
+MANIFEST
+*.egg-info
+*.egg
+*.pyc
+__pycache__
+build
+dist
+.coverage
+coverage.xml
=== modified file 'jenkins/__init__.py'
--- jenkins/__init__.py 2013-09-28 20:00:43 +0000
+++ jenkins/__init__.py 2014-04-08 06:02:58 +0000
@@ -46,12 +46,27 @@
'''
#import sys
-import urllib2
-import urllib
+try:
+ # Python 2
+ from urllib2 import Request
+except ImportError:
+ # Python 3
+ from urllib.request import Request
+try:
+ # Python 2
+ from urllib import quote
+except ImportError:
+ # Python 3
+ from urllib.parse import quote
import base64
#import traceback
import json
-import httplib
+try:
+ # Python 2
+ from httplib import BadStatusLine
+except ImportError:
+ # Python 3
+ from http.client import BadStatusLine
LAUNCHER_SSH = 'hudson.plugins.sshslaves.SSHLauncher'
LAUNCHER_COMMAND = 'hudson.slaves.CommandLauncher'
@@ -131,7 +146,10 @@
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)
+ auth = auth[:-1]
+ auth = auth.encode('ascii')
+ return b'Basic ' + base64.encodestring(auth)
class Jenkins(object):
@@ -159,7 +177,7 @@
def maybe_add_crumb(self, req):
# We don't know yet whether we need a crumb
if self.crumb is None:
- response = self.jenkins_open(urllib2.Request(
+ response = self.jenkins_open(Request(
self.server + CRUMB_URL), add_crumb=False)
if response:
self.crumb = json.loads(response)
@@ -177,7 +195,7 @@
:returns: dictionary of job information
'''
try:
- response = self.jenkins_open(urllib2.Request(
+ response = self.jenkins_open(Request(
self.server + JOB_INFO % locals()))
if response:
return json.loads(response)
@@ -199,7 +217,7 @@
:returns: Name of job or None
'''
response = self.jenkins_open(
- urllib2.Request(self.server + JOB_NAME % locals()))
+ Request(self.server + JOB_NAME % locals()))
if response:
if json.loads(response)['name'] != name:
raise JenkinsException(
@@ -213,7 +231,7 @@
Print out job info in more readable format
'''
for k, v in self.get_job_info(job_name).iteritems():
- print k, v
+ print(k, v)
def jenkins_open(self, req, add_crumb=True):
'''
@@ -227,7 +245,7 @@
if add_crumb:
self.maybe_add_crumb(req)
return urllib2.urlopen(req).read()
- except urllib2.HTTPError, e:
+ except urllib2.HTTPError as e:
# Jenkins's funky authentication means its nigh impossible to
# distinguish errors.
if e.code in [401, 403, 500]:
@@ -255,7 +273,7 @@
{u'building': False, u'changeSet': {u'items': [{u'date': u'2011-12-19T18:01:52.540557Z', u'msg': u'test', u'revision': 66, u'user': u'unknown', u'paths': [{u'editType': u'edit', u'file': u'/branches/demo/index.html'}]}], u'kind': u'svn', u'revisions': [{u'module': u'http://eaas-svn01.i3.level3.com/eaas', u'revision': 66}]}, u'builtOn': u'', u'description': None, u'artifacts': [{u'relativePath': u'dist/eaas-87-2011-12-19_18-01-57.war', u'displayPath': u'eaas-87-2011-12-19_18-01-57.war', u'fileName': u'eaas-87-2011-12-19_18-01-57.war'}, {u'relativePath': u'dist/eaas-87-2011-12-19_18-01-57.war.zip', u'displayPath': u'eaas-87-2011-12-19_18-01-57.war.zip', u'fileName': u'eaas-87-2011-12-19_18-01-57.war.zip'}], u'timestamp': 1324317717000, u'number': 87, u'actions': [{u'parameters': [{u'name': u'SERVICE_NAME', u'value': u'eaas'}, {u'name': u'PROJECT_NAME', u'value': u'demo'}]}, {u'causes': [{u'userName': u'anonymous', u'shortDescription': u'Started by user anonymous'}]}, {}, {}, {}], u'id': u'2011-12-19_18-01-57', u'keepLog': False, u'url': u'http://eaas-jenkins01.i3.level3.com:9080/job/build_war/87/', u'culprits': [{u'absoluteUrl': u'http://eaas-jenkins01.i3.level3.com:9080/user/unknown', u'fullName': u'unknown'}], u'result': u'SUCCESS', u'duration': 8826, u'fullDisplayName': u'build_war #87'}
'''
try:
- response = self.jenkins_open(urllib2.Request(
+ response = self.jenkins_open(Request(
self.server + BUILD_INFO % locals()))
if response:
return json.loads(response)
@@ -281,7 +299,7 @@
{u'task': {u'url': u'http://your_url/job/my_job/', u'color': u'aborted_anime', u'name': u'my_job'}, u'stuck': False, u'actions': [{u'causes': [{u'shortDescription': u'Started by timer'}]}], u'buildable': False, u'params': u'', u'buildableStartMilliseconds': 1315087293316, u'why': u'Build #2,532 is already in progress (ETA:10 min)', u'blocked': True}
'''
return json.loads(self.jenkins_open(
- urllib2.Request(self.server + Q_INFO)
+ Request(self.server + Q_INFO)
))['items']
def cancel_queue(self, number):
@@ -292,7 +310,7 @@
'''
# Jenkins returns a 302 from this URL, unless Referer is not set,
# then you get a 404.
- self.jenkins_open(urllib2.Request(self.server +
+ self.jenkins_open(Request(self.server +
CANCEL_QUEUE % locals(),
headers={'Referer': self.server}))
@@ -314,11 +332,11 @@
"""
try:
return json.loads(self.jenkins_open(
- urllib2.Request(self.server + INFO)))
+ Request(self.server + INFO)))
except urllib2.HTTPError:
raise JenkinsException("Error communicating with server[%s]"
% self.server)
- except httplib.BadStatusLine:
+ except BadStatusLine:
raise JenkinsException("Error communicating with server[%s]"
% self.server)
except ValueError:
@@ -342,7 +360,7 @@
:param to_name: Name of Jenkins job to copy to, ``str``
'''
self.get_job_info(from_name)
- self.jenkins_open(urllib2.Request(
+ self.jenkins_open(Request(
self.server + COPY_JOB % locals(), ''))
if not self.job_exists(to_name):
raise JenkinsException('create[%s] failed' % (to_name))
@@ -355,7 +373,7 @@
:param new_name: New Jenkins job name, ``str``
'''
self.get_job_info(name)
- self.jenkins_open(urllib2.Request(
+ self.jenkins_open(Request(
self.server + RENAME_JOB % locals(), ''))
if not self.job_exists(new_name):
raise JenkinsException('rename[%s] failed'%(new_name))
@@ -367,7 +385,7 @@
:param name: Name of Jenkins job, ``str``
'''
self.get_job_info(name)
- self.jenkins_open(urllib2.Request(
+ self.jenkins_open(Request(
self.server + DELETE_JOB % locals(), ''))
if self.job_exists(name):
raise JenkinsException('delete[%s] failed' % (name))
@@ -379,7 +397,7 @@
:param name: Name of Jenkins job, ``str``
'''
self.get_job_info(name)
- self.jenkins_open(urllib2.Request(
+ self.jenkins_open(Request(
self.server + ENABLE_JOB % locals(), ''))
def disable_job(self, name):
@@ -389,7 +407,7 @@
:param name: Name of Jenkins job, ``str``
'''
self.get_job_info(name)
- self.jenkins_open(urllib2.Request(
+ self.jenkins_open(Request(
self.server + DISABLE_JOB % locals(), ''))
def job_exists(self, name):
@@ -411,7 +429,7 @@
raise JenkinsException('job[%s] already exists' % (name))
headers = {'Content-Type': 'text/xml'}
- self.jenkins_open(urllib2.Request(
+ self.jenkins_open(Request(
self.server + CREATE_JOB % locals(), config_xml, headers))
if not self.job_exists(name):
raise JenkinsException('create[%s] failed' % (name))
@@ -423,8 +441,8 @@
:param name: Name of Jenkins job, ``str``
:returns: job configuration (XML format)
'''
- request = urllib2.Request(self.server + CONFIG_JOB %
- {"name": urllib.quote(name)})
+ request = Request(self.server + CONFIG_JOB %
+ {"name": quote(name)})
return self.jenkins_open(request)
def reconfig_job(self, name, config_xml):
@@ -438,7 +456,7 @@
self.get_job_info(name)
headers = {'Content-Type': 'text/xml'}
reconfig_url = self.server + CONFIG_JOB % locals()
- self.jenkins_open(urllib2.Request(reconfig_url, config_xml, headers))
+ self.jenkins_open(Request(reconfig_url, config_xml, headers))
def build_job_url(self, name, parameters=None, token=None):
'''
@@ -470,7 +488,7 @@
'''
if not self.job_exists(name):
raise JenkinsException('no such job[%s]' % (name))
- return self.jenkins_open(urllib2.Request(
+ return self.jenkins_open(Request(
self.build_job_url(name, parameters, token)))
def stop_build(self, name, number):
@@ -480,7 +498,7 @@
:param name: Name of Jenkins job, ``str``
:param number: Jenkins build number for the job, ``int``
'''
- self.jenkins_open(urllib2.Request(self.server + STOP_BUILD % locals()))
+ self.jenkins_open(Request(self.server + STOP_BUILD % locals()))
def get_node_info(self, name):
'''
@@ -490,7 +508,7 @@
:returns: Dictionary of node info, ``dict``
'''
try:
- response = self.jenkins_open(urllib2.Request(
+ response = self.jenkins_open(Request(
self.server + NODE_INFO % locals()))
if response:
return json.loads(response)
@@ -520,7 +538,7 @@
:param name: Name of Jenkins node, ``str``
'''
self.get_node_info(name)
- self.jenkins_open(urllib2.Request(
+ self.jenkins_open(Request(
self.server + DELETE_NODE % locals(), ''))
if self.node_exists(name):
raise JenkinsException('delete[%s] failed' % (name))
@@ -535,7 +553,7 @@
info = self.get_node_info(name)
if info['offline']:
return
- self.jenkins_open(urllib2.Request(
+ self.jenkins_open(Request(
self.server + TOGGLE_OFFLINE % locals()))
def enable_node(self, name):
@@ -548,7 +566,7 @@
if not info['offline']:
return
msg = ''
- self.jenkins_open(urllib2.Request(
+ self.jenkins_open(Request(
self.server + TOGGLE_OFFLINE % locals()))
def create_node(self, name, numExecutors=2, nodeDescription=None,
@@ -595,7 +613,7 @@
'json': json.dumps(inner_params)
}
- self.jenkins_open(urllib2.Request(
+ self.jenkins_open(Request(
self.server + CREATE_NODE % urllib.urlencode(params)))
if not self.node_exists(name):
@@ -610,7 +628,7 @@
:returns: Build console output, ``str``
'''
try:
- response = self.jenkins_open(urllib2.Request(
+ response = self.jenkins_open(Request(
self.server + BUILD_CONSOLE_OUTPUT % locals()))
if response:
return response
=== modified file 'tests/test_jenkins.py'
--- tests/test_jenkins.py 2012-05-17 15:24:23 +0000
+++ tests/test_jenkins.py 2014-04-08 06:02:58 +0000
@@ -2,7 +2,7 @@
from mock import patch
-from helper import jenkins
+from tests.helper import jenkins
class JenkinsTest(unittest.TestCase):
=== added file 'tox.ini'
--- tox.ini 1970-01-01 00:00:00 +0000
+++ tox.ini 2014-04-08 06:02:58 +0000
@@ -0,0 +1,14 @@
+# Tox (http://tox.testrun.org/) is a tool for running tests
+# in multiple virtualenvs. This configuration file will run the
+# test suite on all supported python versions. To use it, "pip install tox"
+# and then run "tox" from this directory.
+
+[tox]
+envlist = py26, py27, pypy, py33
+
+[testenv]
+deps =
+ mock
+ pytest
+ pytest-cov
+commands = py.test --cov=jenkins --cov-report=xml --cov-report=term-missing tests
Follow ups
-
Re: [Merge] lp:~msabramo/python-jenkins/python3 into lp:python-jenkins
From: Ken Conley, 2014-04-23
-
Re: [Merge] lp:~msabramo/python-jenkins/python3 into lp:python-jenkins
From: Antoine "hashar" Musso, 2014-04-22
-
Re: [Merge] lp:~msabramo/python-jenkins/python3 into lp:python-jenkins
From: Tully, 2014-04-21
-
Re: [Merge] lp:~msabramo/python-jenkins/python3 into lp:python-jenkins
From: Marc Abramowitz, 2014-04-21
-
Re: [Merge] lp:~msabramo/python-jenkins/python3 into lp:python-jenkins
From: Ken Conley, 2014-04-21
-
Re: [Merge] lp:~msabramo/python-jenkins/python3 into lp:python-jenkins
From: Antoine "hashar" Musso, 2014-04-11
-
Re: [Merge] lp:~msabramo/python-jenkins/python3 into lp:python-jenkins
From: Marc Abramowitz, 2014-04-10
-
Re: [Merge] lp:~msabramo/python-jenkins/python3 into lp:python-jenkins
From: Marc Abramowitz, 2014-04-08
-
Re: [Merge] lp:~msabramo/python-jenkins/python3 into lp:python-jenkins
From: Marc Abramowitz, 2014-04-08
-
Re: [Merge] lp:~msabramo/python-jenkins/python3 into lp:python-jenkins
From: Marc Abramowitz, 2014-04-08
-
Re: [Merge] lp:~msabramo/python-jenkins/python3 into lp:python-jenkins
From: Marc Abramowitz, 2014-04-08
-
Re: [Merge] lp:~msabramo/python-jenkins/python3 into lp:python-jenkins
From: Marc Abramowitz, 2014-04-08