U
    Q[                  
   @   s  d Z eZddddddddd	d
g
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k
r   ddlmZ Y nX ddlm  mZ 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(Z.G d*d de'Z/G d+d, d,e'Z0G d-d de)Z1G d.d	 d	e'Z2G d/d de'Z3dS )0a  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_tagE   s    r   c                 C   s   dt |  S )z#Turn a tag name into an XPath path.z./)r   r   r   r   r   
wadl_xpathJ   s    r   c                  G   s$   i }| D ]}|dk	r| | q|S )z<Merge any number of dictionaries, some of which may be None.N)update)Zdictsfinaldictr   r   r   _merge_dictsO   s
    r   c                   @   s   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
   X   s   c                   @   s   e Zd ZdZdS )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   ]   s   c                   @   s   e Zd ZdZdS )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!   g   s   r!   c                   @   s   e Zd ZdZdS )WADLBasez?A base class for objects that contain WADL-derived information.Nr   r   r   r   r   r"   o   s   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kr| j   dkrtd| jdkr,g S | jtd}|dkrHg 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 k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   paramsv   s    
zHasParametersMixin.paramsTc           	      K   s  t ||}i }|D ]}|j}|jdk	r^||krT|| |jkrTtd|| ||jf |j||< dd |jD }t|dkr||kr|| |krtd|| |d|f |r|jr||krtd| ||kr|| ||< ||= qt|dkrt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   s   g | ]
}|j qS r   )value)r(   optionr   r   r   r-      s     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_valuer.   optionslenjoinis_requiredkeys)	r1   r2   param_valuesZenforce_completenesskw_param_valuesvalidated_valuesr$   r5   r7   r   r   r   validate_param_values   sL    



  
z(HasParametersMixin.validate_param_values)N)T)r   r   r   r    r2   r?   r   r   r   r   r#   s   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)r1   rB   r   r   r   __init__   s    z!WADLResolvableDefinition.__init__c                 C   s^   | j dk	r| j S |  }|dkr*| | _ | S | j|}| |}|dkrTt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")rA   _get_definition_urlrB   lookup_xml_id_definition_factoryKeyError)r1   Z
object_urlxml_id
definitionr   r   r   resolve_definition   s    

z+WADLResolvableDefinition.resolve_definitionc                 C   s
   t  dS )zxTransform an XML ID into a wadllib wrapper object.

        Which kind of object it is depends on the subclass.
        NNotImplementedErrorr1   idr   r   r   rG      s    z,WADLResolvableDefinition._definition_factoryc                 C   s
   t  dS )zmFind the URL that identifies an external reference.

        How to do this depends on the subclass.
        NrL   r1   r   r   r   rE      s    z,WADLResolvableDefinition._get_definition_urlN)r   r   r   r    rC   rK   rG   rE   r   r   r   r   r@      s
   	"r@   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r2| j|j| _n|| _d| _	|dk	rx|dkrl|rdt
t|| _	qx|| _	ntd| || _|dk	r|dk	r|| _n| | j| _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   rC   _url
isinstancer   rB   get_resource_typer/   representationjsonloadsr   r!   
media_typerepresentation_definitionget_representation_definition)r1   rB   urlresource_typerV   rY   representation_needs_processingrZ   	__class__r   r   rC      s0    

zResource.__init__c                 C   s   | j S )z Return the URL to this resource.)rS   rP   r   r   r   r\   )  s    zResource.urlc                 C   sb   | j dkrdS | j jd}|dk	r(|S | j jd}|dk	r^t| jj }t|d | S dS )z@Return the URL to the type definition for this resource, if any.NtyperO   #)r/   r&   r'   r   rB   
markup_urlZensureSlashstr)r1   r\   Ztype_idbaser   r   r   type_url.  s    
zResource.type_urlc                 C   s   | j jd S )zReturn the ID of this resource.rO   )r/   r&   rP   r   r   r   rO   @  s    zResource.idrQ   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   rB   r\   r/   )r1   rV   rY   r^   rZ   r   r   r   bindE  s     zResource.bindc                 C   sH   |  dj}|D ]&}| j}|jd|kr|  S qtd| dS )z<Get a description of one of this resource's representations.ZGET	mediaTypez4No definition for representation with media type %s.N)
get_methodresponserK   r/   r&   r'   r!   )r1   rY   Zdefault_get_responserV   representation_tagr   r   r   r[   [  s    

z&Resource.get_representation_definitionc                 C   sX   |   D ]J}|jdd }|dks2|| 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.
        r5    N)_method_tag_iterr&   r'   lowerr   is_described_by)r1   Zhttp_methodrY   query_paramsZrepresentation_params
method_tagr5   methodr   r   r   ri   e  s    

zResource.get_methodc                 C   s   |  || 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_definitionr2   r1   rY   r   r   r   
parameters  s
    
zResource.parametersc                 C   s   |  || S )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.
        )rs   parameter_namesrt   r   r   r   rv     s
    
zResource.parameter_namesc                 c   s   |   D ]}t| |V  qdS )z6An iterator over the methods defined on this resource.N)rm   r   )r1   rq   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$   r5   N)rs   r/   r0   r   r&   r'   r   )r1   
param_namerY   rJ   rk   r)   r   r   r   get_parameter  s    
zResource.get_parameterc                 C   s   | j dkrtd| jdkr|jdkr4td|j | j |j }|dk	r| |j|j\}}|t	kr|dkrzt
|}W nP tk
r   ztjt|ddd	  }W n tk
r   t|Y nX Y nX |S td
| j dS )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.rQ   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.)rV   r   rY   r%   rM   r5   _dereference_namespacer/   ra   XML_SCHEMA_NS_URIr   r.   datetimetimestrptime)r1   	parameterr3   namespace_urlZ	data_typer   r   r   get_parameter_value  sB    


 zResource.get_parameter_valuec                 C   sD   |dk	r"d|k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:   rl   )splitr'   NS_MAP)r1   r/   r3   	namespacens_mapr   r   r   r   r~     s    
zResource._dereference_namespacec                 C   s   | j j|S )z-Given an ID, find a ResourceType for that ID.)rB   resource_typesr'   rN   r   r   r   rG     s    zResource._definition_factoryc                 C   s   | 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.
        ra   r/   r&   r'   rP   r   r   r   rE     s    zResource._get_definition_urlc                 C   s:   | j dk	r| j }n|dk	r*| |}ntd| S )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.)rV   rZ   rK   r[   r   )r1   rY   rJ   r   r   r   rs     s    
z(Resource._find_representation_definitionc                 c   s(   |   j}|tdD ]
}|V  qdS )z+Iterate over this resource's <method> tags.rr   N)rK   r/   r0   r   )r1   rJ   rq   r   r   r   rm   '  s    
zResource._method_tag_iter)NNTN)rQ   TN)NNNN)N)N)N)N)r   r   r   r    rC   propertyr\   rf   rO   rg   r[   ri   ru   rv   rw   ry   r   r~   rG   rE   rs   rm   __classcell__r   r   r_   r   r      s>        4


   

  
!



0	
#c                   @   sf   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+   rB   r/   )r1   r+   rq   r   r   r   rC   1  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)RequestDefinitionr/   findr   rP   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.rj   )r   r+   r/   r   r   rP   r   r   r   rj   ?  s    zMethod.responsec                 C   s   | j jdS )z)The XML ID of the WADL method definition.rO   r   rP   r   r   r   rO   E  s    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.
        r5   r/   r&   r'   rn   rP   r   r   r   r5   J  s    zMethod.nameNc                 K   s   | j j|f|S )4Return the request URL to use to invoke this method.)r   	build_url)r1   r<   r=   r   r   r   build_request_urlS  s    zMethod.build_request_urlc                 K   s   | j j||f|S )zBuild a representation to be sent when invoking this method.

        :return: A 2-tuple of (media_type, representation).
        )r   rV   )r1   rY   r<   r=   r   r   r   build_representationW  s     zMethod.build_representationc              	   C   s   d}|dk	r$| j |}|dkr$dS |dk	rvt|dkrv| j }|dkrJdS z||j|d W n tk
rt   Y dS X |dkst|dkrdS |dk	r||S | j jD ]8}z||| j	|d W  dS  tk
r   Y qX qd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   r[   r8   r?   rp   r.   ro   representationsr2   r+   )r1   rY   Zquery_valuesZrepresentation_valuesrV   r   r   r   r   ro   `  sL      

 zMethod.is_described_by)N)NN)NNN)r   r   r   r    rC   r   r   rj   rO   r5   r   r   ro   r   r   r   r   r   .  s"   	




  
	  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)rr   r+   rB   r/   )r1   rr   Zrequest_tagr   r   r   rC     s    

zRequestDefinition.__init__c                 C   s   |  dgS )z,Return the query parameters for this method.queryr2   rP   r   r   r   rp     s    zRequestDefinition.query_paramsc                 c   s,   | j tdD ]}t| j| j|V  qd S )NrV   )r/   r0   r   r   rB   r+   )r1   rJ   r   r   r   r     s      z!RequestDefinition.representationsNc                 C   s*   | j D ]}|dks|j|kr|  S qdS )z1Return the appropriate representation definition.N)r   rY   r1   rY   rV   r   r   r   r[     s    

z/RequestDefinition.get_representation_definitionc                 K   s,   |  |}|dkrtd| |j|f|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)r[   	TypeErrorrg   )r1   rY   r<   r=   rJ   r   r   r   rV     s    
z RequestDefinition.representationc                 K   sT   | j | j|f|}| jj}t|dkrPd|kr4d}nd}||tt|  7 }|S )r   r   ?&)r?   rp   r+   r\   r8   r   sorteditems)r1   r<   r=   r>   r\   appendr   r   r   r     s     zRequestDefinition.build_url)N)NN)N)r   r   r   r    rC   r   rp   r   r[   rV   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)rB   r+   r/   headers)r1   r+   Zresponse_tagr   r   r   r   rC     s    zResponseDefinition.__init__c                 c   s2   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.
        rV   N)r   r/   r0   r   r+   rB   )r1   pathrk   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+   r/   )r1   r   r   r   r   rg     s    zResponseDefinition.bindc                 C   sH   | j tdD ]2}|jd|kr|jddkrt| |  S qdS )z,Find a header parameter within the response.r$   r5   r%   headerN)r/   r0   r   r&   r'   r   )r1   rx   r)   r   r   r   ry     s    z ResponseDefinition.get_parameterc                 C   s8   | j dk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%   rM   r'   r5   )r1   r   r   r   r   r     s    

z&ResponseDefinition.get_parameter_valuec                 C   s.   | j dkrdS | D ]}|j|kr|  S qdS )z8Get one of the possible representations of the response.N)r/   rY   r   r   r   r   r[   	  s    


z0ResponseDefinition.get_representation_definition)N)
r   r   r   r    rC   r   rg   ry   r   r[   r   r   r   r   r     s   

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 )N)rR   r   rC   r+   r/   )r1   rB   r+   rk   r_   r   r   rC     s    z!RepresentationDefinition.__init__c                    s   t t| ddg|S )Nr   rz   )rR   r   r2   r1   r+   r_   r   r   r2     s    
 zRepresentationDefinition.paramsc                 C   s   dd |  |D S )z#Return the names of all parameters.c                 S   s   g | ]
}|j qS r   )r5   )r(   r$   r   r   r   r-   !  s     z<RepresentationDefinition.parameter_names.<locals>.<listcomp>r   r   r   r   r   rv     s    z(RepresentationDefinition.parameter_namesc                 C   s   |   jjd S )z4The media type of the representation described here.rh   )rK   r/   r&   rP   r   r   r   rY   #  s    z#RepresentationDefinition.media_typec           	      C   s   t ttjd }d| }ttj}d||  d }|dkrB|S |}d}dt| d d	}tj	||tj
d
svq|d t| }|d7 }qJ|S )z;Make a random boundary that does not appear in `all_parts`.r   z%%0%ddz===============z==Nr   z^--z(--)?$ascii)flags.)r8   reprsysmaxsizerandomZ	randrangereescapeencodesearch	MULTILINErd   )	r1   Z	all_partsZ_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   )r1   bufr   keyr3   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   )r1   r   r   closingr   r   r   _write_boundaryC  s
    

z(RepresentationDefinition._write_boundaryc                 C   s  g }|D ]\}}}t  }|r8d}dt|t|f }nd}dt| }| |dd|fd|fg |rt|tstdt| || nft|t	st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str payload expected: %sz
\r\n|\r|\nNr   r   z"multipart/form-data; boundary="%s"T)r   )ioBytesIOr   r   rT   bytesr   ra   r   rd   r   r   r   r   getvaluer   r9   r   )r1   partsZencoded_partsZ	is_binaryr5   r3   r   ZctypeZcdisplinesliner   Zencoded_partr   r   r   _generate_multipart_formK  sR     


z1RepresentationDefinition._generate_multipart_formc                 K   s   |   }|| j}| j||f|}| j}|dkrDtt| }nz|dkrg }t }	|D ]2}
|	|
j
|	}||	k	rZ||
jdk|
j
|f qZ| |\}}n |dkrt|}ntd| ||fS )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binaryrQ   zUnsupported media type: '%s')rK   r2   r+   r?   rY   r   r   r   objectr'   r5   r   ra   r   rW   dumpsr.   )r1   r<   r=   rJ   r2   r>   rY   docr   Zmissingr$   r3   r   r   r   rg     s.     zRepresentationDefinition.bindc                 C   s   | j j|S )z9Turn a representation ID into a RepresentationDefinition.)rB   representation_definitionsr'   rN   r   r   r   rG     s    z,RepresentationDefinition._definition_factoryc                 C   s   | j jdS )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   rP   r   r   r   rE     s    z,RepresentationDefinition._get_definition_url)F)r   r   r   r    rC   r2   rv   r   rY   r   r   r   r   rg   rG   rE   r   r   r   r_   r   r     s   
	
@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)rB   value_containerr/   )r1   r   r/   r   r   r   rC     s    
zParameter.__init__c                 C   s   | j jdS )zThe name of this parameter.r5   r   rP   r   r   r   r5     s    zParameter.namec                 C   s   | j jdS )zThe style of this parameter.r%   r   rP   r   r   r   r%     s    zParameter.stylec                 C   s   | j jdS )zThe XSD type of this parameter.ra   r   rP   r   r   r   ra     s    zParameter.typec                 C   s   | j jdS )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.
        Zfixedr   rP   r   r   r   r6     s    	zParameter.fixed_valuec                 C   s   | j jdd dkS )z6Whether or not a value for this parameter is required.ZrequiredZfalse)1truer   rP   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   rP   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_tagrP   r   r   r-     s   z%Parameter.options.<locals>.<listcomp>r4   )r/   r0   r   rP   r   rP   r   r7     s    
zParameter.optionsc                 C   s&   | j td}|dk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)r/   r   r   r   )r1   link_tagr   r   r   r     s    	zParameter.linkc                 C   s   | j }|dk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   r.   follow)r1   r   r   r   r   linked_resource  s    
zParameter.linked_resourceN)r   r   r   r    rC   r   r5   r%   ra   r6   r:   r   r7   r   r   r   r   r   r   r     s&   





	

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   r/   )r1   r   r   r   r   r   rC     s    zOption.__init__c                 C   s   | j jdS )Nr3   r   rP   r   r   r   r3     s    zOption.valueN)r   r   r   r    rC   r   r3   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)rR   r   rC   rB   r   r/   )r1   r   r   r_   r   r   rC   (  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
   rK   rP   r   r   r   r   2  s    zLink.followc                 C   s(   z|   }W n tk
r"   Y dS X dS )zCan this link be followed within wadllib?

        wadllib can follow a link if it points to a resource that has
        a WADL definition.
        FT)rE   r
   )r1   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   rB   r   r   r   r'   r/   rN   r   r   r   rG   H  s
     zLink._definition_factoryc                 C   s"   | j jd}|dkrtd|S )z(Find the URL containing the definition .r]   NzIParameter is a link, but not to a resource with a known WADL description.)r/   r&   r'   r
   )r1   ra   r   r   r   rE   N  s    zLink._get_definition_url)r   r   r   r    rC   r   r   r   rG   rE   r   r   r   r_   r   r   !  s   


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)r/   )r1   Zresource_type_tagr   r   r   rC   Z  s    zResourceType.__init__N)r   r   r   r    rC   r   r   r   r   r	   W  s   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k	rht| d|}|| j|< qh| jtdD ]}|jd }t|| j|< qd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	resourcesre   rV   rO   Nr]   )rc   hasattr_from_streamr   _from_stringr   r   r   r&   r'   resource_baser   r   r0   r   r	   )r1   rc   markuprV   rO   rJ   r]   r   r   r   rC   e  s(    
  
zApplication.__init__c                 C   sv   d}d}g }t ||D ]R\}}|dkr4|| q|dkrF|  q|dkr|dkrZ|}|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   ZElementTree)r1   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   )rT   r   r   r   r   r   )r1   r   r   r   r   r     s    

zApplication._from_stringc                 C   s.   |  |}| j|}|dkr*td| |S )z7Retrieve a resource type by the URL of its description.NrD   )rF   r   r'   rH   )r1   Zresource_type_urlrI   r]   r   r   r   rU     s
    
zApplication.get_resource_typec                 C   s^   t | j }d|_|dr,t | }n
||}|j}d|_||krN|S td| dS )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   rc   ZensureNoSlashZfragment
startswithZresolverM   )r1   r\   Z
markup_uriZthis_uriZpossible_xml_idr   r   r   rF     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   r8   r
   r   r   r   )r1   r   Zmatchingr   r   r   get_resource_by_path  s      z Application.get_resource_by_pathN)
r   r   r   r    rC   r   r   rU   rF   r   r   r   r   r   r   b  s    )4r    ra   Z__metaclass____all__r   Zemail.utilsr   r   rW   r   r   r   r   Zurllib.parser   ImportErrorZurllibZxml.etree.cElementTreeZetreeZcElementTreer   Zlazr.urir   r   Zwadllibr   r   Zwadllib.iso_strptimer   r   r   r   r   r   	Exceptionr
   r   r!   r   r"   r#   r@   r   r   r   r   r   r   r   r   r	   r   r   r   r   r   <module>   sh   	
B=  >j9B !]6