Use http methods instead of requests directly - toot - Unnamed repository; edit… | |
Log | |
Files | |
Refs | |
LICENSE | |
--- | |
commit 92d4dc745ad51a9cdd8eb70e3e508f2d1ab57afc | |
parent 20eaf86b56fc3c28b66c7043cb60b238e38f8253 | |
Author: Ivan Habunek <[email protected]> | |
Date: Sat, 30 Dec 2017 16:30:35 +0100 | |
Use http methods instead of requests directly | |
Diffstat: | |
tests/test_api.py | 95 +++++++++++++++---------------- | |
tests/test_auth.py | 1 + | |
tests/test_console.py | 163 +++++++++++++++---------------- | |
tests/utils.py | 28 ++++++++++++++++++++++++++++ | |
toot/api.py | 41 ++++++++++++------------------- | |
toot/auth.py | 19 ++++++++++++------- | |
toot/commands.py | 15 ++++++++++++--- | |
toot/http.py | 65 +++++++++++++++++++------------- | |
toot/utils.py | 7 +++++++ | |
9 files changed, 238 insertions(+), 196 deletions(-) | |
--- | |
diff --git a/tests/test_api.py b/tests/test_api.py | |
@@ -2,79 +2,76 @@ | |
import pytest | |
import requests | |
+from requests import Request | |
+ | |
from toot import App, CLIENT_NAME, CLIENT_WEBSITE | |
from toot.api import create_app, login, SCOPES, AuthenticationError | |
-from tests.utils import MockResponse | |
+from tests.utils import MockResponse, Expectations | |
def test_create_app(monkeypatch): | |
- response = { | |
- 'client_id': 'foo', | |
- 'client_secret': 'bar', | |
- } | |
+ request = Request('POST', 'http://bigfish.software/api/v1/apps', | |
+ data={'website': CLIENT_WEBSITE, | |
+ 'client_name': CLIENT_NAME, | |
+ 'scopes': SCOPES, | |
+ 'redirect_uris': 'urn:ietf:wg:oauth:2.0:oob'}) | |
- def mock_post(url, data): | |
- assert url == 'https://bigfish.software/api/v1/apps' | |
- assert data == { | |
- 'website': CLIENT_WEBSITE, | |
- 'client_name': CLIENT_NAME, | |
- 'scopes': SCOPES, | |
- 'redirect_uris': 'urn:ietf:wg:oauth:2.0:oob' | |
- } | |
- return MockResponse(response) | |
+ response = MockResponse({'client_id': 'foo', | |
+ 'client_secret': 'bar'}) | |
- monkeypatch.setattr(requests, 'post', mock_post) | |
+ e = Expectations() | |
+ e.add(request, response) | |
+ e.patch(monkeypatch) | |
- assert create_app('bigfish.software') == response | |
+ create_app('bigfish.software') | |
def test_login(monkeypatch): | |
app = App('bigfish.software', 'https://bigfish.software', 'foo', 'bar') | |
- response = { | |
+ data = { | |
+ 'grant_type': 'password', | |
+ 'client_id': app.client_id, | |
+ 'client_secret': app.client_secret, | |
+ 'username': 'user', | |
+ 'password': 'pass', | |
+ 'scope': SCOPES, | |
+ } | |
+ | |
+ request = Request('POST', 'https://bigfish.software/oauth/token', data=dat… | |
+ | |
+ response = MockResponse({ | |
'token_type': 'bearer', | |
'scope': 'read write follow', | |
'access_token': 'xxx', | |
'created_at': 1492523699 | |
- } | |
+ }) | |
- def mock_post(url, data, allow_redirects): | |
- assert not allow_redirects | |
- assert url == 'https://bigfish.software/oauth/token' | |
- assert data == { | |
- 'grant_type': 'password', | |
- 'client_id': app.client_id, | |
- 'client_secret': app.client_secret, | |
- 'username': 'user', | |
- 'password': 'pass', | |
- 'scope': SCOPES, | |
- } | |
+ e = Expectations() | |
+ e.add(request, response) | |
+ e.patch(monkeypatch) | |
- return MockResponse(response) | |
- | |
- monkeypatch.setattr(requests, 'post', mock_post) | |
- | |
- assert login(app, 'user', 'pass') == response | |
+ login(app, 'user', 'pass') | |
def test_login_failed(monkeypatch): | |
app = App('bigfish.software', 'https://bigfish.software', 'foo', 'bar') | |
- def mock_post(url, data, allow_redirects): | |
- assert not allow_redirects | |
- assert url == 'https://bigfish.software/oauth/token' | |
- assert data == { | |
- 'grant_type': 'password', | |
- 'client_id': app.client_id, | |
- 'client_secret': app.client_secret, | |
- 'username': 'user', | |
- 'password': 'pass', | |
- 'scope': SCOPES, | |
- } | |
- | |
- return MockResponse(is_redirect=True) | |
- | |
- monkeypatch.setattr(requests, 'post', mock_post) | |
+ data = { | |
+ 'grant_type': 'password', | |
+ 'client_id': app.client_id, | |
+ 'client_secret': app.client_secret, | |
+ 'username': 'user', | |
+ 'password': 'pass', | |
+ 'scope': SCOPES, | |
+ } | |
+ | |
+ request = Request('POST', 'https://bigfish.software/oauth/token', data=dat… | |
+ response = MockResponse(is_redirect=True) | |
+ | |
+ e = Expectations() | |
+ e.add(request, response) | |
+ e.patch(monkeypatch) | |
with pytest.raises(AuthenticationError): | |
login(app, 'user', 'pass') | |
diff --git a/tests/test_auth.py b/tests/test_auth.py | |
@@ -15,6 +15,7 @@ def test_register_app(monkeypatch): | |
assert app.client_secret == "cs" | |
monkeypatch.setattr(api, 'create_app', retval(app_data)) | |
+ monkeypatch.setattr(api, 'get_instance', retval({"title": "foo", "version"… | |
monkeypatch.setattr(config, 'save_app', assert_app) | |
app = auth.register_app("foo.bar") | |
diff --git a/tests/test_console.py b/tests/test_console.py | |
@@ -3,10 +3,12 @@ import pytest | |
import requests | |
import re | |
+from requests import Request | |
+ | |
from toot import console, User, App | |
from toot.exceptions import ConsoleError | |
-from tests.utils import MockResponse | |
+from tests.utils import MockResponse, Expectations | |
app = App('habunek.com', 'https://habunek.com', 'foo', 'bar') | |
user = User('habunek.com', '[email protected]', 'xxx') | |
@@ -34,7 +36,7 @@ def test_post_defaults(monkeypatch, capsys): | |
'media_ids[]': None, | |
} | |
- def mock_send(*args): | |
+ def mock_send(*args, **kwargs): | |
return MockResponse({ | |
'url': 'http://ivan.habunek.com/' | |
}) | |
@@ -59,7 +61,7 @@ def test_post_with_options(monkeypatch, capsys): | |
'media_ids[]': None, | |
} | |
- def mock_send(*args): | |
+ def mock_send(*args, **kwargs): | |
return MockResponse({ | |
'url': 'http://ivan.habunek.com/' | |
}) | |
@@ -96,11 +98,12 @@ def test_post_invalid_media(monkeypatch, capsys): | |
def test_timeline(monkeypatch, capsys): | |
- def mock_get(url, params, headers=None): | |
- assert url == 'https://habunek.com/api/v1/timelines/home' | |
- assert headers == {'Authorization': 'Bearer xxx'} | |
- assert params is None | |
+ def mock_prepare(request): | |
+ assert request.url == 'https://habunek.com/api/v1/timelines/home' | |
+ assert request.headers == {'Authorization': 'Bearer xxx'} | |
+ assert request.params == {} | |
+ def mock_send(*args, **kwargs): | |
return MockResponse([{ | |
'account': { | |
'display_name': 'Frank Zappa', | |
@@ -111,7 +114,8 @@ def test_timeline(monkeypatch, capsys): | |
'reblog': None, | |
}]) | |
- monkeypatch.setattr(requests, 'get', mock_get) | |
+ monkeypatch.setattr(requests.Request, 'prepare', mock_prepare) | |
+ monkeypatch.setattr(requests.Session, 'send', mock_send) | |
console.run_command(app, user, 'timeline', []) | |
@@ -127,7 +131,7 @@ def test_upload(monkeypatch, capsys): | |
assert request.headers == {'Authorization': 'Bearer xxx'} | |
assert request.files.get('file') is not None | |
- def mock_send(*args): | |
+ def mock_send(*args, **kwargs): | |
return MockResponse({ | |
'id': 123, | |
'url': 'https://bigfish.software/123/456', | |
@@ -147,14 +151,15 @@ def test_upload(monkeypatch, capsys): | |
def test_search(monkeypatch, capsys): | |
- def mock_get(url, params, headers=None): | |
- assert url == 'https://habunek.com/api/v1/search' | |
- assert headers == {'Authorization': 'Bearer xxx'} | |
- assert params == { | |
+ def mock_prepare(request): | |
+ assert request.url == 'https://habunek.com/api/v1/search' | |
+ assert request.headers == {'Authorization': 'Bearer xxx'} | |
+ assert request.params == { | |
'q': 'freddy', | |
'resolve': False, | |
} | |
+ def mock_send(*args, **kwargs): | |
return MockResponse({ | |
'hashtags': ['foo', 'bar', 'baz'], | |
'accounts': [{ | |
@@ -167,7 +172,8 @@ def test_search(monkeypatch, capsys): | |
'statuses': [], | |
}) | |
- monkeypatch.setattr(requests, 'get', mock_get) | |
+ monkeypatch.setattr(requests.Request, 'prepare', mock_prepare) | |
+ monkeypatch.setattr(requests.Session, 'send', mock_send) | |
console.run_command(app, user, 'search', ['freddy']) | |
@@ -179,25 +185,20 @@ def test_search(monkeypatch, capsys): | |
def test_follow(monkeypatch, capsys): | |
- def mock_get(url, params, headers): | |
- assert url == 'https://habunek.com/api/v1/accounts/search' | |
- assert params == {'q': 'blixa'} | |
- assert headers == {'Authorization': 'Bearer xxx'} | |
- | |
- return MockResponse([ | |
- {'id': 123, 'acct': '[email protected]'}, | |
- {'id': 321, 'acct': 'blixa'}, | |
- ]) | |
- | |
- def mock_prepare(request): | |
- assert request.url == 'https://habunek.com/api/v1/accounts/321/follow' | |
+ req1 = Request('GET', 'https://habunek.com/api/v1/accounts/search', | |
+ params={'q': 'blixa'}, | |
+ headers={'Authorization': 'Bearer xxx'}) | |
+ res1 = MockResponse([ | |
+ {'id': 123, 'acct': '[email protected]'}, | |
+ {'id': 321, 'acct': 'blixa'}, | |
+ ]) | |
- def mock_send(*args, **kwargs): | |
- return MockResponse() | |
+ req2 = Request('POST', 'https://habunek.com/api/v1/accounts/321/follow', | |
+ headers={'Authorization': 'Bearer xxx'}) | |
+ res2 = MockResponse() | |
- monkeypatch.setattr(requests.Request, 'prepare', mock_prepare) | |
- monkeypatch.setattr(requests.Session, 'send', mock_send) | |
- monkeypatch.setattr(requests, 'get', mock_get) | |
+ expectations = Expectations([req1, req2], [res1, res2]) | |
+ expectations.patch(monkeypatch) | |
console.run_command(app, user, 'follow', ['blixa']) | |
@@ -206,14 +207,12 @@ def test_follow(monkeypatch, capsys): | |
def test_follow_not_found(monkeypatch, capsys): | |
- def mock_get(url, params, headers): | |
- assert url == 'https://habunek.com/api/v1/accounts/search' | |
- assert params == {'q': 'blixa'} | |
- assert headers == {'Authorization': 'Bearer xxx'} | |
+ req = Request('GET', 'https://habunek.com/api/v1/accounts/search', | |
+ params={'q': 'blixa'}, headers={'Authorization': 'Bearer xxx… | |
+ res = MockResponse() | |
- return MockResponse([]) | |
- | |
- monkeypatch.setattr(requests, 'get', mock_get) | |
+ expectations = Expectations([req], [res]) | |
+ expectations.patch(monkeypatch) | |
with pytest.raises(ConsoleError) as ex: | |
console.run_command(app, user, 'follow', ['blixa']) | |
@@ -221,25 +220,20 @@ def test_follow_not_found(monkeypatch, capsys): | |
def test_unfollow(monkeypatch, capsys): | |
- def mock_get(url, params, headers): | |
- assert url == 'https://habunek.com/api/v1/accounts/search' | |
- assert params == {'q': 'blixa'} | |
- assert headers == {'Authorization': 'Bearer xxx'} | |
- | |
- return MockResponse([ | |
- {'id': 123, 'acct': '[email protected]'}, | |
- {'id': 321, 'acct': 'blixa'}, | |
- ]) | |
- | |
- def mock_prepare(request): | |
- assert request.url == 'https://habunek.com/api/v1/accounts/321/unfollo… | |
+ req1 = Request('GET', 'https://habunek.com/api/v1/accounts/search', | |
+ params={'q': 'blixa'}, | |
+ headers={'Authorization': 'Bearer xxx'}) | |
+ res1 = MockResponse([ | |
+ {'id': 123, 'acct': '[email protected]'}, | |
+ {'id': 321, 'acct': 'blixa'}, | |
+ ]) | |
- def mock_send(*args, **kwargs): | |
- return MockResponse() | |
+ req2 = Request('POST', 'https://habunek.com/api/v1/accounts/321/unfollow', | |
+ headers={'Authorization': 'Bearer xxx'}) | |
+ res2 = MockResponse() | |
- monkeypatch.setattr(requests.Request, 'prepare', mock_prepare) | |
- monkeypatch.setattr(requests.Session, 'send', mock_send) | |
- monkeypatch.setattr(requests, 'get', mock_get) | |
+ expectations = Expectations([req1, req2], [res1, res2]) | |
+ expectations.patch(monkeypatch) | |
console.run_command(app, user, 'unfollow', ['blixa']) | |
@@ -248,14 +242,12 @@ def test_unfollow(monkeypatch, capsys): | |
def test_unfollow_not_found(monkeypatch, capsys): | |
- def mock_get(url, params, headers): | |
- assert url == 'https://habunek.com/api/v1/accounts/search' | |
- assert params == {'q': 'blixa'} | |
- assert headers == {'Authorization': 'Bearer xxx'} | |
- | |
- return MockResponse([]) | |
+ req = Request('GET', 'https://habunek.com/api/v1/accounts/search', | |
+ params={'q': 'blixa'}, headers={'Authorization': 'Bearer xxx… | |
+ res = MockResponse([]) | |
- monkeypatch.setattr(requests, 'get', mock_get) | |
+ expectations = Expectations([req], [res]) | |
+ expectations.patch(monkeypatch) | |
with pytest.raises(ConsoleError) as ex: | |
console.run_command(app, user, 'unfollow', ['blixa']) | |
@@ -263,30 +255,29 @@ def test_unfollow_not_found(monkeypatch, capsys): | |
def test_whoami(monkeypatch, capsys): | |
- def mock_get(url, params, headers=None): | |
- assert url == 'https://habunek.com/api/v1/accounts/verify_credentials' | |
- assert headers == {'Authorization': 'Bearer xxx'} | |
- assert params is None | |
- | |
- return MockResponse({ | |
- 'acct': 'ihabunek', | |
- 'avatar': 'https://files.mastodon.social/accounts/avatars/000/046/… | |
- 'avatar_static': 'https://files.mastodon.social/accounts/avatars/0… | |
- 'created_at': '2017-04-04T13:23:09.777Z', | |
- 'display_name': 'Ivan Habunek', | |
- 'followers_count': 5, | |
- 'following_count': 9, | |
- 'header': '/headers/original/missing.png', | |
- 'header_static': '/headers/original/missing.png', | |
- 'id': 46103, | |
- 'locked': False, | |
- 'note': 'A developer.', | |
- 'statuses_count': 19, | |
- 'url': 'https://mastodon.social/@ihabunek', | |
- 'username': 'ihabunek' | |
- }) | |
- | |
- monkeypatch.setattr(requests, 'get', mock_get) | |
+ req = Request('GET', 'https://habunek.com/api/v1/accounts/verify_credentia… | |
+ headers={'Authorization': 'Bearer xxx'}) | |
+ | |
+ res = MockResponse({ | |
+ 'acct': 'ihabunek', | |
+ 'avatar': 'https://files.mastodon.social/accounts/avatars/000/046/103/… | |
+ 'avatar_static': 'https://files.mastodon.social/accounts/avatars/000/0… | |
+ 'created_at': '2017-04-04T13:23:09.777Z', | |
+ 'display_name': 'Ivan Habunek', | |
+ 'followers_count': 5, | |
+ 'following_count': 9, | |
+ 'header': '/headers/original/missing.png', | |
+ 'header_static': '/headers/original/missing.png', | |
+ 'id': 46103, | |
+ 'locked': False, | |
+ 'note': 'A developer.', | |
+ 'statuses_count': 19, | |
+ 'url': 'https://mastodon.social/@ihabunek', | |
+ 'username': 'ihabunek' | |
+ }) | |
+ | |
+ expectations = Expectations([req], [res]) | |
+ expectations.patch(monkeypatch) | |
console.run_command(app, user, 'whoami', []) | |
diff --git a/tests/utils.py b/tests/utils.py | |
@@ -1,3 +1,31 @@ | |
+import requests | |
+ | |
+ | |
+class Expectations(): | |
+ """Helper for mocking http requests""" | |
+ def __init__(self, requests=[], responses=[]): | |
+ self.requests = requests | |
+ self.responses = responses | |
+ | |
+ def mock_prepare(self, request): | |
+ expected = self.requests.pop(0) | |
+ assert request.method == expected.method | |
+ assert request.url == expected.url | |
+ assert request.data == expected.data | |
+ assert request.headers == expected.headers | |
+ assert request.params == expected.params | |
+ | |
+ def mock_send(self, *args, **kwargs): | |
+ return self.responses.pop(0) | |
+ | |
+ def add(self, req, res): | |
+ self.requests.append(req) | |
+ self.responses.append(res) | |
+ | |
+ def patch(self, monkeypatch): | |
+ monkeypatch.setattr(requests.Session, 'prepare_request', self.mock_pre… | |
+ monkeypatch.setattr(requests.Session, 'send', self.mock_send) | |
+ | |
class MockResponse: | |
def __init__(self, response_data={}, ok=True, is_redirect=False): | |
diff --git a/toot/api.py b/toot/api.py | |
@@ -1,13 +1,11 @@ | |
# -*- coding: utf-8 -*- | |
import re | |
-import requests | |
from urllib.parse import urlparse, urlencode | |
from toot import http, CLIENT_NAME, CLIENT_WEBSITE | |
-from toot.exceptions import ApiError, AuthenticationError, NotFoundError | |
-from toot.utils import domain_exists | |
+from toot.exceptions import AuthenticationError | |
SCOPES = 'read write follow' | |
@@ -18,31 +16,32 @@ def _account_action(app, user, account, action): | |
return http.post(app, user, url).json() | |
-def create_app(instance): | |
- base_url = 'https://' + instance | |
- url = base_url + '/api/v1/apps' | |
+def create_app(domain): | |
+ url = 'http://{}/api/v1/apps'.format(domain) | |
- response = requests.post(url, { | |
+ data = { | |
'client_name': CLIENT_NAME, | |
'redirect_uris': 'urn:ietf:wg:oauth:2.0:oob', | |
'scopes': SCOPES, | |
'website': CLIENT_WEBSITE, | |
- }) | |
+ } | |
- return http.process_response(response).json() | |
+ return http.anon_post(url, data).json() | |
def login(app, username, password): | |
url = app.base_url + '/oauth/token' | |
- response = requests.post(url, { | |
+ data = { | |
'grant_type': 'password', | |
'client_id': app.client_id, | |
'client_secret': app.client_secret, | |
'username': username, | |
'password': password, | |
'scope': SCOPES, | |
- }, allow_redirects=False) | |
+ } | |
+ | |
+ response = http.anon_post(url, data, allow_redirects=False) | |
# If auth fails, it redirects to the login page | |
if response.is_redirect: | |
@@ -64,13 +63,15 @@ def get_browser_login_url(app): | |
def request_access_token(app, authorization_code): | |
url = app.base_url + '/oauth/token' | |
- response = requests.post(url, { | |
+ data = { | |
'grant_type': 'authorization_code', | |
'client_id': app.client_id, | |
'client_secret': app.client_secret, | |
'code': authorization_code, | |
'redirect_uri': 'urn:ietf:wg:oauth:2.0:oob', | |
- }, allow_redirects=False) | |
+ } | |
+ | |
+ response = http.anon_post(url, data, allow_redirects=False) | |
return http.process_response(response).json() | |
@@ -155,16 +156,6 @@ def get_notifications(app, user): | |
return http.get(app, user, '/api/v1/notifications').json() | |
-def get_instance(app, user, domain): | |
- if not domain_exists(domain): | |
- raise ApiError("Domain {} not found".format(domain)) | |
- | |
+def get_instance(domain): | |
url = "http://{}/api/v1/instance".format(domain) | |
- | |
- try: | |
- return http.unauthorized_get(url).json() | |
- except NotFoundError: | |
- raise ApiError( | |
- "Instance info not found at {}.\n" | |
- "The given domain probably does not host a Mastodon instance.".for… | |
- ) | |
+ return http.anon_get(url).json() | |
diff --git a/toot/auth.py b/toot/auth.py | |
@@ -10,17 +10,22 @@ from toot.exceptions import ApiError, ConsoleError | |
from toot.output import print_out | |
-def register_app(instance): | |
- print_out("Registering application with <green>{}</green>".format(instance… | |
+def register_app(domain): | |
+ print_out("Looking up instance info...") | |
+ instance = api.get_instance(domain) | |
+ | |
+ print_out("Found instance <blue>{}</blue> running Mastodon version <yellow… | |
+ instance['title'], instance['version'])) | |
try: | |
- response = api.create_app(instance) | |
- except Exception: | |
- raise ConsoleError("Registration failed. Did you enter a valid instanc… | |
+ print_out("Registering application...") | |
+ response = api.create_app(domain) | |
+ except ApiError: | |
+ raise ConsoleError("Registration failed.") | |
- base_url = 'https://' + instance | |
+ base_url = 'https://' + domain | |
- app = App(instance, base_url, response['client_id'], response['client_secr… | |
+ app = App(domain, base_url, response['client_id'], response['client_secret… | |
path = config.save_app(app) | |
print_out("Application tokens saved to: <green>{}</green>\n".format(path)) | |
diff --git a/toot/commands.py b/toot/commands.py | |
@@ -8,8 +8,9 @@ from textwrap import TextWrapper | |
from toot import api, config | |
from toot.auth import login_interactive, login_browser_interactive, create_app… | |
-from toot.exceptions import ConsoleError | |
+from toot.exceptions import ConsoleError, NotFoundError | |
from toot.output import print_out, print_instance, print_account, print_search… | |
+from toot.utils import assert_domain_exists | |
def _print_timeline(item): | |
@@ -207,5 +208,13 @@ def instance(app, user, args): | |
if not name: | |
raise ConsoleError("Please specify instance name.") | |
- instance = api.get_instance(app, user, name) | |
- print_instance(instance) | |
+ assert_domain_exists(name) | |
+ | |
+ try: | |
+ instance = api.get_instance(name) | |
+ print_instance(instance) | |
+ except NotFoundError: | |
+ raise ConsoleError( | |
+ "Instance not found at {}.\n" | |
+ "The given domain probably does not host a Mastodon instance.".for… | |
+ ) | |
diff --git a/toot/http.py b/toot/http.py | |
@@ -1,24 +1,37 @@ | |
-import requests | |
- | |
-from toot.logging import log_request, log_response | |
from requests import Request, Session | |
from toot.exceptions import NotFoundError, ApiError | |
+from toot.logging import log_request, log_response | |
-def process_response(response): | |
+def send_request(request, allow_redirects=True): | |
+ log_request(request) | |
+ | |
+ with Session() as session: | |
+ prepared = session.prepare_request(request) | |
+ response = session.send(prepared, allow_redirects=allow_redirects) | |
+ | |
log_response(response) | |
- if not response.ok: | |
- error = "Unknown error" | |
+ return response | |
+ | |
- try: | |
- data = response.json() | |
- if "error_description" in data: | |
- error = data['error_description'] | |
- elif "error" in data: | |
- error = data['error'] | |
- except Exception: | |
- pass | |
+def _get_error_message(response): | |
+ """Attempt to extract an error message from response body""" | |
+ try: | |
+ data = response.json() | |
+ if "error_description" in data: | |
+ return data['error_description'] | |
+ if "error" in data: | |
+ return data['error'] | |
+ except Exception: | |
+ pass | |
+ | |
+ return "Unknown error" | |
+ | |
+ | |
+def process_response(response): | |
+ if not response.ok: | |
+ error = _get_error_message(response) | |
if response.status_code == 404: | |
raise NotFoundError(error) | |
@@ -32,31 +45,31 @@ def get(app, user, url, params=None): | |
url = app.base_url + url | |
headers = {"Authorization": "Bearer " + user.access_token} | |
- log_request(Request('GET', url, headers, params=params)) | |
- | |
- response = requests.get(url, params, headers=headers) | |
+ request = Request('GET', url, headers, params=params) | |
+ response = send_request(request) | |
return process_response(response) | |
-def unauthorized_get(url, params=None): | |
- log_request(Request('GET', url, None, params=params)) | |
- | |
- response = requests.get(url, params) | |
+def anon_get(url, params=None): | |
+ request = Request('GET', url, None, params=params) | |
+ response = send_request(request) | |
return process_response(response) | |
-def post(app, user, url, data=None, files=None): | |
+def post(app, user, url, data=None, files=None, allow_redirects=True): | |
url = app.base_url + url | |
headers = {"Authorization": "Bearer " + user.access_token} | |
- session = Session() | |
request = Request('POST', url, headers, files, data) | |
- prepared_request = request.prepare() | |
+ response = send_request(request, allow_redirects) | |
+ | |
+ return process_response(response) | |
- log_request(request) | |
- response = session.send(prepared_request) | |
+def anon_post(url, data=None, files=None, allow_redirects=True): | |
+ request = Request('POST', url, {}, files, data) | |
+ response = send_request(request, allow_redirects) | |
return process_response(response) | |
diff --git a/toot/utils.py b/toot/utils.py | |
@@ -5,6 +5,8 @@ import socket | |
from bs4 import BeautifulSoup | |
+from toot.exceptions import ConsoleError | |
+ | |
def get_text(html): | |
"""Converts html to text, strips all tags.""" | |
@@ -50,3 +52,8 @@ def domain_exists(name): | |
return True | |
except OSError: | |
return False | |
+ | |
+ | |
+def assert_domain_exists(domain): | |
+ if not domain_exists(domain): | |
+ raise ConsoleError("Domain {} not found".format(domain)) |