o
    R
`                     @   s  d Z eZg dZddlZddlmZ ddlZddlZddl	Z	ddl
Z
ddlZddlZzddlmZ W n eyA   ddlmZ Y nw zddlm  mZ W n ey_   ddlm  mZ Y nw ddlmZmZ ddlmZmZ ddlmZ d	Zd
Z dd Z!dd Z"dd Z#G dd de$Z%G dd de%Z&G dd de%Z'G dd de(Z)G dd dZ*G dd de)Z+G dd de+Z,G dd  d e)Z-G d!d" d"e)e*Z.G d#d$ d$e*Z/G d%d& d&e+e*Z0G d'd( d(e)Z1G d)d* d*e)Z2G d+d, d,e+Z3G d-d. d.e)Z4G d/d0 d0e)Z5dS )1a  Navigate the resources exposed by a web service.

The wadllib library helps a web client navigate the resources
exposed by a web service. The service defines its resources in a
single WADL file. wadllib parses this file and gives access to the
resources defined inside. The client code can see the capabilities of
a given resource and make the corresponding HTTP requests.

If a request returns a representation of the resource, the client can
bind the string representation to the wadllib Resource object.
)
ApplicationLinkMethodNoBoundRepresentationError	ParameterRepresentationDefinitionResponseDefinitionResourceResourceType	WADLError    N)quote)	urlencode)URImerge)_make_unicode_string_types)iso_strptimez	xmlns:mapz http://www.w3.org/2001/XMLSchemac                 C   s   d|  S )z)Scope a tag name with the WADL namespace.z&{http://research.sun.com/wadl/2006/10} tag_namer   r   5/usr/lib/python3/dist-packages/wadllib/application.pywadl_tagH   s   r   c                 C   s   dt |  S )z#Turn a tag name into an XPath path.z./)r   r   r   r   r   
wadl_xpathM   s   r   c                  G   s$   i }| D ]}|dur| | q|S )z<Merge any number of dictionaries, some of which may be None.N)update)dictsfinaldictr   r   r   _merge_dictsR   s   
r   c                   @      e Zd ZdZdS )r
   zAAn exception having to do with the state of the WADL application.N__name__
__module____qualname____doc__r   r   r   r   r
   [   s    r
   c                   @   r   )r   aA  An unbound resource was used where wadllib expected a bound resource.

    To obtain the value of a resource's parameter, you first must bind
    the resource to a representation. Otherwise the resource has no
    idea what the value is and doesn't even know if you've given it a
    parameter name that makes sense.
    Nr   r   r   r   r   r   `       r   c                   @   r   )UnsupportedMediaTypeErrorzA media type was given that's not supported in this context.

    A resource can only be bound to media types it has representations
    of.
    Nr   r   r   r   r   r%   j   r$   r%   c                   @   r   )WADLBasez?A base class for objects that contain WADL-derived information.Nr   r   r   r   r   r&   r   r$   r&   c                   @   s&   e Zd ZdZdddZ	d	ddZdS )
HasParametersMixinzAA mixin class for objects that have associated Parameter objects.Nc                    s\    du r| j   du rtd| jdu rg S | jtd}|du r$g S  fdd|D S )z6Find subsidiary parameters that have the given styles.Nz&Could not find any particular resourceparamc                    s&   g | ]}|j d v rt |qS )style)attribgetr   ).0	param_tagresourcestylesr   r   
<listcomp>   s    z-HasParametersMixin.params.<locals>.<listcomp>)r/   
ValueErrortagfindallr   )selfr0   r/   
param_tagsr   r.   r   paramsy   s   
zHasParametersMixin.paramsTc           	      K   s
  t ||}i }|D ]h}|j}|jdur/||v r*|| |jkr*td|| ||jf |j||< dd |jD }t|dkrU||v rU|| |vrUtd|| |d|f |rd|jrd||vrdtd| ||v rq|| ||< ||= q	t|dkrtd	d
|  |S )a  Make sure the given valueset is valid.

        A valueset might be invalid because it contradicts a fixed
        value or (if enforce_completeness is True) because it lacks a
        required value.

        :param params: A list of Parameter objects.
        :param param_values: A dictionary of parameter values. May include
           paramters whose names are not valid Python identifiers.
        :param enforce_completeness: If True, this method will raise
           an exception when the given value set lacks a value for a
           required parameter.
        :param kw_param_values: A dictionary of parameter values.
        :return: A dictionary of validated parameter values.
        Nz=Value '%s' for parameter '%s' conflicts with fixed value '%s'c                 S      g | ]}|j qS r   )value)r,   optionr   r   r   r1          z<HasParametersMixin.validate_param_values.<locals>.<listcomp>r   z=Invalid value '%s' for parameter '%s': valid values are: "%s"z", "z$No value for required parameter '%s'zUnrecognized parameter(s): '%s'z', ')	r   namefixed_valuer2   optionslenjoinis_requiredkeys)	r5   r7   param_valuesenforce_completenesskw_param_valuesvalidated_valuesr(   r<   r>   r   r   r   validate_param_values   sJ   




z(HasParametersMixin.validate_param_valuesN)T)r    r!   r"   r#   r7   rG   r   r   r   r   r'   v   s
    
r'   c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )WADLResolvableDefinitionz=A base class for objects whose definitions may be references.c                 C   s   d| _ || _dS )zInitialize with a WADL application.

        :param application: A WADLDefinition. Relative links are
            assumed to be relative to this object's URL.
        N)_definitionapplication)r5   rK   r   r   r   __init__      
z!WADLResolvableDefinition.__init__c                 C   s^   | j dur| j S |  }|du r| | _ | S | j|}| |}|du r*td| || _ |S )a  Return the definition of this object, wherever it is.

        Resource is a good example. A WADL <resource> tag
        may contain a large number of nested tags describing a
        resource, or it may just contain a 'type' attribute that
        references a <resource_type> which contains those same
        tags. Resource.resolve_definition() will return the original
        Resource object in the first case, and a
        ResourceType object in the second case.
        NNo such XML ID: "%s")rJ   _get_definition_urlrK   lookup_xml_id_definition_factoryKeyError)r5   
object_urlxml_id
definitionr   r   r   resolve_definition   s   

z+WADLResolvableDefinition.resolve_definitionc                 C      t  )zxTransform an XML ID into a wadllib wrapper object.

        Which kind of object it is depends on the subclass.
        NotImplementedErrorr5   idr   r   r   rQ         z,WADLResolvableDefinition._definition_factoryc                 C   rW   )zmFind the URL that identifies an external reference.

        How to do this depends on the subclass.
        rX   r5   r   r   r   rO      r\   z,WADLResolvableDefinition._get_definition_urlN)r    r!   r"   r#   rL   rV   rQ   rO   r   r   r   r   rI      s    	"rI   c                       s   e Zd ZdZ			d' fdd	Zedd Zedd	 Zed
d Z			d(ddZ	dd Z
		d)ddZd*ddZd*ddZedd Zd*ddZdd Zdd Zdd  Zd!d" Zd*d#d$Zd%d& Z  ZS )+r   z/A resource, possibly bound to a representation.NTc                    s   t t| | || _t|tr| j|j| _n|| _d| _	|dur<|dkr6|r2t
t|| _	n
|| _	ntd| || _|durU|durL|| _dS | | j| _dS dS )a[  
        :param application: A WADLApplication.
        :param url: The URL to this resource.
        :param resource_type: An ElementTree <resource> or <resource_type> tag.
        :param representation: A string representation.
        :param media_type: The media type of the representation.
        :param representation_needs_processing: Set to False if the
            'representation' parameter should be used as
            is. Otherwise, it will be transformed from a string into
            an appropriate Python data structure, depending on its
            media type.
        :param representation_definition: A RepresentationDefinition
            object describing the structure of this
            representation. Used in cases when the representation
            isn't the result of sending a standard GET to the
            resource.
        Napplication/jsonz?This resource doesn't define a representation for media type %s)superr   rL   _url
isinstancer   rK   get_resource_typer3   representationjsonloadsr   r%   
media_typerepresentation_definitionget_representation_definition)r5   rK   urlresource_typerc   rf   representation_needs_processingrg   	__class__r   r   rL      s2   


zResource.__init__c                 C   s   | j S )z Return the URL to this resource.)r`   r]   r   r   r   ri   ,  s   zResource.urlc                 C   sb   | j du rdS | j jd}|dur|S | j jd}|dur/t| jj }t|d | S dS )z@Return the URL to the type definition for this resource, if any.Ntyper[   #)r3   r*   r+   r   rK   
markup_urlensureSlashstr)r5   ri   type_idbaser   r   r   type_url1  s   
zResource.type_urlc                 C   s   | j jd S )zReturn the ID of this resource.r[   )r3   r*   r]   r   r   r   r[   C     zResource.idr^   c                 C   s   t | j| j| j||||S )a  Bind the resource to a representation of that resource.

        :param representation: A string representation
        :param media_type: The media type of the representation.
        :param representation_needs_processing: Set to False if the
            'representation' parameter should be used as
            is.
        :param representation_definition: A RepresentationDefinition
            object describing the structure of this
            representation. Used in cases when the representation
            isn't the result of sending a standard GET to the
            resource.
        :return: A Resource bound to a particular representation.
        )r   rK   ri   r3   )r5   rc   rf   rk   rg   r   r   r   bindH  s
   zResource.bindc                 C   sD   |  dj}|D ]}| j}|jd|kr|  S qtd| )z<Get a description of one of this resource's representations.GET	mediaTypez4No definition for representation with media type %s.)
get_methodresponserV   r3   r*   r+   r%   )r5   rf   default_get_responserc   representation_tagr   r   r   rh   ^  s   
z&Resource.get_representation_definitionc                 C   sX   |   D ]%}|jdd }|du s|| kr)t| |}||||r)|  S qdS )a   Look up one of this resource's methods by HTTP method.

        :param http_method: The HTTP method used to invoke the desired
                            method. Case-insensitive and optional.

        :param media_type: The media type of the representation
                           accepted by the method. Optional.

        :param query_params: The names and values of any fixed query
                             parameters used to distinguish between
                             two methods that use the same HTTP
                             method. Optional.

        :param representation_params: The names and values of any
                             fixed representation parameters used to
                             distinguish between two methods that use
                             the same HTTP method and have the same
                             media type. Optional.

        :return: A MethodDefinition, or None if there's no definition
                  that fits the given constraints.
        r<    N)_method_tag_iterr*   r+   lowerr   is_described_by)r5   http_methodrf   query_paramsrepresentation_params
method_tagr<   methodr   r   r   rz   h  s   
zResource.get_methodc                 C      |  || S )a~  A list of this resource's parameters.

        :param media_type: Media type of the representation definition
            whose parameters are being named. Must be present unless
            this resource is bound to a representation.

        :raise NoBoundRepresentationError: If this resource is not
            bound to a representation and media_type was not provided.
        )_find_representation_definitionr7   r5   rf   r   r   r   
parameters  
   
zResource.parametersc                 C   r   )a  A list naming this resource's parameters.

        :param media_type: Media type of the representation definition
            whose parameters are being named. Must be present unless
            this resource is bound to a representation.

        :raise NoBoundRepresentationError: If this resource is not
            bound to a representation and media_type was not provided.
        )r   parameter_namesr   r   r   r   r     r   zResource.parameter_namesc                 c   s     |   D ]}t| |V  qdS )z6An iterator over the methods defined on this resource.N)r   r   )r5   r   r   r   r   method_iter  s   zResource.method_iterc                 C   sF   |  |}|j}|tdD ]}|jd|kr t| |  S qdS )a  Find a parameter within a representation definition.

        :param param_name: Name of the parameter to find.

        :param media_type: Media type of the representation definition
            whose parameters are being named. Must be present unless
            this resource is bound to a representation.

        :raise NoBoundRepresentationError: If this resource is not
            bound to a representation and media_type was not provided.
        r(   r<   N)r   r3   r4   r   r*   r+   r   )r5   
param_namerf   rU   r}   r-   r   r   r   get_parameter  s   
zResource.get_parameterc                 C   s   | j du r	td| jdkrd|jdkrtd|j | j |j }|durb| |j|j\}}|t	krb|dv rbzt
|}W |S  tya   ztjt|ddd	  }W Y |S  ty`   t|w w |S td
| j )zFind the value of a parameter, given the Parameter object.

        :raise ValueError: If the parameter value can't be converted into
        its defined type.
        Nz,Resource is not bound to any representation.r^   plain8Don't know how to find value for a parameter of type %s.)dateTimedatez%Y-%m-%dr      zEPath traversal not implemented for a representation of media type %s.)rc   r   rf   r)   rY   r<   _dereference_namespacer3   rn   XML_SCHEMA_NS_URIr   r2   datetimetimestrptime)r5   	parameterr9   namespace_url	data_typer   r   r   get_parameter_value  sH   




zResource.get_parameter_valuec                 C   sD   |durd|v r| dd\}}nd}|t}||d}||fS )zSplits a value into namespace URI and value.

        :param tag: A tag to use as context when mapping namespace
        names to URIs.
        N:   r~   )splitr+   NS_MAP)r5   r3   r9   	namespacens_mapr   r   r   r   r     s   
zResource._dereference_namespacec                 C      | j j|S )z-Given an ID, find a ResourceType for that ID.)rK   resource_typesr+   rZ   r   r   r   rQ        zResource._definition_factoryc                 C      | j jdS )zReturn the URL that shows where a resource is 'really' defined.

        If a resource's capabilities are defined by reference, the
        <resource> tag's 'type' attribute will contain the URL to the
        <resource_type> that defines them.
        rn   r3   r*   r+   r]   r   r   r   rO        zResource._get_definition_urlc                 C   s>   | j dur| j }| S |dur| |}| S td)a3  Get the most appropriate representation definition.

        If media_type is provided, the most appropriate definition is
        the definition of the representation of that media type.

        If this resource is bound to a representation, the most
        appropriate definition is the definition of that
        representation. Otherwise, the most appropriate definition is
        the definition of the representation served in response to a
        standard GET.

        :param media_type: Media type of the definition to find. Must
            be present unless the resource is bound to a
            representation.

        :raise NoBoundRepresentationError: If this resource is not
            bound to a representation and media_type was not provided.

        :return: A RepresentationDefinition
        NzSResource is not bound to any representation, and no media media type was specified.)rc   rg   rV   rh   r   )r5   rf   rU   r   r   r   r     s   


z(Resource._find_representation_definitionc                 c   s*    |   j}|tdD ]}|V  qdS )z+Iterate over this resource's <method> tags.r   N)rV   r3   r4   r   )r5   rU   r   r   r   r   r   *  s
   
zResource._method_tag_iter)NNTN)r^   TN)NNNNrH   )r    r!   r"   r#   rL   propertyri   ru   r[   rw   rh   rz   r   r   r   r   r   r   rQ   rO   r   r   __classcell__r   r   rl   r   r      s>    4






!


0
	#r   c                   @   sn   e Zd ZdZdd Zedd Zedd Zedd	 Zed
d Z	dddZ
		dddZ		dddZdS )r   z*A wrapper around an XML <method> tag.
    c                 C   s   || _ | j j| _|| _dS )zaInitialize with a <method> tag.

        :param method_tag: An ElementTree <method> tag.
        N)r/   rK   r3   )r5   r/   r   r   r   r   rL   4  s   

zMethod.__init__c                 C   s   t | | jtdS )z@Return the definition of a request that invokes the WADL method.request)RequestDefinitionr3   findr   r]   r   r   r   r   =  s   zMethod.requestc                 C   s   t | j| jtdS )z9Return the definition of the response to the WADL method.r{   )r   r/   r3   r   r   r]   r   r   r   r{   B  s   zMethod.responsec                 C   r   )z)The XML ID of the WADL method definition.r[   r   r]   r   r   r   r[   H     z	Method.idc                 C   s   | j jd S )zThe name of the WADL method definition.

        This is also the name of the HTTP method (GET, POST, etc.)
        that should be used to invoke the WADL method.
        r<   r3   r*   r+   r   r]   r   r   r   r<   M  s   zMethod.nameNc                 K   s   | j j|fi |S )4Return the request URL to use to invoke this method.)r   	build_url)r5   rC   rE   r   r   r   build_request_urlV     zMethod.build_request_urlc                 K   s   | j j||fi |S )zBuild a representation to be sent when invoking this method.

        :return: A 2-tuple of (media_type, representation).
        )r   rc   )r5   rf   rC   rE   r   r   r   build_representationZ  s
   zMethod.build_representationc              	   C   s   d}|dur| j |}|du rdS |dur:t|dkr:| j }|du r%dS z
||j|d W n
 ty9   Y dS w |du sDt|dkrFdS |durO||S | j jD ]}z||| j	|d W  dS  tym   Y qSw dS )a  Returns true if this method fits the given constraints.

        :param media_type: The method must accept this media type as a
                           representation.

        :param query_values: These key-value pairs must be acceptable
                           as values for this method's query
                           parameters. This need not be a complete set
                           of parameters acceptable to the method.

        :param representation_values: These key-value pairs must be
                           acceptable as values for this method's
                           representation parameters. Again, this need
                           not be a complete set of parameters
                           acceptable to the method.
        NFr   T)
r   rh   r?   rG   r   r2   r   representationsr7   r/   )r5   rf   query_valuesrepresentation_valuesrc   r   r   r   r   r   c  sJ   

zMethod.is_described_byrH   NN)NNN)r    r!   r"   r#   rL   r   r   r{   r[   r<   r   r   r   r   r   r   r   r   1  s$    	





	r   c                   @   sN   e Zd ZdZdd Zedd Zedd Zdd	d
ZdddZ	dddZ
dS )r   zBA wrapper around the description of the request invoking a method.c                 C   s$   || _ | j j| _| jj| _|| _dS )zInitialize with a <request> tag.

        :param resource: The resource to which this request can be sent.
        :param request_tag: An ElementTree <request> tag.
        N)r   r/   rK   r3   )r5   r   request_tagr   r   r   rL     s   


zRequestDefinition.__init__c                 C   s   |  dgS )z,Return the query parameters for this method.queryr7   r]   r   r   r   r     rv   zRequestDefinition.query_paramsc                 c   s.    | j tdD ]}t| j| j|V  q	d S )Nrc   )r3   r4   r   r   rK   r/   )r5   rU   r   r   r   r     s   
z!RequestDefinition.representationsNc                 C   s*   | j D ]}|du s|j|kr|  S qdS )z1Return the appropriate representation definition.N)r   rf   r5   rf   rc   r   r   r   rh     s
   
z/RequestDefinition.get_representation_definitionc                 K   s0   |  |}|du rtd| |j|fi |S )zBuild a representation to be sent along with this request.

        :return: A 2-tuple of (media_type, representation).
        Nz,Cannot build representation of media type %s)rh   	TypeErrorrw   )r5   rf   rC   rE   rU   r   r   r   rc     s   
z RequestDefinition.representationc                 K   sX   | j | j|fi |}| jj}t|dkr*d|v rd}nd}||tt|  7 }|S )r   r   ?&)rG   r   r/   ri   r?   r   sorteditems)r5   rC   rE   rF   ri   appendr   r   r   r     s   zRequestDefinition.build_urlrH   r   )r    r!   r"   r#   rL   r   r   r   rh   rc   r   r   r   r   r   r     s    



r   c                   @   sB   e Zd ZdZdddZdd Zdd Zd	d
 Zdd Zdd Z	dS )r   z;A wrapper around the description of a response to a method.Nc                 C   s   |j | _ || _|| _|| _dS )zgInitialize with a <response> tag.

        :param response_tag: An ElementTree <response> tag.
        N)rK   r/   r3   headers)r5   r/   response_tagr   r   r   r   rL     s   
zResponseDefinition.__init__c                 c   s4    t d}| j|D ]}t| jj| j|V  qdS )zGet an iterator over the representation definitions.

        These are the representations returned in response to an
        invocation of this method.
        rc   N)r   r3   r4   r   r/   rK   )r5   pathr}   r   r   r   __iter__  s   zResponseDefinition.__iter__c                 C   s   t | j| j|S )zBind the response to a set of HTTP headers.

        A WADL response can have associated header parameters, but no
        other kind.
        )r   r/   r3   )r5   r   r   r   r   rw     s   zResponseDefinition.bindc                 C   sH   | j tdD ]}|jd|kr!|jddkr!t| |  S qdS )z,Find a header parameter within the response.r(   r<   r)   headerN)r3   r4   r   r*   r+   r   )r5   r   r-   r   r   r   r     s   z ResponseDefinition.get_parameterc                 C   s8   | j du r	td|jdkrtd|j | j |jS )z:Find the value of a parameter, given the Parameter object.Nz,Response object is not bound to any headers.r   r   )r   r   r)   rY   r+   r<   )r5   r   r   r   r   r     s   

z&ResponseDefinition.get_parameter_valuec                 C   s.   | j du rdS | D ]}|j|kr|  S q	dS )z8Get one of the possible representations of the response.N)r3   rf   r   r   r   r   rh     s   

z0ResponseDefinition.get_representation_definitionrH   )
r    r!   r"   r#   rL   r   rw   r   r   rh   r   r   r   r   r     s    

r   c                       sz   e Zd ZdZ fddZ fddZdd Zedd	 Zd
d Z	dd Z
dddZdd Zdd Zdd Zdd Z  ZS )r   z2A definition of the structure of a representation.c                    s    t t| | || _|| _d S rH   )r_   r   rL   r/   r3   )r5   rK   r/   r}   rl   r   r   rL     s   
z!RepresentationDefinition.__init__c                    s   t t| ddg|S )Nr   r   )r_   r   r7   r5   r/   rl   r   r   r7     s   
zRepresentationDefinition.paramsc                 C   s   dd |  |D S )z#Return the names of all parameters.c                 S   r8   r   )r<   )r,   r(   r   r   r   r1   $  r;   z<RepresentationDefinition.parameter_names.<locals>.<listcomp>r   r   r   r   r   r   "  r   z(RepresentationDefinition.parameter_namesc                 C   s   |   jjd S )z4The media type of the representation described here.ry   )rV   r3   r*   r]   r   r   r   rf   &  s   z#RepresentationDefinition.media_typec           	      C   s   t ttjd }d| }ttj}d||  d }|du r!|S |}d}	 dt| d	 d
}tj	||tj
ds>	 |S |d t| }|d7 }q&)z;Make a random boundary that does not appear in `all_parts`.r   z%%0%ddz===============z==Nr   Tz^--z(--)?$ascii)flags.)r?   reprsysmaxsizerandom	randrangereescapeencodesearch	MULTILINErr   )	r5   	all_parts_width_fmttokenboundarybcounterpatternr   r   r   _make_boundary+  s    z'RepresentationDefinition._make_boundaryc                 C   sP   |D ]\}}| |d | d | |d | d q| d dS )z$Write MIME headers to a file object.UTF-8s   :    
Nwriter   )r5   bufr   keyr9   r   r   r   _write_headers=  s   
z'RepresentationDefinition._write_headersFc                 C   s6   | d | |d |r| d | d dS )z,Write a multipart boundary to a file object.s   --r   r   Nr   )r5   r   r   closingr   r   r   _write_boundaryF  s
   

z(RepresentationDefinition._write_boundaryc                 C   s  g }|D ]|\}}}t  }|rd}dt|t|f }nd}dt| }| |dd|fd|fg |rFt|ts@tdt| || n3t|t	sStd	t| t
d
|}	|	dd D ]}
||
d |d q_||	d d ||  q| d|}t  }dt| }| |dd|fg |D ]}| || || |d q| j||dd || fS )aV  Generate a multipart/form-data message.

        This is very loosely based on the email module in the Python standard
        library.  However, that module doesn't really support directly embedding
        binary data in a form: various versions of Python have mangled line
        separators in different ways, and none of them get it quite right.
        Since we only need a tiny subset of MIME here, it's easier to implement
        it ourselves.

        :return: a tuple of two elements: the Content-Type of the message, and
            the entire encoded message as a byte string.
        zapplication/octet-streamz#form-data; name="%s"; filename="%s"ztext/plain; charset="utf-8"zform-data; name="%s")zMIME-Versionz1.0zContent-TypezContent-Dispositionzbytes payload expected: %szstring payload expected: %sz
\r\n|\r|\nNr   r   z"multipart/form-data; boundary="%s"T)r   )ioBytesIOr   r   ra   bytesr   rn   r   r   r   r   r   r   getvaluer   r@   r   )r5   partsencoded_parts	is_binaryr<   r9   r   ctypecdisplinesliner   encoded_partr   r   r   _generate_multipart_formN  sT   



z1RepresentationDefinition._generate_multipart_formc                 K   s   |   }|| j}| j||fi |}| j}|dkr'tt| }||fS |dkrWg }t }	|D ]}
|	|
j
|	}||	urK||
jdk|
j
|f q2| |\}}||fS |dkrdt|}||fS td| )zzBind the definition to parameter values, creating a document.

        :return: A 2-tuple (media_type, document).
        z!application/x-www-form-urlencodedzmultipart/form-databinaryr^   zUnsupported media type: '%s')rV   r7   r/   rG   rf   r   r   r   objectr+   r<   r   rn   r   rd   dumpsr2   )r5   rC   rE   rU   r7   rF   rf   docr   missingr(   r9   r   r   r   rw     s2   
zRepresentationDefinition.bindc                 C   r   )z9Turn a representation ID into a RepresentationDefinition.)rK   representation_definitionsr+   rZ   r   r   r   rQ     r   z,RepresentationDefinition._definition_factoryc                 C   r   )a  Find the URL containing the representation's 'real' definition.

        If a representation's structure is defined by reference, the
        <representation> tag's 'href' attribute will contain the URL
        to the <representation> that defines the structure.
        hrefr   r]   r   r   r   rO     r   z,RepresentationDefinition._get_definition_url)F)r    r!   r"   r#   rL   r7   r   r   rf   r   r   r   r   rw   rQ   rO   r   r   r   rl   r   r     s    

	Ar   c                   @   s   e Zd ZdZdd Zedd Zedd Zedd	 Zed
d Z	edd Z
dd Zedd Zedd Zedd ZdS )r   z5One of the parameters of a representation definition.c                 C   s   |j | _ || _|| _dS )a  Initialize with respect to a value container.

        :param value_container: Usually the resource whose representation
            has this parameter. If the resource is bound to a representation,
            you'll be able to find the value of this parameter in the
            representation. This may also be a server response whose headers
            define a value for this parameter.
        :tag: The ElementTree <param> tag for this parameter.
        N)rK   value_containerr3   )r5   r   r3   r   r   r   rL     s   

zParameter.__init__c                 C   r   )zThe name of this parameter.r<   r   r]   r   r   r   r<     r   zParameter.namec                 C   r   )zThe style of this parameter.r)   r   r]   r   r   r   r)     r   zParameter.stylec                 C   r   )zThe XSD type of this parameter.rn   r   r]   r   r   r   rn     r   zParameter.typec                 C   r   )a9  The value to which this parameter is fixed, if any.

        A fixed parameter must be present in invocations of a WADL
        method, and it must have a particular value. This is commonly
        used to designate one parameter as containing the name of the
        server-side operation to be invoked.
        fixedr   r]   r   r   r   r=     s   	zParameter.fixed_valuec                 C   s   | j jdd dv S )z6Whether or not a value for this parameter is required.requiredfalse)1truer   r]   r   r   r   rA     s   zParameter.is_requiredc                 C   s   | j | S )zThe value of this parameter in the bound representation/headers.

        :raise NoBoundRepresentationError: If this parameter's value
               container is not bound to a representation or a set of
               headers.
        )r   r   r]   r   r   r   	get_value  s   zParameter.get_valuec                    s    fdd j tdD S )z7Return the set of acceptable values for this parameter.c                    s   g | ]}t  |qS r   )Option)r,   
option_tagr]   r   r   r1     s    z%Parameter.options.<locals>.<listcomp>r:   )r3   r4   r   r]   r   r]   r   r>     s   
zParameter.optionsc                 C   s&   | j td}|du rdS t| |S )zGet the link to another resource.

        The link may be examined and, if its type is of a known WADL
        description, it may be followed.

        :return: A Link object, or None.
        linkN)r3   r   r   r   )r5   link_tagr   r   r   r    s   	
zParameter.linkc                 C   s   | j }|du rtd|jS )a  Follow a link from this parameter to a new resource.

        This only works for parameters whose WADL definition includes a
        <link> tag that points to a known WADL description.

        :return: A Resource object for the resource at the other end
        of the link.
        Nz(This parameter isn't a link to anything.)r  r2   follow)r5   r  r   r   r   linked_resource  s   
zParameter.linked_resourceN)r    r!   r"   r#   rL   r   r<   r)   rn   r=   rA   r  r>   r  r
  r   r   r   r   r     s(    





	

r   c                   @   s$   e Zd ZdZdd Zedd ZdS )r  z0One of a set of possible values for a parameter.c                 C   s   || _ || _dS )z}Initialize the option.

        :param parameter: A Parameter.
        :param link_tag: An ElementTree <option> tag.
        N)r   r3   )r5   r   r  r   r   r   rL     rM   zOption.__init__c                 C   r   )Nr9   r   r]   r   r   r   r9      r   zOption.valueN)r    r!   r"   r#   rL   r   r9   r   r   r   r   r    s
    	r  c                       sH   e Zd ZdZ fddZedd Zedd Zdd	 Zd
d Z	  Z
S )r   zA link from one resource to another.

    Calling resolve_definition() on a Link will give you a Resource for the
    type of resource linked to. An alias for this is 'follow'.
    c                    s"   t t| |j || _|| _dS )zyInitialize the link.

        :param parameter: A Parameter.
        :param link_tag: An ElementTree <link> tag.
        N)r_   r   rL   rK   r   r3   )r5   r   r  rl   r   r   rL   ,  s   
zLink.__init__c                 C   s   | j std|  S )z$Follow the link to another Resource.zfCannot follow a link when the target has no WADL description. Try using a general HTTP client instead.)
can_followr
   rV   r]   r   r   r   r	  6  s   zLink.followc                 C   s$   z|   }W dS  ty   Y dS w )zCan this link be followed within wadllib?

        wadllib can follow a link if it points to a resource that has
        a WADL definition.
        FT)rO   r
   )r5   definition_urlr   r   r   r  ?  s   
zLink.can_followc                 C   s    t | j| j | jj|jS )z,Turn a resource type ID into a ResourceType.)r   rK   r   r  r   r+   r3   rZ   r   r   r   rQ   L  s   zLink._definition_factoryc                 C   s"   | j jd}|du rtd|S )z(Find the URL containing the definition .rj   NzIParameter is a link, but not to a resource with a known WADL description.)r3   r*   r+   r
   )r5   rn   r   r   r   rO   R  s   zLink._get_definition_url)r    r!   r"   r#   rL   r   r	  r  rQ   rO   r   r   r   rl   r   r   %  s    


r   c                   @   s   e Zd ZdZdd ZdS )r	   z,A wrapper around an XML <resource_type> tag.c                 C   s
   || _ dS )zvInitialize with a <resource_type> tag.

        :param resource_type_tag: An ElementTree <resource_type> tag.
        N)r3   )r5   resource_type_tagr   r   r   rL   ^  s   
zResourceType.__init__N)r    r!   r"   r#   rL   r   r   r   r   r	   [  s    r	   c                   @   s@   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dS )r   z1A WADL document made programmatically accessible.c                 C   s   || _ t|dr| || _n| || _| jtd| _| jj	d| _
i | _i | _| jtdD ]}|j	d}|durKt| d|}|| j|< q4| jtdD ]}|jd }t|| j|< qTdS )zParse WADL and find the most important parts of the document.

        :param markup_url: The URL from which this document was obtained.
        :param markup: The WADL markup itself, or an open filehandle to it.
        read	resourcesrt   rc   r[   Nrj   )rp   hasattr_from_streamr   _from_stringr   r   r  r*   r+   resource_baser   r   r4   r   r	   )r5   rp   markuprc   r[   rU   rj   r   r   r   rL   i  s(   


zApplication.__init__c                 C   sv   d}d}g }t ||D ])\}}|dkr|| q|dkr#|  q|dkr5|du r-|}|tt| qt |S )zrTurns markup into a document.

        Just a wrapper around ElementTree which keeps track of namespaces.
        )startstart-nsend-nsNr  r  r  )ET	iterparser   popsetr   r   ElementTree)r5   streameventsrootr   eventelemr   r   r   r    s   

zApplication._from_streamc                 C   s$   t |ts
|d}| t|S )zTurns markup into a document.r   )ra   r   r   r  r   r   )r5   r  r   r   r   r    s   

zApplication._from_stringc                 C   s.   |  |}| j|}|du rtd| |S )z7Retrieve a resource type by the URL of its description.NrN   )rP   r   r+   rR   )r5   resource_type_urlrT   rj   r   r   r   rb     s
   
zApplication.get_resource_typec                 C   sZ   t | j }d|_|drt | }n||}|j}d|_||kr'|S td| )zA helper method for locating a part of a WADL document.

        :param url: The URL (with anchor) of the desired part of the
        WADL document.
        :return: The XML ID corresponding to the anchor.
        Nhttpz,Can't look up definition in another url (%s))r   rp   ensureNoSlashfragment
startswithresolverY   )r5   ri   
markup_urithis_uripossible_xml_idr   r   r   rP     s   

zApplication.lookup_xml_idc                    sV    fdd| j D }t|dk rdS t|dkrtd  t| t| j d|d S )zpLocate one of the resources described by this document.

        :param path: The path to the resource.
        c                    s   g | ]}|j d   kr|qS r   )r*   )r,   r/   r+  r   r   r1     s    
z4Application.get_resource_by_path.<locals>.<listcomp>r   Nz+More than one resource defined with path %sTr   )r  r?   r
   r   r   r  )r5   r   matchingr   r+  r   get_resource_by_path  s   z Application.get_resource_by_pathN)
r    r!   r"   r#   rL   r  r  rb   rP   r-  r   r   r   r   r   f  s     r   )6r#   rn   __metaclass____all__r   email.utilsr   r   rd   r   r   r   r   urllib.parser   ImportErrorurllibxml.etree.cElementTreeetreecElementTreer  xml.etree.ElementTreer  lazr.urir   r   wadllibr   r   wadllib.iso_strptimer   r   r   r   r   r   	Exceptionr
   r   r%   r   r&   r'   rI   r   r   r   r   r   r   r  r   r	   r   r   r   r   r   <module>   s`   	
B=  >j9B "]6