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
33from 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
66import collections
77import itypes
88
99
1010LinkAncestor = collections .namedtuple ('LinkAncestor' , ['document' , 'keys' ])
1111
1212
13- def lookup_link (document , keys ):
13+ def _lookup_link (document , keys ):
1414 """
1515 Validates that keys looking up a link are correct.
1616
@@ -53,30 +53,13 @@ def lookup_link(document, keys):
5353
5454
5555class 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
5959 if transports is None :
60- transports = [HTTPTransport ()]
61-
62- self ._codecs = itypes .List (codecs )
60+ transports = default_transports
61+ self ._decoders = itypes .List (decoders )
6362 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
8063
8164 @property
8265 def decoders (self ):
@@ -86,123 +69,34 @@ def decoders(self):
8669 def transports (self ):
8770 return self ._transports
8871
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-
16272 def get (self , url ):
163- transport = self .determine_transport (url )
16473 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 )
16678
16779 def reload (self , document ):
16880 url = document .url
169- transport = self .determine_transport (url )
17081 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 )
17286
17387 def action (self , document , keys , params = None , action = None , inplace = None ):
17488 if isinstance (keys , string_types ):
17589 keys = [keys ]
17690
177- if params is None :
178- params = {}
179-
18091 # Validate the keys and link parameters.
181- link , link_ancestors = lookup_link (document , keys )
92+ link , link_ancestors = _lookup_link (document , keys )
18293
183- if action is not None or inplace is not None :
94+ if ( action is not None ) or ( inplace is not None ) :
18495 # Handle any explicit overrides.
18596 action = link .action if (action is None ) else action
18697 inplace = link .inplace if (inplace is None ) else inplace
18798 link = Link (link .url , action , inplace , link .fields )
18899
189100 # 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