B
    &‹d;s  ã               @   s^   d dl Z d dlZddlmZ ddlmZmZ ddddd	d
ddœZe d¡Z	G dd„ deƒZ
dS )é    Né   )ÚJsonSchemaDefinitionException)ÚCodeGeneratorÚenforce_listZNoneTypeÚboolzint, float, DecimalÚintÚstrzlist, tupleÚdict)ÚnullÚbooleanÚnumberÚintegerÚstringÚarrayÚobjectz	(?<!\\)\$c                   s  e Zd ZdddddddœZdi d	f‡ fd
d„	Ze‡ fdd„ƒZdd„ Zdd„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zd"d#„ Zd$d%„ Zd&d'„ Zd(d)„ Zd*d+„ Zd,d-„ Zd.d/„ Zd0d1„ Zd2d3„ Zd4d5„ Zd6d7„ Zd8d9„ Zd:d;„ Zd<d=„ Zd>d?„ Z‡  Z S )@ÚCodeGeneratorDraft04zk^\d{4}-[01]\d-[0-3]\d(t|T)[0-2]\d:[0-5]\d:[0-5]\d(?:\.\d+)?(?:[+-][0-2]\d:[0-5]\d|[+-][0-2]\d[0-5]\d|z|Z)\Zz^[^@]+@[^@]+\.[^@]+\Zzv^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9])\ZzV^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\Zaå  ^(?:(?:[0-9A-Fa-f]{1,4}:){6}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|::(?:[0-9A-Fa-f]{1,4}:){5}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,4}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|(?:(?:[0-9A-Fa-f]{1,4}:){,6}[0-9A-Fa-f]{1,4})?::)\Zz^\w+:(\/?\/?)[^\s]+\Z)z	date-timeÚemailÚhostnameZipv4Zipv6ÚuriNTc                sð   t ƒ  ||¡ || _|| _| j d| jfd| jfd| jfd| j	fd| j
fd| jfd| jfd| jfd	| jfd
| jfd| jfd| jfd| jfd| jfd| jfd| jfd| jfd| jfd| jfd| jfd| jfd| jfd| jfd| jff¡ d| _d S )NÚtypeÚenumÚallOfÚanyOfÚoneOfÚnotÚ	minLengthÚ	maxLengthÚpatternÚformatÚminimumÚmaximumÚ
multipleOfÚminItemsÚmaxItemsÚuniqueItemsÚitemsÚminPropertiesÚmaxPropertiesÚrequiredÚdependenciesÚ
propertiesÚpatternPropertiesÚadditionalPropertiesr   )ÚsuperÚ__init__Ú_custom_formatsÚ_use_defaultZ_json_keywords_to_functionÚupdateÚgenerate_typeÚgenerate_enumÚgenerate_all_ofÚgenerate_any_ofÚgenerate_one_ofÚgenerate_notÚgenerate_min_lengthÚgenerate_max_lengthÚgenerate_patternÚgenerate_formatÚgenerate_minimumÚgenerate_maximumÚgenerate_multiple_ofÚgenerate_min_itemsÚgenerate_max_itemsÚgenerate_unique_itemsÚgenerate_itemsÚgenerate_min_propertiesÚgenerate_max_propertiesÚgenerate_requiredÚgenerate_dependenciesÚgenerate_propertiesÚgenerate_pattern_propertiesÚgenerate_additional_propertiesÚ_any_or_one_of_count)ÚselfÚ
definitionÚresolverÚformatsZuse_default)Ú	__class__© úc/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/fastjsonschema/draft04.pyr.   %   s:    zCodeGeneratorDraft04.__init__c                s   t ƒ j}| j|d< |S )NZcustom_formats)r-   Úglobal_stater/   )rK   Úres)rO   rP   rQ   rR   F   s    
z!CodeGeneratorDraft04.global_statec          
   C   s¶   t | jd ƒ}yd dd„ |D ƒ¡}W n0 tk
rV } ztd |¡ƒ‚W dd}~X Y nX d}d|ksld	|kr‚d
|kr‚dj| jd}|  d||¡ | jdd |¡dd W dQ R X dS )z²
        Validation of type. Can be one type or list of types.

        .. code-block:: python

            {'type': 'string'}
            {'type': ['string', 'number']}
        r   z, c             s   s   | ]}t | V  qd S )N)ÚJSON_TYPE_TO_PYTHON_TYPE)Ú.0ÚtrP   rP   rQ   ú	<genexpr>W   s    z5CodeGeneratorDraft04.generate_type.<locals>.<genexpr>zUnknown type: {}NÚ r   r   r   z  or isinstance({variable}, bool))Úvariablez&if not isinstance({variable}, ({})){}:z{name} must be {}z or )Úrule)	r   Ú_definitionÚjoinÚKeyErrorr   r   Ú	_variableÚlÚexc)rK   ÚtypesZpython_typesr`   ÚextrarP   rP   rQ   r2   L   s    	 z"CodeGeneratorDraft04.generate_typec          	   C   sP   | j d }t|ttfƒs tdƒ‚|  d¡ | jd|  |¡dd W dQ R X dS )z¨
        Means that only value specified in the enum is valid.

        .. code-block:: python

            {
                'enum': ['a', 'b'],
            }
        r   zenum must be an arrayzif {variable} not in {enum}:z{name} must be one of {})rZ   N)r[   Ú
isinstanceÚlistÚtupler   r_   r`   Úe)rK   r   rP   rP   rQ   r3   b   s
    

z"CodeGeneratorDraft04.generate_enumc             C   s.   x(| j d D ]}| j|| j| jdd qW dS )a’  
        Means that value have to be valid by all of those definitions. It's like put it in
        one big definition.

        .. code-block:: python

            {
                'allOf': [
                    {'type': 'number'},
                    {'minimum': 5},
                ],
            }

        Valid values for this definition are 5, 6, 7, ... but not 4 or 'abc' for example.
        r   T)Úclear_variablesN)r[   Úgenerate_func_code_blockr^   Ú_variable_name)rK   Údefinition_itemrP   rP   rQ   r4   r   s    z$CodeGeneratorDraft04.generate_all_ofc             C   sÈ   |  j d7  _ | j }| jd|d xv| jd D ]h}| jd|ddN | jddd	* | j|| j| jd
d | jd|d W dQ R X |  d¡ W dQ R X q.W | jd|dd | jddd W dQ R X dS )a¯  
        Means that value have to be valid by any of those definitions. It can also be valid
        by all of them.

        .. code-block:: python

            {
                'anyOf': [
                    {'type': 'number', 'minimum': 10},
                    {'type': 'number', 'maximum': 5},
                ],
            }

        Valid values for this definition are 3, 4, 5, 10, 11, ... but not 8 for example.
        r   z"{variable}_any_of_count{count} = 0)Úcountr   z&if not {variable}_any_of_count{count}:F)rk   Úoptimizeztry:)rl   T)rg   z#{variable}_any_of_count{count} += 1Nz%except JsonSchemaValueException: passz,{name} cannot be validated by any definition)rZ   )rJ   r_   r[   rh   r^   ri   r`   )rK   rk   rj   rP   rP   rQ   r5   …   s    z$CodeGeneratorDraft04.generate_any_ofc             C   sÎ   |  j d7  _ | j }| jd|d xv| jd D ]h}| jd|ddN | jddd	* | j|| j| jd
d | jd|d W dQ R X |  d¡ W dQ R X q.W | jd|d d}| jd||dd W dQ R X dS )a·  
        Means that value have to be valid by only one of those definitions. It can't be valid
        by two or more of them.

        .. code-block:: python

            {
                'oneOf': [
                    {'type': 'number', 'multipleOf': 3},
                    {'type': 'number', 'multipleOf': 5},
                ],
            }

        Valid values for this definition are 3, 5, 6, ... but not 15 for example.
        r   z"{variable}_one_of_count{count} = 0)rk   r   z&if {variable}_one_of_count{count} < 2:F)rk   rl   ztry:)rl   T)rg   z#{variable}_one_of_count{count} += 1Nz%except JsonSchemaValueException: passz'if {variable}_one_of_count{count} != 1:z9" (" + str({variable}_one_of_count{}) + " matches found)"z.{name} must be valid exactly by one definition)Zappend_to_msgrZ   )rJ   r_   r[   rh   r^   ri   r`   )rK   rk   rj   ZdynamicrP   rP   rQ   r6   £   s    z$CodeGeneratorDraft04.generate_one_ofc          	   C   sº   | j d }|dkr"| jddd n”|dkr.dS |s\|  d| j¡ | jddd W dQ R X nZ| jd	dd
 |  || j| j¡ W dQ R X |  d¡ |  d¡ | jddd W dQ R X dS )aT  
        Means that value have not to be valid by this definition.

        .. code-block:: python

            {'not': {'type': 'null'}}

        Valid values for this definition are 'hello', 42, {} ... but not None.

        Since draft 06 definition can be boolean. False means nothing, True
        means everything is invalid.
        r   Tz{name} must not be there)rZ   FNzif {}:z-{name} must NOT match a disallowed definitionztry:)rl   z%except JsonSchemaValueException: passzelse:)r[   r`   r_   r^   rh   ri   )rK   Znot_definitionrP   rP   rQ   r7   Â   s    

z!CodeGeneratorDraft04.generate_notc          
   C   s^   |   d¡J |  ¡  t| jd tƒs,tdƒ‚|   d¡ | jddd W d Q R X W d Q R X d S )Nzif isinstance({variable}, str):r   zminLength must be a numberz if {variable}_len < {minLength}:z={name} must be longer than or equal to {minLength} characters)rZ   )r_   Úcreate_variable_with_lengthrc   r[   r   r   r`   )rK   rP   rP   rQ   r8   Þ   s    z(CodeGeneratorDraft04.generate_min_lengthc          
   C   s^   |   d¡J |  ¡  t| jd tƒs,tdƒ‚|   d¡ | jddd W d Q R X W d Q R X d S )Nzif isinstance({variable}, str):r   zmaxLength must be a numberz if {variable}_len > {maxLength}:z>{name} must be shorter than or equal to {maxLength} characters)rZ   )r_   rm   rc   r[   r   r   r`   )rK   rP   rP   rQ   r9   æ   s    z(CodeGeneratorDraft04.generate_max_lengthc          
   C   s€   |   d¡l | jd }| dd¡ dd¡}t d|¡}t |¡| j|< |   dt|ƒ¡ | j	d	|dd
 W d Q R X W d Q R X d S )Nzif isinstance({variable}, str):r   ú\z\\ú"z\"z\\Zz-if not REGEX_PATTERNS[{}].search({variable}):z{name} must match pattern {})rZ   )
r_   r[   ÚreplaceÚDOLLAR_FINDERÚsubÚreÚcompileÚ_compile_regexpsÚreprr`   )rK   r   Zsafe_patternZend_of_string_fixed_patternrP   rP   rQ   r:   î   s    
z%CodeGeneratorDraft04.generate_patternc          
   C   s  |   d¡ô | jd }|| jkrr| j| }t|tƒrH|  ||d |¡ qú|   d|¡ | jd|dd W dQ R X nˆ|| jkrš| j| }|  ||d |¡ n`|dkrì| j d	d
d |   d¡ W dQ R X |   d¡ | jddd W dQ R X ntd 	|¡ƒ‚W dQ R X dS )zô
        Means that value have to be in specified format. For example date, email or other.

        .. code-block:: python

            {'format': 'email'}

        Valid value for this definition is user@example.com but not @username
        zif isinstance({variable}, str):r   Z_re_patternz(if not custom_formats["{}"]({variable}):z{name} must be {})rZ   NÚregexztry:F)rl   zre.compile({variable})zexcept Exception:z{name} must be a valid regexzUnknown format: {})
r_   r[   r/   rc   r   Ú_generate_formatr`   ÚFORMAT_REGEXSr   r   )rK   Zformat_Zcustom_formatZformat_regexrP   rP   rQ   r;   ÷   s"    






z$CodeGeneratorDraft04.generate_formatc          	   C   sT   | j d |krP|| jkr(t |¡| j|< |  d|¡ | jd|dd W d Q R X d S )Nr   z.if not REGEX_PATTERNS["{}"].match({variable}):z{name} must be {})rZ   )r[   ru   rs   rt   r_   r`   )rK   Úformat_nameZregexp_nameÚregexprP   rP   rQ   rx     s
    
z%CodeGeneratorDraft04._generate_formatc          
   C   s’   |   d¡~ t| jd tttjfƒs,tdƒ‚| j dd¡r`|   d¡ | j	ddd W d Q R X n$|   d	¡ | j	d
dd W d Q R X W d Q R X d S )Nz1if isinstance({variable}, (int, float, Decimal)):r   zminimum must be a numberZexclusiveMinimumFzif {variable} <= {minimum}:z${name} must be bigger than {minimum})rZ   zif {variable} < {minimum}:z0{name} must be bigger than or equal to {minimum})
r_   rc   r[   r   ÚfloatÚdecimalÚDecimalr   Úgetr`   )rK   rP   rP   rQ   r<     s    z%CodeGeneratorDraft04.generate_minimumc          
   C   s’   |   d¡~ t| jd tttjfƒs,tdƒ‚| j dd¡r`|   d¡ | j	ddd W d Q R X n$|   d	¡ | j	d
dd W d Q R X W d Q R X d S )Nz1if isinstance({variable}, (int, float, Decimal)):r    zmaximum must be a numberZexclusiveMaximumFzif {variable} >= {maximum}:z%{name} must be smaller than {maximum})rZ   zif {variable} > {maximum}:z1{name} must be smaller than or equal to {maximum})
r_   rc   r[   r   r|   r}   r~   r   r   r`   )rK   rP   rP   rQ   r=   *  s    z%CodeGeneratorDraft04.generate_maximumc          
   C   s„   |   d¡p t| jd tttjfƒs,tdƒ‚t| jd tƒrH|   d¡ n
|   d¡ |   d¡ | jddd W d Q R X W d Q R X d S )	Nz1if isinstance({variable}, (int, float, Decimal)):r!   zmultipleOf must be a numberzBquotient = Decimal(repr({variable})) / Decimal(repr({multipleOf}))z$quotient = {variable} / {multipleOf}zif int(quotient) != quotient:z'{name} must be multiple of {multipleOf})rZ   )	r_   rc   r[   r   r|   r}   r~   r   r`   )rK   rP   rP   rQ   r>   5  s    
z)CodeGeneratorDraft04.generate_multiple_ofc          
   C   sf   |   ¡  |  d¡J t| jd tƒs,tdƒ‚|  ¡  |  d¡ | jddd W d Q R X W d Q R X d S )Nzif {variable}_is_list:r"   zminItems must be a numberzif {variable}_len < {minItems}:z-{name} must contain at least {minItems} items)rZ   )Úcreate_variable_is_listr_   rc   r[   r   r   rm   r`   )rK   rP   rP   rQ   r?   B  s    z'CodeGeneratorDraft04.generate_min_itemsc          
   C   sf   |   ¡  |  d¡J t| jd tƒs,tdƒ‚|  ¡  |  d¡ | jddd W d Q R X W d Q R X d S )Nzif {variable}_is_list:r#   zmaxItems must be a numberzif {variable}_len > {maxItems}:z:{name} must contain less than or equal to {maxItems} items)rZ   )r€   r_   rc   r[   r   r   rm   r`   )rK   rP   rP   rQ   r@   K  s    z'CodeGeneratorDraft04.generate_max_itemsc          
   C   sj   | j d }|sdS |  ¡  |  d¡< |  d¡ |  ¡  |  d¡ | jddd W dQ R X W dQ R X dS )a²  
        With Python 3.4 module ``timeit`` recommended this solutions:

        .. code-block:: python

            >>> timeit.timeit("len(x) > len(set(x))", "x=range(100)+range(100)", number=100000)
            0.5839540958404541
            >>> timeit.timeit("len({}.fromkeys(x)) == len(x)", "x=range(100)+range(100)", number=100000)
            0.7094449996948242
            >>> timeit.timeit("seen = set(); any(i in seen or seen.add(i) for i in x)", "x=range(100)+range(100)", number=100000)
            2.0819358825683594
            >>> timeit.timeit("np.unique(x).size == len(x)", "x=range(100)+range(100); import numpy as np", number=100000)
            2.1439831256866455
        r$   Nzif {variable}_is_list:zØdef fn(var): return frozenset(dict((k, fn(v)) for k, v in var.items()).items()) if hasattr(var, "items") else tuple(fn(v) for v in var) if isinstance(var, (dict, list)) else str(var) if isinstance(var, bool) else varzNif {variable}_len > len(set(fn({variable}_x) for {variable}_x in {variable})):z {name} must contain unique items)rZ   )r[   r€   r_   rm   r`   )rK   Zunique_definitionrP   rP   rQ   rA   T  s    
z*CodeGeneratorDraft04.generate_unique_itemsc             C   sú  | j d }|dkrdS |  ¡  |  d¡Æ |  ¡  |dkrd|  d¡ | jddd W dQ R X nˆt|tƒršx†t|ƒD ]z\}}|  d	|¡4 |  d
|¡ |  |d 	| j
|¡d 	| j|¡¡ W dQ R X | jrzt|tƒrzd|krz|  dt|d ƒ¡ qzW d| j krì| j d dkr@|  d	t|ƒ¡ | jddd W dQ R X nX|  dt|ƒ¡B |  | j d d 	| j
¡d 	| j| j
¡¡}|dkrŽ|  d¡ W dQ R X nR|rì|  d¡< |  |d 	| j
¡d 	| j| j
¡¡}|dkrâ|  d¡ W dQ R X W dQ R X dS )aÓ  
        Means array is valid only when all items are valid by this definition.

        .. code-block:: python

            {
                'items': [
                    {'type': 'integer'},
                    {'type': 'string'},
                ],
            }

        Valid arrays are those with integers or strings, nothing else.

        Since draft 06 definition can be also boolean. True means nothing, False
        means everything is invalid.
        r%   TNzif {variable}_is_list:Fzif {variable}:z{name} must not be there)rZ   zif {variable}_len > {}:z!{variable}__{0} = {variable}[{0}]z{}__{}z{}[{}]Údefaultzelse: {variable}.append({})ZadditionalItemsz({name} must contain only specified itemszFfor {variable}_x, {variable}_item in enumerate({variable}[{0}:], {0}):z{}_itemz{}[{{{}_x}}]r   Úpassz;for {variable}_x, {variable}_item in enumerate({variable}):)r[   r€   r_   rm   r`   rc   rd   Ú	enumeraterh   r   r^   ri   r0   r	   rv   Úlen)rK   Zitems_definitionÚidxZitem_definitionrk   rP   rP   rQ   rB   u  sL    




z#CodeGeneratorDraft04.generate_itemsc          
   C   sf   |   ¡  |  d¡J t| jd tƒs,tdƒ‚|  ¡  |  d¡ | jddd W d Q R X W d Q R X d S )Nzif {variable}_is_dict:r&   zminProperties must be a numberz$if {variable}_len < {minProperties}:z7{name} must contain at least {minProperties} properties)rZ   )Úcreate_variable_is_dictr_   rc   r[   r   r   rm   r`   )rK   rP   rP   rQ   rC   µ  s    z,CodeGeneratorDraft04.generate_min_propertiesc          
   C   sf   |   ¡  |  d¡J t| jd tƒs,tdƒ‚|  ¡  |  d¡ | jddd W d Q R X W d Q R X d S )Nzif {variable}_is_dict:r'   zmaxProperties must be a numberz$if {variable}_len > {maxProperties}:zD{name} must contain less than or equal to {maxProperties} properties)rZ   )r†   r_   rc   r[   r   r   rm   r`   )rK   rP   rP   rQ   rD   ¾  s    z,CodeGeneratorDraft04.generate_max_propertiesc          
   C   sx   |   ¡  |  d¡\ t| jd ttfƒs0tdƒ‚|  ¡  |  d¡" | jd|  	| jd ¡dd W d Q R X W d Q R X d S )Nzif {variable}_is_dict:r(   zrequired must be an arrayz6if not all(prop in {variable} for prop in {required}):z!{name} must contain {} properties)rZ   )
r†   r_   rc   r[   rd   re   r   rm   r`   rf   )rK   rP   rP   rQ   rE   Ç  s    z&CodeGeneratorDraft04.generate_requiredc             C   s  |   ¡  |  d¡ ü |  ¡  xì| jd  ¡ D ]Ú\}}t dd|¡}t|tt	fƒsdt
d | j|¡ƒ‚|  d|  |¡¡X |  d|  |¡¡ |  d||  |¡¡ | j|d	 | j|¡d
 | j|  |¡¡dd W dQ R X | jr.t|tƒr.d|kr.|  d|  |¡t|d ƒ¡ q.W W dQ R X dS )a  
        Means object with defined keys.

        .. code-block:: python

            {
                'properties': {
                    'key': {'type': 'number'},
                },
            }

        Valid object is containing key called 'key' and value any number.
        zif {variable}_is_dict:r*   z($[^a-zA-Z]|[^a-zA-Z0-9])rX   z{}[{}] must be objectzif "{}" in {variable}_keys:z{variable}_keys.remove("{}")z#{variable}__{0} = {variable}["{1}"]z{}__{}z{}.{}T)rg   Nr   zelse: {variable}["{}"] = {})r†   r_   Úcreate_variable_keysr[   r%   rs   rr   rc   r	   r   r   r   r^   rf   rh   ri   r0   rv   )rK   ÚkeyZprop_definitionZkey_namerP   rP   rQ   rG   Ð  s"    z(CodeGeneratorDraft04.generate_propertiesc             C   sê   |   ¡  |  d¡Î |  ¡  x*| jd  ¡ D ]\}}t |¡| j|< q,W |  d¡„ x|| jd  ¡ D ]j\}}|  dt|ƒ¡L |  d¡ |  d¡ W dQ R X | j	|d 
| j¡d	 
| j| j¡d
d W dQ R X qdW W dQ R X W dQ R X dS )a4  
        Means object with defined keys as patterns.

        .. code-block:: python

            {
                'patternProperties': {
                    '^x': {'type': 'number'},
                },
            }

        Valid object is containing key starting with a 'x' and value any number.
        zif {variable}_is_dict:r+   z9for {variable}_key, {variable}_val in {variable}.items():z-if REGEX_PATTERNS[{}].search({variable}_key):z%if {variable}_key in {variable}_keys:z&{variable}_keys.remove({variable}_key)Nz{}_valz{}.{{{}_key}}T)rg   )r†   r_   r‡   r[   r%   rs   rt   ru   rv   rh   r   r^   ri   )rK   r   rL   rP   rP   rQ   rH   ñ  s    
z0CodeGeneratorDraft04.generate_pattern_propertiesc             C   sâ   |   ¡  |  d¡Æ |  ¡  | jd }|dks6|i kr:dS |r°t| j di ¡ ¡ ƒ}|  d¡J |  d|¡2 |  d¡ |  |d	 | j	¡d
 | j
| j	¡¡ W dQ R X W dQ R X n$|  d¡ | jddd W dQ R X W dQ R X dS )aŸ  
        Means object with keys with values defined by definition.

        .. code-block:: python

            {
                'properties': {
                    'key': {'type': 'number'},
                }
                'additionalProperties': {'type': 'string'},
            }

        Valid object is containing key called 'key' and it's value any number and
        any other key with any string.
        zif {variable}_is_dict:r,   TNr*   z&for {variable}_key in {variable}_keys:zif {variable}_key not in {}:z1{variable}_value = {variable}.get({variable}_key)z{}_valuez{}.{{{}_key}}zif {variable}_keys:z;{name} must not contain "+str({variable}_keys)+" properties)rZ   )r†   r_   r‡   r[   rd   r   Úkeysrh   r   r^   ri   r`   )rK   Zadd_prop_definitionZproperties_keysrP   rP   rQ   rI     s"    


(z3CodeGeneratorDraft04.generate_additional_propertiesc             C   s
  |   ¡  |  d¡î d}xÔ| jd  ¡ D ]Â\}}|g ks(|dkrBq(d}|  d|  |¡¡Œ |dkrt| jd|dd nlt|tƒrÊx`|D ]@}|  d|  |¡¡$ | jd	|  |¡|  |¡dd W d
Q R X q„W n| j|| j	| j
dd W d
Q R X q(W |rü|  d¡ W d
Q R X d
S )aþ  
        Means when object has property, it needs to have also other property.

        .. code-block:: python

            {
                'dependencies': {
                    'bar': ['foo'],
                },
            }

        Valid object is containing only foo, both bar and foo or none of them, but not
        object with only bar.

        Since draft 06 definition can be boolean or empty array. True and empty array
        means nothing, False means that key cannot be there at all.
        zif {variable}_is_dict:Tr)   Fzif "{}" in {variable}:z{} in {name} must not be there)rZ   zif "{}" not in {variable}:z#{name} missing dependency {} for {}N)rg   r‚   )r†   r_   r[   r%   rf   r`   rc   rd   rh   r^   ri   )rK   Zis_emptyrˆ   ÚvaluesÚvaluerP   rP   rQ   rF   4  s"    

.$z*CodeGeneratorDraft04.generate_dependencies)!Ú__name__Ú
__module__Ú__qualname__ry   r.   ÚpropertyrR   r2   r3   r4   r5   r6   r7   r8   r9   r:   r;   rx   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rG   rH   rI   rF   Ú__classcell__rP   rP   )rO   rQ   r      sB   !	!		!@			!$r   )r}   rs   Ú
exceptionsr   Ú	generatorr   r   rT   rt   rq   r   rP   rP   rP   rQ   Ú<module>   s   
