diff --git a/pwclient/api.py b/pwclient/api.py index fcd3673..d5b4b15 100644 --- a/pwclient/api.py +++ b/pwclient/api.py @@ -9,10 +9,9 @@ import json import http import re +import requests import sys -import urllib.error import urllib.parse -import urllib.request from . import exceptions from . import xmlrpc @@ -470,72 +469,63 @@ def _generate_headers(self, additional_headers=None): return headers - def _get(self, url): - request = urllib.request.Request( - url=url, method='GET', headers=self._generate_headers() + def _get(self, url, params=None): + r = requests.get( + url, params=params, headers=self._generate_headers() ) + if r.status_code == http.HTTPStatus.NOT_FOUND: + # the XML-RPC API returns an empty body. To let callers handle + # this, we return instead of causing an error here + return r try: - with urllib.request.urlopen(request) as resp: - data = resp.read() - headers = resp.getheaders() - except urllib.error.HTTPError as exc: - # the XML-RPC API returns an empty body, annoyingly, so we must - # emulate this - if exc.status == http.HTTPStatus.NOT_FOUND: - return {}, {} - + r.raise_for_status() + except requests.exceptions.RequestException as exc: sys.stderr.write('Request failed\n\n') sys.stderr.write('Response:\n') - sys.stderr.write(exc.read().decode('utf-8')) + sys.stderr.write(r.text) sys.exit(1) - return data, headers + return r def _post(self, url, data): - request = urllib.request.Request( - url=url, - data=json.dumps(data).encode('utf-8'), - method='POST', - headers=self._generate_headers( + r = requests.post( + url, + data=data, + headers=self.generate_headers( { 'Content-Type': 'application/json', }, ), ) try: - with urllib.request.urlopen(request) as resp: - data = resp.read() - headers = resp.getheaders() - except urllib.error.HTTPError as exc: + r.raise_for_status() + except requests.exceptions.RequestException as exc: sys.stderr.write('Request failed\n\n') sys.stderr.write('Response:\n') - sys.stderr.write(exc.read().decode('utf-8')) + sys.stderr.write(r.text) sys.exit(1) - return data, headers + return r def _put(self, url, data): - request = urllib.request.Request( - url=url, - data=json.dumps(data).encode('utf-8'), - method='PATCH', - headers=self._generate_headers( + r = requests.patch( + url, + data=data, + headers=self.generate_headers( { 'Content-Type': 'application/json', }, ), ) try: - with urllib.request.urlopen(request) as resp: - data = resp.read() - headers = resp.getheaders() - except urllib.error.HTTPError as exc: + r.raise_for_status() + except requests.exceptions.RequestException as exc: sys.stderr.write('Request failed\n\n') sys.stderr.write('Response:\n') - sys.stderr.write(exc.read().decode('utf-8')) + sys.stderr.write(r.text) sys.exit(1) - return data, headers + return r def _create( self, @@ -548,8 +538,8 @@ def _create( url = f'{self._server}/{resource_type}/' if resource_id: url = f'{url}{resource_id}/{subresource_type}/' - data, _ = self._post(url, data) - return json.loads(data) + r = self._post(url, data) + return r.json() def _update( self, @@ -563,8 +553,8 @@ def _update( url = f'{self._server}/{resource_type}/{resource_id}/' if subresource_id: url = f'{url}{subresource_type}/{subresource_id}/' - data, _ = self._put(url, data) - return json.loads(data) + r = self._put(url, data) + return r.json() def _detail( self, @@ -578,10 +568,10 @@ def _detail( url = f'{self._server}/{resource_type}/{resource_id}/' if subresource_type: url = f'{url}{subresource_type}/{subresource_id}/' - if params: - url = f'{url}?{urllib.parse.urlencode(params)}' - data, _ = self._get(url) - return json.loads(data) + r = self._get(url, params) + if r.status_code == http.HTTPStatus.NOT_FOUND: + return {} + return r.json() def _list( self, @@ -594,10 +584,10 @@ def _list( url = f'{self._server}/{resource_type}/' if resource_id: url = f'{url}{resource_id}/{subresource_type}/' - if params: - url = f'{url}?{urllib.parse.urlencode(params)}' - data, _ = self._get(url) - return json.loads(data) + r = self._get(url, params) + if r.status_code == http.HTTPStatus.NOT_FOUND: + return [] + return r.json() # project @@ -764,19 +754,20 @@ def patch_get_by_project_hash(self, project, hash): def patch_get_mbox(self, patch_id): patch = self._detail('patches', patch_id) - data, headers = self._get(patch['mbox']) - header = '' - for name, value in headers: - if name.lower() == 'content-disposition': - header = value - break + r = self._get(patch['mbox']) + if r.status_code == http.HTTPStatus.NOT_FOUND: + sys.stderr.write('Request failed\n\n') + sys.stderr.write('Response:\n') + sys.stderr.write(r.text) + sys.exit(1) + + header = r.headers['content-disposition'] header_re = re.search('filename=(.+)', header) if not header_re: raise Exception('filename header was missing from the response') - filename = header_re.group(1)[:-6] # remove the extension - return data.decode('utf-8'), filename + return r.text, filename def patch_get_diff(self, patch_id): patch = self._detail('patches', patch_id) diff --git a/requirements.txt b/requirements.txt index 19414e7..f434190 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ importlib_metadata;python_version<'3.8' +requests