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} Z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)Z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   )selfr.   r-   Z
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   r/          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_valuer0   optionslenjoinis_requiredkeys)	r3   r4   param_valuesZenforce_completenesskw_param_valuesvalidated_valuesr&   r9   r;   r   r   r   validate_param_values   sJ   




z(HasParametersMixin.validate_param_valuesN)T)r   r   r    r!   r4   rC   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)r3   rG   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")rF   _get_definition_urlrG   lookup_xml_id_definition_factoryKeyError)r3   Z
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r3   idr   r   r   rM         z,WADLResolvableDefinition._definition_factoryc                 C   rR   )zmFind the URL that identifies an external reference.

        How to do this depends on the subclass.
        rS   r3   r   r   r   rK      rW   z,WADLResolvableDefinition._get_definition_urlN)r   r   r    r!   rH   rQ   rM   rK   r   r   r   r   rE      s    	"rE   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   rH   _url
isinstancer   rG   get_resource_typer1   representationjsonloadsr   r#   
media_typerepresentation_definitionget_representation_definition)r3   rG   urlresource_typer^   ra   representation_needs_processingrb   	__class__r   r   rH      s2   


zResource.__init__c                 C   s   | j S )z Return the URL to this resource.)r[   rX   r   r   r   rd   ,  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typerV   #)r1   r(   r)   r   rG   
markup_urlZensureSlashstr)r3   rd   Z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.rV   )r1   r(   rX   r   r   r   rV   C     zResource.idrY   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   rG   rd   r1   )r3   r^   ra   rf   rb   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.ZGET	mediaTypez4No definition for representation with media type %s.)
get_methodresponserQ   r1   r(   r)   r#   )r3   ra   Zdefault_get_responser^   representation_tagr   r   r   rc   ^  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.
        r9    N)_method_tag_iterr(   r)   lowerr   is_described_by)r3   Zhttp_methodra   query_paramsZrepresentation_params
method_tagr9   methodr   r   r   rr   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_definitionr4   r3   ra   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)rv   r   )r3   rz   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&   r9   N)r}   r1   r2   r   r(   r)   r   )r3   
param_namera   rP   rt   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.rY   plain8Don't know how to find value for a parameter of type %s.)ZdateTimedatez%Y-%m-%dr      zEPath traversal not implemented for a representation of media type %s.)r^   r   ra   r'   rT   r9   _dereference_namespacer1   ri   XML_SCHEMA_NS_URIr   r0   datetimetimestrptime)r3   	parameterr6   namespace_urlZ	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:   ru   )splitr)   NS_MAP)r3   r1   r6   	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.)rG   resource_typesr)   rU   r   r   r   rM        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.
        ri   r1   r(   r)   rX   r   r   r   rK        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.)r^   rb   rQ   rc   r   )r3   ra   rP   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)rQ   r1   r2   r   )r3   rP   rz   r   r   r   rv   *  s
   
zResource._method_tag_iter)NNTN)rY   TN)NNNNrD   )r   r   r    r!   rH   propertyrd   rn   rV   rp   rc   rr   r   r   r   r   r   r   rM   rK   r}   rv   __classcell__r   r   rg   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-   rG   r1   )r3   r-   rz   r   r   r   rH   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)RequestDefinitionr1   findr   rX   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.rs   )r   r-   r1   r   r   rX   r   r   r   rs   B  s   zMethod.responsec                 C   r   )z)The XML ID of the WADL method definition.rV   r   rX   r   r   r   rV   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.
        r9   r1   r(   r)   rw   rX   r   r   r   r9   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)r3   r@   rA   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   r^   )r3   ra   r@   rA   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   rc   r<   rC   ry   r0   rx   representationsr4   r-   )r3   ra   Zquery_valuesZrepresentation_valuesr^   r   r   r   r   rx   c  sJ   

zMethod.is_described_byrD   NN)NNN)r   r   r    r!   rH   r   r   rs   rV   r9   r   r   rx   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-   rG   r1   )r3   r{   Zrequest_tagr   r   r   rH     s   


zRequestDefinition.__init__c                 C   s   |  dgS )z,Return the query parameters for this method.queryr4   rX   r   r   r   ry     ro   zRequestDefinition.query_paramsc                 c   s.    | j tdD ]}t| j| j|V  q	d S )Nr^   )r1   r2   r   r   rG   r-   )r3   rP   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   ra   r3   ra   r^   r   r   r   rc     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)rc   	TypeErrorrp   )r3   ra   r@   rA   rP   r   r   r   r^     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   ?&)rC   ry   r-   rd   r<   r   sorteditems)r3   r@   rA   rB   rd   appendr   r   r   r     s   zRequestDefinition.build_urlrD   r   )r   r   r    r!   rH   r   ry   r   rc   r^   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)rG   r-   r1   headers)r3   r-   Zresponse_tagr   r   r   r   rH     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.
        r^   N)r   r1   r2   r   r-   rG   )r3   pathrt   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-   r1   )r3   r   r   r   r   rp     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&   r9   r'   headerN)r1   r2   r   r(   r)   r   )r3   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'   rT   r)   r9   )r3   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)r1   ra   r   r   r   r   rc     s   

z0ResponseDefinition.get_representation_definitionrD   )
r   r   r    r!   rH   r   rp   r   r   rc   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 rD   )rZ   r   rH   r-   r1   )r3   rG   r-   rt   rg   r   r   rH     s   
z!RepresentationDefinition.__init__c                    s   t t| ddg|S )Nr   r   )rZ   r   r4   r3   r-   rg   r   r   r4     s   
zRepresentationDefinition.paramsc                 C   s   dd |  |D S )z#Return the names of all parameters.c                 S   r5   r   )r9   )r*   r&   r   r   r   r/   $  r8   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.rq   )rQ   r1   r(   rX   r   r   r   ra   &  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randomZ	randrangereescapeencodesearch	MULTILINErl   )	r3   Z	all_parts_widthZ_fmttokenboundarybZ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   )r3   bufr   keyr6   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   )r3   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   r\   bytesr   ri   r   r   r   r   r   r   getvaluer   r=   r   )r3   partsZencoded_partsZ	is_binaryr9   r6   r   ZctypeZcdisplinesliner   Z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binaryrY   zUnsupported media type: '%s')rQ   r4   r-   rC   ra   r   r   r   objectr)   r9   r   ri   r   r_   dumpsr0   )r3   r@   rA   rP   r4   rB   ra   docr   missingr&   r6   r   r   r   rp     s2   
zRepresentationDefinition.bindc                 C   r   )z9Turn a representation ID into a RepresentationDefinition.)rG   representation_definitionsr)   rU   r   r   r   rM     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.
        Zhrefr   rX   r   r   r   rK     r   z,RepresentationDefinition._get_definition_url)F)r   r   r    r!   rH   r4   r   r   ra   r   r   r   r   rp   rM   rK   r   r   r   rg   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)rG   value_containerr1   )r3   r   r1   r   r   r   rH     s   

zParameter.__init__c                 C   r   )zThe name of this parameter.r9   r   rX   r   r   r   r9     r   zParameter.namec                 C   r   )zThe style of this parameter.r'   r   rX   r   r   r   r'     r   zParameter.stylec                 C   r   )zThe XSD type of this parameter.ri   r   rX   r   r   r   ri     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   rX   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.requiredZfalse)1truer   rX   r   r   r   r>     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   rX   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_tagrX   r   r   r/     s    z%Parameter.options.<locals>.<listcomp>r7   )r1   r2   r   rX   r   rX   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)r1   r   r   r   )r3   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   r0   follow)r3   r   r   r   r   linked_resource  s   
zParameter.linked_resourceN)r   r   r    r!   rH   r   r9   r'   ri   r:   r>   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   r1   )r3   r   r   r   r   r   rH     rI   zOption.__init__c                 C   r   )Nr6   r   rX   r   r   r   r6      r   zOption.valueN)r   r   r    r!   rH   r   r6   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)rZ   r   rH   rG   r   r1   )r3   r   r   rg   r   r   rH   ,  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
   rQ   rX   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)rK   r
   )r3   Z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   rG   r   r   r   r)   r1   rU   r   r   r   rM   L  s   zLink._definition_factoryc                 C   s"   | j jd}|du rtd|S )z(Find the URL containing the definition .re   NzIParameter is a link, but not to a resource with a known WADL description.)r1   r(   r)   r
   )r3   ri   r   r   r   rK   R  s   zLink._get_definition_url)r   r   r    r!   rH   r   r   r   rM   rK   r   r   r   rg   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)r1   )r3   Zresource_type_tagr   r   r   rH   ^  s   
zResourceType.__init__N)r   r   r    r!   rH   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	resourcesrm   r^   rV   Nre   )rk   hasattr_from_streamr   _from_stringr   r   r   r(   r)   resource_baser   r   r2   r   r	   )r3   rk   markupr^   rV   rP   re   r   r   r   rH   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   )ETZ	iterparser   popsetr   r   ElementTree)r3   streamZeventsrootr   Z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   )r\   r   r   r   r   r   )r3   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.NrJ   )rL   r   r)   rN   )r3   Zresource_type_urlrO   re   r   r   r   r]     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.
        NZhttpz,Can't look up definition in another url (%s))r   rk   ZensureNoSlashZfragment
startswithZresolverT   )r3   rd   Z
markup_uriZthis_uriZpossible_xml_idr   r   r   rL     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   r/     s    
z4Application.get_resource_by_path.<locals>.<listcomp>r   Nz+More than one resource defined with path %sTr   )r   r<   r
   r   r   r   )r3   r   Zmatchingr   r  r   get_resource_by_path  s   z Application.get_resource_by_pathN)
r   r   r    r!   rH   r   r   r]   rL   r  r   r   r   r   r   f  s     r   )6r!   ri   Z__metaclass____all__r   Zemail.utilsr   r   r_   r   r   r   r   Zurllib.parser   ImportErrorZurllibZxml.etree.cElementTreeZetreeZcElementTreer   Zxml.etree.ElementTreer   Zlazr.urir   r   Zwadllibr   r   Zwadllib.iso_strptimer   r   r   r   r   r   	Exceptionr
   r   r#   r   r$   r%   rE   r   r   r   r   r   r   r   r   r	   r   r   r   r   r   <module>   s`   	
B=  >j9B "]6