1
- from coreapi .codecs import CoreJSONCodec , HALCodec , HTMLCodec , PlainTextCodec
2
- from coreapi .compat import string_types , urlparse
1
+ from coreapi .codecs import default_decoders
2
+ from coreapi .compat import string_types
3
3
from coreapi .document import Document , Link
4
- from coreapi .exceptions import LinkLookupError , NotAcceptable , UnsupportedContentType , TransportError
5
- from coreapi .transports import HTTPTransport
4
+ from coreapi .exceptions import LinkLookupError
5
+ from coreapi .transports import default_transports , determine_transport
6
6
import collections
7
7
import itypes
8
8
9
9
10
10
LinkAncestor = collections .namedtuple ('LinkAncestor' , ['document' , 'keys' ])
11
11
12
12
13
- def lookup_link (document , keys ):
13
+ def _lookup_link (document , keys ):
14
14
"""
15
15
Validates that keys looking up a link are correct.
16
16
@@ -53,30 +53,13 @@ def lookup_link(document, keys):
53
53
54
54
55
55
class Client (itypes .Object ):
56
- def __init__ (self , codecs = None , transports = None ):
57
- if codecs is None :
58
- codecs = [ CoreJSONCodec (), HALCodec (), HTMLCodec (), PlainTextCodec ()]
56
+ def __init__ (self , decoders = None , transports = None ):
57
+ if decoders is None :
58
+ decoders = default_decoders
59
59
if transports is None :
60
- transports = [HTTPTransport ()]
61
-
62
- self ._codecs = itypes .List (codecs )
60
+ transports = default_transports
61
+ self ._decoders = itypes .List (decoders )
63
62
self ._transports = itypes .List (transports )
64
- self ._decoders = [
65
- codec for codec in codecs
66
- if not getattr (codec .load , 'not_implemented' , False )
67
- ]
68
- self ._encoders = [
69
- codec for codec in codecs
70
- if not getattr (codec .dump , 'not_implemented' , False )
71
- ]
72
-
73
- @property
74
- def codecs (self ):
75
- return self ._codecs
76
-
77
- @property
78
- def encoders (self ):
79
- return self ._encoders
80
63
81
64
@property
82
65
def decoders (self ):
@@ -86,123 +69,34 @@ def decoders(self):
86
69
def transports (self ):
87
70
return self ._transports
88
71
89
- def get_accept_header (self ):
90
- """
91
- Return an 'Accept' header for the given codecs.
92
- """
93
- return ', ' .join ([codec .media_type for codec in self .decoders ])
94
-
95
- def negotiate_decoder (self , content_type = None ):
96
- """
97
- Given the value of a 'Content-Type' header, return the appropriate
98
- codec registered to decode the request content.
99
- """
100
- if content_type is None :
101
- return self .decoders [0 ]
102
-
103
- content_type = content_type .split (';' )[0 ].strip ().lower ()
104
- for codec in self .decoders :
105
- if codec .media_type == content_type :
106
- break
107
- else :
108
- msg = "Unsupported media in Content-Type header '%s'" % content_type
109
- raise UnsupportedContentType (msg )
110
-
111
- return codec
112
-
113
- def negotiate_encoder (self , accept = None ):
114
- """
115
- Given the value of a 'Accept' header, return a two tuple of the appropriate
116
- content type and codec registered to encode the response content.
117
- """
118
- if accept is None :
119
- return self .encoders [0 ]
120
-
121
- acceptable = set ([
122
- item .split (';' )[0 ].strip ().lower ()
123
- for item in accept .split (',' )
124
- ])
125
-
126
- for codec in self .encoders :
127
- if codec .media_type in acceptable :
128
- return codec
129
-
130
- for codec in self .encoders :
131
- if codec .media_type .split ('/' )[0 ] + '/*' in acceptable :
132
- return codec
133
-
134
- if '*/*' in acceptable :
135
- return self .encoders [0 ]
136
-
137
- msg = "Unsupported media in Accept header '%s'" % accept
138
- raise NotAcceptable (msg )
139
-
140
- def determine_transport (self , url ):
141
- """
142
- Given a URL determine the appropriate transport instance.
143
- """
144
- url_components = urlparse .urlparse (url )
145
- scheme = url_components .scheme .lower ()
146
- netloc = url_components .netloc
147
-
148
- if not scheme :
149
- raise TransportError ("URL missing scheme '%s'." % url )
150
-
151
- if not netloc :
152
- raise TransportError ("URL missing hostname '%s'." % url )
153
-
154
- for transport in self .transports :
155
- if scheme in transport .schemes :
156
- break
157
- else :
158
- raise TransportError ("Unsupported URL scheme '%s'." % scheme )
159
-
160
- return transport
161
-
162
72
def get (self , url ):
163
- transport = self .determine_transport (url )
164
73
link = Link (url , action = 'get' )
165
- return transport .transition (link , client = self )
74
+
75
+ # Perform the action, and return a new document.
76
+ transport = determine_transport (link .url , transports = self .transports )
77
+ return transport .transition (link , decoders = self .decoders )
166
78
167
79
def reload (self , document ):
168
80
url = document .url
169
- transport = self .determine_transport (url )
170
81
link = Link (url , action = 'get' )
171
- return transport .transition (link , client = self )
82
+
83
+ # Perform the action, and return a new document.
84
+ transport = determine_transport (link .url , transports = self .transports )
85
+ return transport .transition (link , decoders = self .decoders )
172
86
173
87
def action (self , document , keys , params = None , action = None , inplace = None ):
174
88
if isinstance (keys , string_types ):
175
89
keys = [keys ]
176
90
177
- if params is None :
178
- params = {}
179
-
180
91
# Validate the keys and link parameters.
181
- link , link_ancestors = lookup_link (document , keys )
92
+ link , link_ancestors = _lookup_link (document , keys )
182
93
183
- if action is not None or inplace is not None :
94
+ if ( action is not None ) or ( inplace is not None ) :
184
95
# Handle any explicit overrides.
185
96
action = link .action if (action is None ) else action
186
97
inplace = link .inplace if (inplace is None ) else inplace
187
98
link = Link (link .url , action , inplace , link .fields )
188
99
189
100
# Perform the action, and return a new document.
190
- transport = self .determine_transport (link .url )
191
- return transport .transition (link , params , client = self , link_ancestors = link_ancestors )
192
-
193
- def load (self , bytestring , content_type = None ):
194
- """
195
- Given a bytestring and an optional content_type, return the
196
- parsed Document.
197
- """
198
- codec = self .negotiate_decoder (content_type )
199
- return codec .load (bytestring )
200
-
201
- def dump (self , document , accept = None , ** kwargs ):
202
- """
203
- Given a document, and an optional accept header, return a two-tuple of
204
- the selected media type and encoded bytestring.
205
- """
206
- codec = self .negotiate_encoder (accept )
207
- content = codec .dump (document , ** kwargs )
208
- return (codec .media_type , content )
101
+ transport = determine_transport (link .url , transports = self .transports )
102
+ return transport .transition (link , params , decoders = self .decoders , link_ancestors = link_ancestors )
0 commit comments