1111from __future__ import print_function
1212
1313import argparse
14- import BaseHTTPServer
15- import ConfigParser
1614import json
1715import os
1816import random
2624import time
2725import traceback
2826import unittest
29- import urlparse
27+
28+
29+ from six .moves .BaseHTTPServer import BaseHTTPRequestHandler , HTTPServer
30+ from six .moves .configparser import ConfigParser
31+ from six .moves .urllib .parse import parse_qs , urlparse
3032
3133from lxml import html
3234
3537from trac .util .translation import _
3638
3739import requests
40+ import six
3841
3942
4043GIT = 'test-git-foo'
@@ -83,6 +86,9 @@ def git_check_output(*args, **kwargs):
8386 as a string.
8487 """
8588 repo = kwargs .pop ('repo' , None )
89+ kwargs .setdefault ('text' , True )
90+ if six .PY2 :
91+ del kwargs ['text' ]
8692
8793 if repo is None :
8894 cmdargs = ["git" ] + list (args )
@@ -136,9 +142,12 @@ def createTracEnvironment(cls, **kwargs):
136142 subprocess .check_output ([TRAC_ADMIN_BIN , d (ENV ), 'permission' ,
137143 'add' , 'anonymous' , 'TRAC_ADMIN' ])
138144
139- conf = ConfigParser .ConfigParser ()
140- with open (d (CONF ), 'rb' ) as fp :
141- conf .readfp (fp )
145+ conf = ConfigParser ()
146+ with open (d (CONF ), 'r' ) as fp :
147+ if six .PY2 :
148+ conf .readfp (fp )
149+ else :
150+ conf .read_file (fp )
142151
143152 conf .add_section ('components' )
144153 conf .set ('components' , 'trac.versioncontrol.web_ui.browser.BrowserModule' , 'disabled' )
@@ -210,7 +219,7 @@ def createTracEnvironment(cls, **kwargs):
210219 conf .set ('trac' , 'permission_policies' ,
211220 'GitHubPolicy, %s' % old_permission_policies )
212221
213- with open (d (CONF ), 'wb ' ) as fp :
222+ with open (d (CONF ), 'w ' ) as fp :
214223 conf .write (fp )
215224
216225 with open (d (HTDIGEST ), 'w' ) as fp :
@@ -269,7 +278,7 @@ def makeGitCommit(repo, path, content, message='edit', branch=None):
269278
270279 if branch != GIT_DEFAULT_BRANCH :
271280 git_check_output ('checkout' , branch , repo = repo )
272- with open (d (repo , path ), 'wb ' ) as fp :
281+ with open (d (repo , path ), 'w ' ) as fp :
273282 fp .write (content )
274283 git_check_output ('add' , path , repo = repo )
275284 git_check_output ('commit' , '-m' , message , repo = repo )
@@ -406,11 +415,11 @@ def testLogin(self):
406415 response = requests .get (u ('github/login' ), allow_redirects = False )
407416 self .assertEqual (response .status_code , 302 )
408417
409- redirect_url = urlparse . urlparse (response .headers ['Location' ])
418+ redirect_url = urlparse (response .headers ['Location' ])
410419 self .assertEqual (redirect_url .scheme , 'https' )
411420 self .assertEqual (redirect_url .netloc , 'github.com' )
412421 self .assertEqual (redirect_url .path , '/login/oauth/authorize' )
413- params = urlparse . parse_qs (redirect_url .query , keep_blank_values = True )
422+ params = parse_qs (redirect_url .query , keep_blank_values = True )
414423 state = params ['state' ][0 ] # this is a random value
415424 self .assertEqual (params , {
416425 'client_id' : ['01234567890123456789' ],
@@ -490,7 +499,7 @@ def setUpClass(cls):
490499 cls .trac_env_broken = trac_env_broken
491500 cls .trac_env_broken_api = trac_env_broken_api
492501
493- with open (d (SECRET ), 'wb ' ) as fp :
502+ with open (d (SECRET ), 'w ' ) as fp :
494503 fp .write ('98765432109876543210' )
495504
496505
@@ -505,11 +514,11 @@ def testLoginWithReqEmail(self):
505514 response = requests .get (u ('github/login' ), allow_redirects = False )
506515 self .assertEqual (response .status_code , 302 )
507516
508- redirect_url = urlparse . urlparse (response .headers ['Location' ])
517+ redirect_url = urlparse (response .headers ['Location' ])
509518 self .assertEqual (redirect_url .scheme , 'https' )
510519 self .assertEqual (redirect_url .netloc , 'github.com' )
511520 self .assertEqual (redirect_url .path , '/login/oauth/authorize' )
512- params = urlparse . parse_qs (redirect_url .query , keep_blank_values = True )
521+ params = parse_qs (redirect_url .query , keep_blank_values = True )
513522 state = params ['state' ][0 ] # this is a random value
514523 self .assertEqual (params , {
515524 'client_id' : ['01234567890123456789' ],
@@ -527,11 +536,11 @@ def loginAndVerifyClientId(self, expected_client_id):
527536 response = requests .get (u ('github/login' ), allow_redirects = False )
528537 self .assertEqual (response .status_code , 302 )
529538
530- redirect_url = urlparse . urlparse (response .headers ['Location' ])
539+ redirect_url = urlparse (response .headers ['Location' ])
531540 self .assertEqual (redirect_url .scheme , 'https' )
532541 self .assertEqual (redirect_url .netloc , 'github.com' )
533542 self .assertEqual (redirect_url .path , '/login/oauth/authorize' )
534- params = urlparse . parse_qs (redirect_url .query , keep_blank_values = True )
543+ params = parse_qs (redirect_url .query , keep_blank_values = True )
535544 state = params ['state' ][0 ] # this is a random value
536545 self .assertEqual (params , {
537546 'client_id' : [expected_client_id ],
@@ -636,8 +645,8 @@ def attemptValidOauth(self, testenv, callback, **kwargs):
636645 self .assertEqual (response .status_code , 302 )
637646
638647 # Extract the state from the redirect
639- redirect_url = urlparse . urlparse (response .headers ['Location' ])
640- params = urlparse . parse_qs (redirect_url .query , keep_blank_values = True )
648+ redirect_url = urlparse (response .headers ['Location' ])
649+ params = parse_qs (redirect_url .query , keep_blank_values = True )
641650 state = params ['state' ][0 ] # this is a random value
642651 response = session .get (
643652 u ('github/oauth' ),
@@ -938,7 +947,7 @@ def testAlternativeRepository(self):
938947 def testCommit (self ):
939948 self .makeGitCommit (GIT , 'foo' , 'foo content\n ' )
940949 output = self .openGitHubHook ()
941- self . assertRegexpMatches ( output , r"Running hook on \(default\)\n"
950+ six . assertRegex ( self , output , r"Running hook on \(default\)\n"
942951 r"\* Updating clone\n"
943952 r"\* Synchronizing with clone\n"
944953 r"\* Adding commit [0-9a-f]{40}\n" )
@@ -947,7 +956,7 @@ def testMultipleCommits(self):
947956 self .makeGitCommit (GIT , 'bar' , 'bar content\n ' )
948957 self .makeGitCommit (GIT , 'bar' , 'more bar content\n ' )
949958 output = self .openGitHubHook (2 )
950- self . assertRegexpMatches ( output , r"Running hook on \(default\)\n"
959+ six . assertRegex ( self , output , r"Running hook on \(default\)\n"
951960 r"\* Updating clone\n"
952961 r"\* Synchronizing with clone\n"
953962 r"\* Adding commits [0-9a-f]{40}, [0-9a-f]{40}\n" )
@@ -958,7 +967,7 @@ def testCommitOnBranch(self):
958967 self .makeGitBranch (ALTGIT , 'unstable/1.0' )
959968 self .makeGitCommit (ALTGIT , 'unstable' , 'unstable branch\n ' , branch = 'unstable/1.0' )
960969 output = self .openGitHubHook (2 , 'alt' )
961- self . assertRegexpMatches ( output , r"Running hook on alt\n"
970+ six . assertRegex ( self , output , r"Running hook on alt\n"
962971 r"\* Updating clone\n"
963972 r"\* Synchronizing with clone\n"
964973 r"\* Adding commit [0-9a-f]{40}\n"
@@ -969,7 +978,7 @@ def testUnknownCommit(self):
969978 random_id = '' .join (random .choice ('0123456789abcdef' ) for _ in range (40 ))
970979 payload = {'commits' : [{'id' : random_id , 'message' : '' , 'distinct' : True }]}
971980 response = requests .post (u ('github' ), json = payload , headers = HEADERS )
972- self . assertRegexpMatches ( response .text , r"Running hook on \(default\)\n"
981+ six . assertRegex ( self , response .text , r"Running hook on \(default\)\n"
973982 r"\* Updating clone\n"
974983 r"\* Synchronizing with clone\n"
975984 r"\* Unknown commit [0-9a-f]{40}\n" )
@@ -1095,13 +1104,13 @@ class GitHubPostCommitHookWithUpdateHookTests(TracGitHubTests):
10951104
10961105 @classmethod
10971106 def createUpdateHook (cls ):
1098- with open (d (UPDATEHOOK ), 'wb ' ) as fp :
1107+ with open (d (UPDATEHOOK ), 'w ' ) as fp :
10991108 # simple shell script to echo back all input
11001109 fp .write ("""#!/bin/sh\n exec cat""" )
11011110 os .fchmod (fp .fileno (), 0o755 )
11021111
11031112 def createFailingUpdateHook (cls ):
1104- with open (d (UPDATEHOOK ), 'wb ' ) as fp :
1113+ with open (d (UPDATEHOOK ), 'w ' ) as fp :
11051114 fp .write ("""#!/bin/sh\n exit 1""" )
11061115 os .fchmod (fp .fileno (), 0o755 )
11071116
@@ -1128,7 +1137,7 @@ def testUpdateHook(self):
11281137 self .makeGitCommit (GIT , 'foo' , 'foo content\n ' )
11291138 payload = self .makeGitHubHookPayload ()
11301139 output = self .openGitHubHook (payload = payload )
1131- self . assertRegexpMatches ( output , r"Running hook on \(default\)\n"
1140+ six . assertRegex ( self , output , r"Running hook on \(default\)\n"
11321141 r"\* Updating clone\n"
11331142 r"\* Synchronizing with clone\n"
11341143 r"\* Adding commit [0-9a-f]{40}\n"
@@ -1139,14 +1148,14 @@ def testUpdateHookExecFailure(self):
11391148 os .chmod (d (UPDATEHOOK ), 0o644 )
11401149 self .makeGitCommit (GIT , 'bar' , 'bar content\n ' )
11411150 payload = self .makeGitHubHookPayload ()
1142- with self . assertRaisesRegexp ( requests .HTTPError , r'^500 Server Error: Internal Server Error' ):
1151+ with six . assertRaisesRegex ( self , requests .HTTPError , r'^500 Server Error: Internal Server Error' ):
11431152 output = self .openGitHubHook (payload = payload )
11441153
11451154 def testUpdateHookFailure (self ):
11461155 self .createFailingUpdateHook ()
11471156 self .makeGitCommit (GIT , 'baz' , 'baz content\n ' )
11481157 payload = self .makeGitHubHookPayload ()
1149- with self . assertRaisesRegexp ( requests .HTTPError , r'^500 Server Error: Internal Server Error' ):
1158+ with six . assertRaisesRegex ( self , requests .HTTPError , r'^500 Server Error: Internal Server Error' ):
11501159 output = self .openGitHubHook (payload = payload )
11511160
11521161
@@ -1160,7 +1169,7 @@ class GitHubPostCommitHookWithCacheTests(GitHubPostCommitHookTests):
11601169 cached_git = True
11611170
11621171
1163- class GitHubAPIMock (BaseHTTPServer . BaseHTTPRequestHandler ):
1172+ class GitHubAPIMock (BaseHTTPRequestHandler ):
11641173 def log_message (self , format , * args ):
11651174 # Visibly differentiate GitHub API mock logging from tracd logs
11661175 sys .stderr .write ("%s [%s] %s\n " %
@@ -1221,7 +1230,7 @@ def do_GET(self):
12211230 self .send_header ("Content-Type" , contenttype )
12221231 self .end_headers ()
12231232
1224- self .wfile .write (json .dumps (answer ))
1233+ self .wfile .write (json .dumps (answer , ensure_ascii = True ). encode ( 'ascii' ))
12251234
12261235 def do_POST (self ):
12271236 md = self .server .mockdata
@@ -1239,9 +1248,9 @@ def do_POST(self):
12391248 chunk = self .rfile .read (chunk_size )
12401249 if not chunk :
12411250 break
1242- L .append (chunk )
1251+ L .append (chunk . decode ( 'ascii' ) )
12431252 size_remaining -= len (L [- 1 ])
1244- args = urlparse . parse_qs ('' .join (L ))
1253+ args = parse_qs ('' .join (L ))
12451254
12461255 retcode = 404
12471256 answer = {}
@@ -1255,7 +1264,7 @@ def do_POST(self):
12551264 self .send_response (retcode )
12561265 self .send_header ("Content-Type" , contenttype )
12571266 self .end_headers ()
1258- self .wfile .write (json .dumps (answer ))
1267+ self .wfile .write (json .dumps (answer , ensure_ascii = True ). encode ( 'ascii' ))
12591268
12601269
12611270class TracContext (object ):
@@ -1836,7 +1845,7 @@ def test_014_hook_membership_event_add_team(self):
18361845 self .assertGreater (len (data ), 0 , "No groups returned after update" )
18371846 self .assertIn (users [0 ]["login" ], data ,
18381847 "User %s expected after update, but not present" % users [0 ]["login" ])
1839- self . assertItemsEqual (
1848+ six . assertCountEqual ( self ,
18401849 data [users [0 ]["login" ]],
18411850 (u"github-%s-justice-league" % self .organization , u"github-%s" % self .organization ),
18421851 "User %s does not have expected groups after update" % users [0 ]["login" ])
@@ -1901,7 +1910,7 @@ def test_015_hook_membership_event_add_member(self):
19011910 self .assertGreater (len (data ), 0 , "No groups returned after update" )
19021911 self .assertIn (users [1 ]["login" ], data ,
19031912 "User %s expected after update, but not present" % users [1 ]["login" ])
1904- self . assertItemsEqual (
1913+ six . assertCountEqual ( self ,
19051914 data [users [1 ]["login" ]],
19061915 (u"github-%s-justice-league" % self .organization , u"github-%s" % self .organization ),
19071916 "User %s does not have expected groups after update" % users [1 ]["login" ])
@@ -2113,7 +2122,7 @@ def updateMockData(md, retcode=None, contenttype=None, answers=None,
21132122 JSON-encoded and returned for requests to the paths.
21142123 :param postcallback: A callback function called for the next POST requests.
21152124 Arguments are the requested path and a dict of POST
2116- data as returned by `urlparse. parse_qs()`. The
2125+ data as returned by `parse_qs()`. The
21172126 callback should return a tuple `(retcode, answer)`
21182127 where `retcode` is the HTTP return code and `answer`
21192128 will be JSON-encoded and sent to the client. Note that
@@ -2148,7 +2157,7 @@ def apiMockServer(port, mockdata):
21482157 be JSON-encoded and returned. Use `updateMockData()` to
21492158 update the contents of the mockdata dict.
21502159 """
2151- httpd = BaseHTTPServer . HTTPServer (('127.0.0.1' , port ), GitHubAPIMock )
2160+ httpd = HTTPServer (('127.0.0.1' , port ), GitHubAPIMock )
21522161 # Make mockdata available to server
21532162 httpd .mockdata = mockdata
21542163 httpd .serve_forever ()
0 commit comments