mirror of
https://github.com/status-im/PyGithub.git
synced 2026-09-01 03:11:09 +00:00
Adding communications Retry functionality into requests via urllib3 retry object. (#1002)
This is a continuation of the work started by @allevin on https://github.com/PyGithub/PyGithub/pull/860. I have refactored the testing Framework to use the `httpretty` library in order to use the urllib3 retry feature and therefore be able to test it. Please refer to https://github.com/PyGithub/PyGithub/pull/860 for additional context. cc: @allevin @mfonville @jrouquie @sfdye Closes #757 Closes #860
This commit is contained in:
@@ -104,6 +104,7 @@ from ExposeAllAttributes import *
|
||||
from BadAttributes import *
|
||||
from Equality import *
|
||||
from Search import *
|
||||
from Retry import *
|
||||
|
||||
from Issue33 import *
|
||||
from Issue50 import *
|
||||
|
||||
+69
-15
@@ -41,6 +41,9 @@ import os
|
||||
import sys
|
||||
import traceback
|
||||
import unittest
|
||||
import httpretty
|
||||
from requests.structures import CaseInsensitiveDict
|
||||
from urllib3.util import Url
|
||||
|
||||
import github
|
||||
|
||||
@@ -163,14 +166,28 @@ class ReplayingConnection:
|
||||
self.__file = file
|
||||
self.__protocol = protocol
|
||||
self.__host = host
|
||||
self.__port = str(port)
|
||||
self.__port = port
|
||||
self.response_headers = CaseInsensitiveDict()
|
||||
|
||||
self.__cnx = self._realConnection(host, port, *args, **kwds)
|
||||
|
||||
def request(self, verb, url, input, headers):
|
||||
full_url = Url(scheme=self.__protocol, host=self.__host, port=self.__port, path=url)
|
||||
|
||||
httpretty.register_uri(
|
||||
verb,
|
||||
full_url.url,
|
||||
body=self.__request_callback
|
||||
)
|
||||
|
||||
self.__cnx.request(verb, url, input, headers)
|
||||
|
||||
def __readNextRequest(self, verb, url, input, headers):
|
||||
fixAuthorizationHeader(headers)
|
||||
self.__testCase.assertEqual(self.__protocol, readLine(self.__file))
|
||||
self.__testCase.assertEqual(verb, readLine(self.__file))
|
||||
self.__testCase.assertEqual(self.__host, readLine(self.__file))
|
||||
self.__testCase.assertEqual(self.__port, readLine(self.__file))
|
||||
self.__testCase.assertEqual(str(self.__port), readLine(self.__file))
|
||||
self.__testCase.assertEqual(self.__splitUrl(url), self.__splitUrl(readLine(self.__file)))
|
||||
self.__testCase.assertEqual(headers, eval(readLine(self.__file)))
|
||||
expectedInput = readLine(self.__file)
|
||||
@@ -193,29 +210,58 @@ class ReplayingConnection:
|
||||
base, qs = splitedUrl
|
||||
return (base, sorted(qs.split("&")))
|
||||
|
||||
def getresponse(self):
|
||||
def __request_callback(self, request, uri, response_headers):
|
||||
self.__readNextRequest(self.__cnx.verb, self.__cnx.url, self.__cnx.input, self.__cnx.headers)
|
||||
|
||||
status = int(readLine(self.__file))
|
||||
headers = eval(readLine(self.__file))
|
||||
self.response_headers = CaseInsensitiveDict(eval(readLine(self.__file)))
|
||||
output = readLine(self.__file)
|
||||
|
||||
return FakeHttpResponse(status, headers, output)
|
||||
|
||||
def close(self):
|
||||
readLine(self.__file)
|
||||
|
||||
if atLeastPython3:
|
||||
output = bytes(output, 'utf-8')
|
||||
|
||||
def ReplayingHttpConnection(testCase, file, *args, **kwds):
|
||||
return ReplayingConnection(testCase, file, "http", *args, **kwds)
|
||||
# make a copy of the headers and remove the ones that interfere with the response handling
|
||||
adding_headers = CaseInsensitiveDict(self.response_headers)
|
||||
adding_headers.pop('content-length', None)
|
||||
adding_headers.pop('transfer-encoding', None)
|
||||
adding_headers.pop('content-encoding', None)
|
||||
|
||||
response_headers.update(adding_headers)
|
||||
return [status, response_headers, output]
|
||||
|
||||
def getresponse(self):
|
||||
# call original connection, this will go all the way down to the python socket and will be intercepted by httpretty
|
||||
response = self.__cnx.getresponse()
|
||||
|
||||
# restore original headers to the response
|
||||
response.headers = self.response_headers
|
||||
|
||||
return response
|
||||
|
||||
def close(self):
|
||||
self.__cnx.close()
|
||||
|
||||
|
||||
def ReplayingHttpsConnection(testCase, file, *args, **kwds):
|
||||
return ReplayingConnection(testCase, file, "https", *args, **kwds)
|
||||
class ReplayingHttpConnection(ReplayingConnection):
|
||||
_realConnection = github.Requester.HTTPRequestsConnectionClass
|
||||
|
||||
def __init__(self, testCase, file, *args, **kwds):
|
||||
ReplayingConnection.__init__(self, testCase, file, "http", *args, **kwds)
|
||||
|
||||
|
||||
class ReplayingHttpsConnection(ReplayingConnection):
|
||||
_realConnection = github.Requester.HTTPSRequestsConnectionClass
|
||||
|
||||
def __init__(self, testCase, file, *args, **kwds):
|
||||
ReplayingConnection.__init__(self, testCase, file, "https", *args, **kwds)
|
||||
|
||||
|
||||
class BasicTestCase(unittest.TestCase):
|
||||
recordMode = False
|
||||
tokenAuthMode = False
|
||||
jwtAuthMode = False
|
||||
retry = None
|
||||
replayDataFolder = os.path.join(os.path.dirname(__file__), "ReplayData")
|
||||
|
||||
def setUp(self):
|
||||
@@ -247,8 +293,12 @@ class BasicTestCase(unittest.TestCase):
|
||||
self.client_secret = "client_secret"
|
||||
self.jwt = "jwt"
|
||||
|
||||
httpretty.enable(allow_net_connect=False)
|
||||
|
||||
def tearDown(self):
|
||||
unittest.TestCase.tearDown(self)
|
||||
httpretty.disable()
|
||||
httpretty.reset()
|
||||
self.__closeReplayFileIfNeeded()
|
||||
github.Requester.Requester.resetConnectionClasses()
|
||||
|
||||
@@ -298,11 +348,11 @@ class TestCase(BasicTestCase):
|
||||
github.Requester.Requester.setOnCheckMe(self.getFrameChecker())
|
||||
|
||||
if self.tokenAuthMode:
|
||||
self.g = github.Github(self.oauth_token)
|
||||
self.g = github.Github(self.oauth_token, retry=self.retry)
|
||||
elif self.jwtAuthMode:
|
||||
self.g = github.Github(jwt=self.jwt)
|
||||
self.g = github.Github(jwt=self.jwt, retry=self.retry)
|
||||
else:
|
||||
self.g = github.Github(self.login, self.password)
|
||||
self.g = github.Github(self.login, self.password, retry=self.retry)
|
||||
|
||||
|
||||
def activateRecordMode(): # pragma no cover (Function useful only when recording new tests, not used during automated tests)
|
||||
@@ -315,3 +365,7 @@ def activateTokenAuthMode(): # pragma no cover (Function useful only when recor
|
||||
|
||||
def activateJWTAuthMode(): # pragma no cover (Function useful only when recording new tests, not used during automated tests)
|
||||
BasicTestCase.jwtAuthMode = True
|
||||
|
||||
|
||||
def enableRetry(retry):
|
||||
BasicTestCase.retry = retry
|
||||
|
||||
@@ -38,6 +38,6 @@ None
|
||||
/repos/edhollandAL/PyGithub/releases/1210837/assets?label=unit+test+artifact&name=archive.zip
|
||||
{'Authorization': 'Basic login_and_password_removed', 'Content-Length': '140', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/zip'}
|
||||
None
|
||||
204
|
||||
[('content-length', '150'), ('vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('x-served-by', '139317cebd6caf9cd03889139437f00b'), ('x-xss-protection', '1; mode=block'), ('x-content-type-options', 'nosniff'), ('etag', '"26708914904a29b8c9fd2ac006beb9db"'), ('access-control-allow-credentials', 'true'), ('status', '200 OK'), ('x-ratelimit-remaining', '4942'), ('x-github-media-type', 'github.v3; format=json'), ('access-control-expose-headers', 'ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('x-github-request-id', '56BCFFD3:5677:5265FA1:553A03F5'), ('cache-control', 'private, max-age=60, s-maxage=60'), ('last-modified', 'Fri, 24 Apr 2015 08:43:32 GMT'), ('date', 'Fri, 24 Apr 2015 08:51:01 GMT'), ('access-control-allow-origin', '*'), ('content-security-policy', "default-src 'none'"), ('strict-transport-security', 'max-age=31536000; includeSubdomains; preload'), ('server', 'GitHub.com'), ('x-ratelimit-limit', '5000'), ('x-frame-options', 'deny'), ('content-type', 'application/zip'), ('x-ratelimit-reset', '1429867683')]
|
||||
201
|
||||
[('content-length', '155'), ('vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('x-served-by', '139317cebd6caf9cd03889139437f00b'), ('x-xss-protection', '1; mode=block'), ('x-content-type-options', 'nosniff'), ('etag', '"26708914904a29b8c9fd2ac006beb9db"'), ('access-control-allow-credentials', 'true'), ('status', '201 CREATED'), ('x-ratelimit-remaining', '4942'), ('x-github-media-type', 'github.v3; format=json'), ('access-control-expose-headers', 'ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('x-github-request-id', '56BCFFD3:5677:5265FA1:553A03F5'), ('cache-control', 'private, max-age=60, s-maxage=60'), ('last-modified', 'Fri, 24 Apr 2015 08:43:32 GMT'), ('date', 'Fri, 24 Apr 2015 08:51:01 GMT'), ('access-control-allow-origin', '*'), ('content-security-policy', "default-src 'none'"), ('strict-transport-security', 'max-age=31536000; includeSubdomains; preload'), ('server', 'GitHub.com'), ('x-ratelimit-limit', '5000'), ('x-frame-options', 'deny'), ('content-type', 'application/zip'), ('x-ratelimit-reset', '1429867683')]
|
||||
{"url":"/repos/edhollandAL/PyGithub/releases/1210837/assets/xxx","id":"xxx","name":"archive.zip","label":"unit test artifact","uploader":"unittests"}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
https
|
||||
GET
|
||||
api.github.com
|
||||
None
|
||||
/repos/PyGithub/PyGithub
|
||||
{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}
|
||||
None
|
||||
502
|
||||
[('Server', 'GitHub.com'), ('Date', 'Fri, 26 Oct 2018 06:02:42 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Status', '502 Bad Gateway'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4970'), ('X-RateLimit-Reset', '1540536267'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP'), ('ETag', 'W/"3ffd69d4f4e7383eae948812b1eb72e5"'), ('X-OAuth-Scopes', 'repo'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; param=star; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'F9D6:235E:3C00DD:772BC6:5BD2AE02')]
|
||||
{"error": "Server Error"}
|
||||
|
||||
https
|
||||
GET
|
||||
api.github.com
|
||||
None
|
||||
/repos/PyGithub/PyGithub
|
||||
{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}
|
||||
None
|
||||
502
|
||||
[('Server', 'GitHub.com'), ('Date', 'Fri, 26 Oct 2018 06:02:42 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Status', '502 Bad Gateway'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4970'), ('X-RateLimit-Reset', '1540536267'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP'), ('ETag', 'W/"3ffd69d4f4e7383eae948812b1eb72e5"'), ('X-OAuth-Scopes', 'repo'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; param=star; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'F9D6:235E:3C00DD:772BC6:5BD2AE02')]
|
||||
{"error": "Server Error"}
|
||||
|
||||
https
|
||||
GET
|
||||
api.github.com
|
||||
None
|
||||
/repos/PyGithub/PyGithub
|
||||
{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}
|
||||
None
|
||||
502
|
||||
[('Server', 'GitHub.com'), ('Date', 'Fri, 26 Oct 2018 06:02:42 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Status', '502 Bad Gateway'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4970'), ('X-RateLimit-Reset', '1540536267'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP'), ('ETag', 'W/"3ffd69d4f4e7383eae948812b1eb72e5"'), ('X-OAuth-Scopes', 'repo'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; param=star; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'F9D6:235E:3C00DD:772BC6:5BD2AE02')]
|
||||
{"error": "Server Error"}
|
||||
|
||||
https
|
||||
GET
|
||||
api.github.com
|
||||
None
|
||||
/repos/PyGithub/PyGithub
|
||||
{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}
|
||||
None
|
||||
502
|
||||
[('Server', 'GitHub.com'), ('Date', 'Fri, 26 Oct 2018 06:02:42 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Status', '502 Bad Gateway'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4970'), ('X-RateLimit-Reset', '1540536267'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP'), ('ETag', 'W/"3ffd69d4f4e7383eae948812b1eb72e5"'), ('X-OAuth-Scopes', 'repo'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; param=star; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'F9D6:235E:3C00DD:772BC6:5BD2AE02')]
|
||||
{"error": "Server Error"}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,11 @@
|
||||
https
|
||||
GET
|
||||
api.github.com
|
||||
None
|
||||
/repos/PyGithub/PyGithub
|
||||
{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}
|
||||
None
|
||||
400
|
||||
[('Server', 'GitHub.com'), ('Date', 'Fri, 26 Oct 2018 06:02:42 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Status', '400 Bad Request'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4970'), ('X-RateLimit-Reset', '1540536267'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP'), ('ETag', 'W/"3ffd69d4f4e7383eae948812b1eb72e5"'), ('X-OAuth-Scopes', 'repo'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; param=star; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'F9D6:235E:3C00DD:772BC6:5BD2AE02')]
|
||||
{"error": "Bad Request"}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
############################ Copyrights and license ############################
|
||||
# #
|
||||
# Copyright 2018 Justin Kufro <jkufro@andrew.cmu.edu> #
|
||||
# Copyright 2018 Ivan Minno <iminno@andrew.cmu.edu> #
|
||||
# Copyright 2018 Zilei Gu <zileig@andrew.cmu.edu> #
|
||||
# Copyright 2018 Yves Zumbach <yzumbach@andrew.cmu.edu> #
|
||||
# Copyright 2018 Leying Chen <leyingc@andrew.cmu.edu> #
|
||||
# #
|
||||
# This file is part of PyGithub. #
|
||||
# http://pygithub.readthedocs.io/ #
|
||||
# #
|
||||
# PyGithub is free software: you can redistribute it and/or modify it under #
|
||||
# the terms of the GNU Lesser General Public License as published by the Free #
|
||||
# Software Foundation, either version 3 of the License, or (at your option) #
|
||||
# any later version. #
|
||||
# #
|
||||
# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
|
||||
# details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU Lesser General Public License #
|
||||
# along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
################################################################################
|
||||
import urllib3
|
||||
from httpretty import httpretty
|
||||
|
||||
import Framework
|
||||
|
||||
import requests
|
||||
|
||||
from github import GithubException
|
||||
from github.Repository import Repository
|
||||
|
||||
REPO_NAME = 'PyGithub/PyGithub'
|
||||
|
||||
|
||||
class Retry(Framework.TestCase):
|
||||
def setUp(self):
|
||||
# status codes returned on random github server errors
|
||||
status_forcelist = (500, 502, 504)
|
||||
retry = urllib3.Retry(
|
||||
total=3,
|
||||
read=3,
|
||||
connect=3,
|
||||
status_forcelist=status_forcelist
|
||||
)
|
||||
|
||||
Framework.enableRetry(retry)
|
||||
Framework.TestCase.setUp(self)
|
||||
|
||||
def testShouldNotRetryWhenStatusNotOnList(self):
|
||||
try:
|
||||
self.g.get_repo(REPO_NAME)
|
||||
except GithubException:
|
||||
self.assertEquals(len(httpretty.latest_requests), 1)
|
||||
|
||||
def testReturnsRepoAfter3Retries(self):
|
||||
repository = self.g.get_repo(REPO_NAME)
|
||||
self.assertEquals(len(httpretty.latest_requests), 4)
|
||||
for request in httpretty.latest_requests:
|
||||
self.assertEquals(request.path, '/repos/' + REPO_NAME)
|
||||
|
||||
self.assertIsInstance(repository, Repository)
|
||||
self.assertEquals(repository.full_name, REPO_NAME)
|
||||
|
||||
def testReturnsRepoAfter1Retry(self):
|
||||
repository = self.g.get_repo(REPO_NAME)
|
||||
self.assertEquals(len(httpretty.latest_requests), 2)
|
||||
for request in httpretty.latest_requests:
|
||||
self.assertEquals(request.path, '/repos/' + REPO_NAME)
|
||||
|
||||
self.assertIsInstance(repository, Repository)
|
||||
self.assertEquals(repository.full_name, REPO_NAME)
|
||||
|
||||
def testRaisesRetryErrorAfterMaxRetries(self):
|
||||
try:
|
||||
response = self.g.get_repo('PyGithub/PyGithub')
|
||||
self.fail("RetryError should have been raised")
|
||||
except requests.exceptions.RetryError:
|
||||
self.assertEquals(len(httpretty.latest_requests), 4)
|
||||
for request in httpretty.latest_requests:
|
||||
self.assertEquals(request.path, '/repos/PyGithub/PyGithub')
|
||||
Reference in New Issue
Block a user