U
    kuf                     @   sr   d Z ddlZddlZddlZddlmZ ddlmZ ddl	m
Z
 dd Zd	d
 Zdd Zdd ZG dd dZdS )z
JSON Schema URI resolution scopes and dereferencing

https://tools.ietf.org/id/draft-zyp-json-schema-04.html#rfc.section.7

Code adapted from https://github.com/Julian/jsonschema
    N)parse)unquote   )JsonSchemaDefinitionExceptionc                 C   s   |  d|  ddS )z9
    Originally ID was `id` and since v7 it's `$id`.
    $idid )get)schema r   ?/tmp/pip-unpacked-wheel-8kk9cw5n/fastjsonschema/ref_resolver.pyget_id   s    r   c                 C   sz   | d}|rt|dng }|D ]P}|dddd}t| trT| t| } q$|| krf| | } q$td|q$| S )zk
    Return definition from path.

    Path is unescaped according https://tools.ietf.org/html/rfc6901
    /~1~0~zUnresolvable ref: {})	lstripr   splitreplace
isinstancelistintr   format)r
   fragmentpartspartr   r   r   resolve_path   s    


r   c                 C   s   t |  S N)urlparseurlsplitgeturl)urir   r   r   	normalize,   s    r"   c              
   C   s   t | j}||kr"|| | }npddlm} || }|  pDd}zt|	 
|}W n2 tk
r } ztd| |W 5 d}~X Y nX |S )z
    Resolve a remote ``uri``.

    .. note::

        urllib library is used to fetch requests from the remote ``uri``
        if handlers does notdefine otherwise.
    r   )urlopenzutf-8z{} failed to decode: {}N)r   r   schemeurllib.requestr#   infoget_content_charsetjsonloadsreaddecode
ValueErrorr   r   )r!   handlersr$   resultr#   reqencodingexcr   r   r   resolve_remote0   s    	"r2   c                   @   sv   e Zd ZdZi di fddZei fddZeje	ddd	Z
eje	d
ddZdd Zdd ZedddZdS )RefResolverz"
    Resolve JSON References.
    Tc                 C   s2   || _ || _|| _|| _|| _|| _| | dS )a  
        `base_uri` is URI of the referring document from the `schema`.
        `store` is an dictionary that will be used to cache the fetched schemas
        (if `cache=True`).

        Please notice that you can have caching problems when compiling schemas
        with colliding `$ref`. To force overwriting use `cache=False` or
        explicitly pass the `store` argument (with a brand new dictionary)
        N)base_uriresolution_scoper
   storecacher-   walk)selfr4   r
   r6   r7   r-   r   r   r   __init__N   s    
zRefResolver.__init__c                 K   s(   | t |trt|nd|fd|i|S )zA
        Construct a resolver from a JSON schema object.
        r   r-   )r   dictr   )clsr
   r-   kwargsr   r   r   from_schema`   s    zRefResolver.from_schema)scopec                 c   s,   | j }t||| _ z
dV  W 5 || _ X dS )z:
        Context manager to handle current scope.
        N)r5   r   urljoin)r9   r?   Z	old_scoper   r   r   in_scopel   s
    
zRefResolver.in_scope)refc              	   c   s   t | j|}t |\}}|r>t|| jkr>| jt| }n6|rL|| jkrT| j}n t|| j	}| j
rt|| jt|< | j| j }}|| | _| _z&| | t||V  W 5 Q R X W 5 || | _| _X dS )zt
        Context manager which resolves a JSON ``ref`` and enters the
        resolution scope of this ref.
        N)r   r@   r5   	urldefragr"   r6   r4   r
   r2   r-   r7   rA   r   )r9   rB   Znew_urir!   r   r
   Zold_base_uriZ
old_schemar   r   r   	resolvingx   s    zRefResolver.resolvingc                 C   s
   t | jS r   )r"   r5   )r9   r   r   r   get_uri   s    zRefResolver.get_uric                 C   sF   dt | jdddddd }tdd|}| d}|S )zK
        Get current scope and return it as a valid function name.
        Z	validate_r   _r   "r   z($[^a-zA-Z]|[^a-zA-Z0-9]))r   r5   r   resublowerrstrip)r9   namer   r   r   get_scope_name   s    &zRefResolver.get_scope_name)nodec              	   C   s   t |trnd|kr>t |d tr>|d }t| j||d< nd|ksNd|krt t|tr| t|< || jt	| j< |
 D ]\}}t |tr| | qW 5 Q R X n&|
 D ]\}}t |tr| | qdS )zR
        Walk thru schema and dereferencing ``id`` and ``$ref`` instances
        z$refr   r   N)r   boolstrr   r@   r5   r   rA   r6   r"   itemsr;   r8   )r9   rN   rB   rF   itemr   r   r   r8      s    


zRefResolver.walkN)__name__
__module____qualname____doc__r:   classmethodr>   
contextlibcontextmanagerrP   rA   rD   rE   rM   r;   r8   r   r   r   r   r3   H   s   	r3   )rV   rX   r(   rH   urllibr   r   urllib.parser   
exceptionsr   r   r   r"   r2   r3   r   r   r   r   <module>   s   