def _request(self, method: str, url: str, fields: Optional[Mapping[str, str]] = None, headers: Mapping[str, str] = {}, body: Optional[bytes] = None): if method in ('PATCH', 'POST', 'PUT'): headers = { **self.base_headers, 'Content-Type': f'application/json; charset={self.API_BODY_ENCODING.upper()}', **headers } body = body.encode(self.API_BODY_ENCODING) if body and hasattr( body, 'encode') else body else: headers = {**self.base_headers, **headers} response = self.http.request(method, self._resolve_url(url), headers=headers, body=body) content_type = ContentType.from_response(response) if content_type.is_json(): return json.loads( response.data.decode( content_type.charset( default=self.API_BODY_ENCODING).lower())) else: return response.data.decode( content_type.charset(default=self.API_BODY_ENCODING).lower())
def test_str(self): @dataclass class SubTest: content_type: ContentType expected: str subtests = [ SubTest(ContentType(type='text', subtype='plain'), 'text/plain'), SubTest(ContentType(type='application', subtype='json'), 'application/json'), SubTest( ContentType(type='application', subtype='json', attribute='charset', value='UTF-8'), 'application/json; charset=UTF-8'), ] for subtest in subtests: with self.subTest(subtest=subtest): assert str(subtest.content_type) == subtest.expected
def test_charset(self): @dataclass class SubTest: content_type: ContentType default: str expected: str subtests = [ # charset() SubTest(ContentType(type='text', subtype='plain', attribute='charset', value='utf-8'), default=None, expected='utf-8'), SubTest(ContentType(type='text', subtype='plain', attribute='charset', value='UTF-8'), default=None, expected='UTF-8'), SubTest(ContentType(type='text', subtype='plain', attribute='charset'), default=None, expected='UTF-8'), SubTest(ContentType(type='text', subtype='plain'), default=None, expected='UTF-8'), # charset(default=...) SubTest(ContentType(type='text', subtype='plain', attribute='charset', value='utf-8'), default='ascii', expected='utf-8'), SubTest(ContentType(type='text', subtype='plain', attribute='charset', value='UTF-8'), default='ascii', expected='UTF-8'), SubTest(ContentType(type='text', subtype='plain'), default='utf-8', expected='UTF-8'), ] for subtest in subtests: with self.subTest(subtest=subtest): if subtest.default: assert subtest.content_type.charset( subtest.default) == subtest.expected else: assert subtest.content_type.charset() == subtest.expected
def test_from_response(self): @dataclass class SubTest: content_type: str expected: ContentType subtests = [ SubTest('text/plain', ContentType(type='text', subtype='plain')), SubTest('application/json', ContentType(type='application', subtype='json')), SubTest( 'application/json; charset=UTF-8', ContentType(type='application', subtype='json', attribute='charset', value='UTF-8')), ] for subtest in subtests: with self.subTest(subtest=subtest): mock_response = MagicMock(getheader=MagicMock( return_value=subtest.content_type)) assert ContentType.from_response( mock_response) == subtest.expected
def _request(self, method: str, url: str, fields: Optional[Mapping[str, str]] = None, headers: Mapping[str, str] = None, body: Union[bytes, str, None] = None): headers = headers if headers else {} if method in ('PATCH', 'POST', 'PUT'): headers = { **self.base_headers, 'Content-Type': self.API_CONTENT_TYPE, **headers } body = body.encode(self.API_BODY_ENCODING) if isinstance( body, str) else body else: headers = {**self.base_headers, **headers} response = self.http.request(method, self._resolve_url(url), fields=fields, headers=headers, body=body) content_type = ContentType.from_response(response) if content_type.is_json(): content = json.loads( response.data.decode( content_type.charset( default=self.API_BODY_ENCODING).lower())) else: content = response.data.decode( content_type.charset(default=self.API_BODY_ENCODING).lower()) self._logger.debug( 'GitHub API request: %s <%s>\nGitHub API response (status: %s; content type: %s):\n%s', method, url, HTTPStatus(response.status), content_type, content) if response.status >= 400: raise GitHubClientError(response.status, response.reason, content) return content