Skip to content

Commit b63ff56

Browse files
Refactor transport class
1 parent 2c9a5ec commit b63ff56

6 files changed

Lines changed: 61 additions & 54 deletions

File tree

coreapi/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ def negotiate_decoder(content_type=None):
4141
def get(url):
4242
session = _default_session
4343
transport = session.determine_transport(url)
44-
return transport.transition(url, 'get')
44+
link = Link(url, action='get')
45+
return transport.transition(link, session=session)
4546

4647

4748
def action(document, keys, **params):

coreapi/sessions.py

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from coreapi.compat import string_types, urlparse
2-
from coreapi.document import Error
3-
from coreapi.exceptions import ErrorMessage, NotAcceptable, ParseError, TransportError
2+
from coreapi.exceptions import NotAcceptable, ParseError, TransportError
43
from coreapi.validation import validate_keys_to_link, validate_parameters
54
import itypes
65

@@ -117,20 +116,4 @@ def action(self, document, keys, **params):
117116

118117
# Perform the action, and return a new document.
119118
transport = self.determine_transport(link.url)
120-
new_document = transport.transition(link.url, link.action, params)
121-
122-
# If we got an error response back, raise an exception.
123-
if isinstance(new_document, Error):
124-
raise ErrorMessage(new_document.messages)
125-
126-
# Return the new document or other media.
127-
transition = link.transition
128-
if not transition and link.action.lower() in ('put', 'patch', 'delete'):
129-
transition = 'inline'
130-
131-
if transition == 'inline':
132-
keys_to_link_parent = link_ancestors[-1].keys
133-
if new_document is None:
134-
return document.delete_in(keys_to_link_parent)
135-
return document.set_in(keys_to_link_parent, new_document)
136-
return new_document
119+
return transport.transition(link, params, session=self, link_ancestors=link_ancestors)

coreapi/transport.py

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# coding: utf-8
22
from __future__ import unicode_literals
3+
from coreapi import Error, ErrorMessage
34
import requests
45
import itypes
56
import json
@@ -8,17 +9,30 @@
89
class BaseTransport(itypes.Object):
910
schemes = None
1011

11-
def transition(self, url, action=None, parameters=None):
12+
def transition(self, link, params=None, session=None, link_ancestors=None):
1213
raise NotImplementedError() # pragma: nocover
1314

1415

1516
class HTTPTransport(BaseTransport):
1617
schemes = ['http', 'https']
1718

18-
def transition(self, url, action=None, params=None):
19-
from coreapi import get_default_session
20-
session = get_default_session()
19+
def transition(self, link, params=None, session=None, link_ancestors=None):
20+
if session is None:
21+
from coreapi import get_default_session
22+
session = get_default_session()
2123

24+
response = self.make_http_request(session, link.url, link.action, params)
25+
document = self.load_document(session, response)
26+
27+
if isinstance(document, Error):
28+
raise ErrorMessage(document.messages)
29+
30+
if link_ancestors:
31+
document = self.handle_inline_replacements(document, link, link_ancestors)
32+
33+
return document
34+
35+
def make_http_request(self, session, url, action=None, params=None):
2236
method = 'GET' if (action is None) else action.upper()
2337
accept = session.get_accept_header()
2438

@@ -44,10 +58,24 @@ def transition(self, url, action=None, params=None):
4458
}
4559
}
4660

47-
response = requests.request(method, url, **opts)
61+
return requests.request(method, url, **opts)
62+
63+
def load_document(self, session, response):
4864
if not response.content:
4965
return None
50-
5166
content_type = response.headers.get('content-type')
5267
codec = session.negotiate_decoder(content_type)
53-
return codec.load(response.content, base_url=url)
68+
return codec.load(response.content, base_url=response.url)
69+
70+
def handle_inline_replacements(self, document, link, link_ancestors):
71+
transition_type = link.transition
72+
if not transition_type and link.action.lower() in ('put', 'patch', 'delete'):
73+
transition_type = 'inline'
74+
75+
if transition_type == 'inline':
76+
root = link_ancestors[0].document
77+
keys_to_link_parent = link_ancestors[-1].keys
78+
if document is None:
79+
return root.delete_in(keys_to_link_parent)
80+
return root.set_in(keys_to_link_parent, document)
81+
return document

tests/test_integration.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class MockResponse(object):
1919
def __init__(self, content):
2020
self.content = content
2121
self.headers = {}
22+
self.url = 'http://example.org'
2223

2324

2425
# Basic integration tests.

tests/test_transitions.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
# coding: utf-8
2-
from coreapi import action, Document, Link, BaseTransport, Session
2+
from coreapi import action, Document, Link, HTTPTransport, Session
33
import datetime
44
import pytest
55

66

7-
class MockTransport(BaseTransport):
7+
class MockTransport(HTTPTransport):
88
schemes = ['mock']
99

10-
def transition(self, url, action=None, params=None):
11-
if action == 'get':
12-
return Document(title='new', content={'new': 123})
13-
elif action in ('put', 'post'):
14-
return Document(title='new', content={'new': 123, 'param': params.get('param')})
15-
return None
10+
def transition(self, link, params=None, session=None, link_ancestors=None):
11+
if link.action == 'get':
12+
document = Document(title='new', content={'new': 123})
13+
elif link.action in ('put', 'post'):
14+
document = Document(title='new', content={'new': 123, 'param': params.get('param')})
15+
else:
16+
document = None
17+
18+
return self.handle_inline_replacements(document, link, link_ancestors)
1619

1720

1821
now = datetime.datetime.now()

tests/test_transport.py

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# coding: utf-8
2-
from coreapi import get_default_session
2+
from coreapi import get_default_session, Link
33
from coreapi.exceptions import TransportError
44
from coreapi.transport import HTTPTransport
55
import pytest
@@ -15,6 +15,7 @@ class MockResponse(object):
1515
def __init__(self, content):
1616
self.content = content
1717
self.headers = {}
18+
self.url = 'http://example.org'
1819

1920

2021
# Test transport errors.
@@ -45,10 +46,8 @@ def mockreturn(method, url, headers):
4546

4647
monkeypatch.setattr(requests, 'request', mockreturn)
4748

48-
doc = http.transition(
49-
url='http://example.org',
50-
action='get'
51-
)
49+
link = Link(url='http://example.org', action='get')
50+
doc = http.transition(link)
5251
assert doc == {'example': 123}
5352

5453

@@ -61,11 +60,8 @@ def mockreturn(method, url, params, headers):
6160

6261
monkeypatch.setattr(requests, 'request', mockreturn)
6362

64-
doc = http.transition(
65-
url='http://example.org',
66-
action='get',
67-
params={'example': 'abc'}
68-
)
63+
link = Link(url='http://example.org', action='get')
64+
doc = http.transition(link, params={'example': 'abc'})
6965
assert doc == {'example': 'abc'}
7066

7167

@@ -76,11 +72,8 @@ def mockreturn(method, url, data, headers):
7672

7773
monkeypatch.setattr(requests, 'request', mockreturn)
7874

79-
doc = http.transition(
80-
url='http://example.org',
81-
action='post',
82-
params={'example': 'abc'}
83-
)
75+
link = Link(url='http://example.org', action='post')
76+
doc = http.transition(link, params={'example': 'abc'})
8477
assert doc == {'data': {'example': 'abc'}}
8578

8679

@@ -90,8 +83,6 @@ def mockreturn(method, url, headers):
9083

9184
monkeypatch.setattr(requests, 'request', mockreturn)
9285

93-
doc = http.transition(
94-
url='http://example.org',
95-
action='delete'
96-
)
86+
link = Link(url='http://example.org', action='delete')
87+
doc = http.transition(link)
9788
assert doc is None

0 commit comments

Comments
 (0)