o
    r|að-  ã                   @   s\   d Z ddlmZ edƒjZG dd„ deƒZeƒ Zdd„ Z	G dd„ deƒZ
G d	d
„ d
eƒZdS )a„  
Exposes a ContextStack class.

The Mustache spec makes a special distinction between two types of context
stack elements: hashes and objects.  For the purposes of interpreting the
spec, we define these categories mutually exclusively as follows:

 (1) Hash: an item whose type is a subclass of dict.

 (2) Object: an item that is neither a hash nor an instance of a
     built-in type.

é    )ÚPystacheErrorc                   @   s   e Zd ZdS )ÚNotFoundN)Ú__name__Ú
__module__Ú__qualname__© r   r   ú2/usr/lib/python3/dist-packages/pystache/context.pyr       s    r   c                 C   sf   t | tƒr|| v r| | S tS t| ƒjtkr1zt| |ƒ}W n
 ty'   Y tS w t|ƒr/|ƒ S |S tS )z¼
    Retrieve a key's value from a context item.

    Returns _NOT_FOUND if the key does not exist.

    The ContextStack.get() docstring documents this function's intended behavior.

    )	Ú
isinstanceÚdictÚtyper   Ú_BUILTIN_MODULEÚgetattrÚAttributeErrorÚcallableÚ
_NOT_FOUND)ÚcontextÚkeyÚattrr   r   r   Ú
_get_value'   s   
	éó	r   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚKeyNotFoundErrorzJ
    An exception raised when a key is not found in a context stack.

    c                 C   s   || _ || _d S )N)r   Údetails)Úselfr   r   r   r   r   Ú__init__X   s   
zKeyNotFoundError.__init__c                 C   s   dt | jƒ| jf S )NzKey %s not found: %s)Úreprr   r   ©r   r   r   r   Ú__str__\   s   zKeyNotFoundError.__str__N)r   r   r   Ú__doc__r   r   r   r   r   r   r   Q   s    r   c                   @   s\   e Zd ZdZdd„ Zdd„ Zedd„ ƒZdd	„ Zd
d„ Z	dd„ Z
dd„ Zdd„ Zdd„ ZdS )ÚContextStacka¾  
    Provides dictionary-like access to a stack of zero or more items.

    Instances of this class are meant to act as the rendering context
    when rendering Mustache templates in accordance with mustache(5)
    and the Mustache spec.

    Instances encapsulate a private stack of hashes, objects, and built-in
    type instances.  Querying the stack for the value of a key queries
    the items in the stack in order from last-added objects to first
    (last in, first out).

    Caution: this class does not currently support recursive nesting in
    that items in the stack cannot themselves be ContextStack instances.

    See the docstrings of the methods of this class for more details.

    c                 G   s   t |ƒ| _dS )aé  
        Construct an instance, and initialize the private stack.

        The *items arguments are the items with which to populate the
        initial stack.  Items in the argument list are added to the
        stack in order so that, in particular, items at the end of
        the argument list are queried first when querying the stack.

        Caution: items should not themselves be ContextStack instances, as
        recursive nesting does not behave as one might expect.

        N)ÚlistÚ_stack)r   Úitemsr   r   r   r   w   s   zContextStack.__init__c                 C   s   d| j jt| jƒf S )zö
        Return a string representation of the instance.

        For example--

        >>> context = ContextStack({'alpha': 'abc'}, {'numeric': 123})
        >>> repr(context)
        "ContextStack({'alpha': 'abc'}, {'numeric': 123})"

        z%s%s)Ú	__class__r   Útupler   r   r   r   r   Ú__repr__†   s   zContextStack.__repr__c                  O   sT   | }t ƒ } |D ]}|du rqt|t ƒr| j |j¡ q|  |¡ q|r(|  |¡ | S )a  
        Build a ContextStack instance from a sequence of context-like items.

        This factory-style method is more general than the ContextStack class's
        constructor in that, unlike the constructor, the argument list
        can itself contain ContextStack instances.

        Here is an example illustrating various aspects of this method:

        >>> obj1 = {'animal': 'cat', 'vegetable': 'carrot', 'mineral': 'copper'}
        >>> obj2 = ContextStack({'vegetable': 'spinach', 'mineral': 'silver'})
        >>>
        >>> context = ContextStack.create(obj1, None, obj2, mineral='gold')
        >>>
        >>> context.get('animal')
        'cat'
        >>> context.get('vegetable')
        'spinach'
        >>> context.get('mineral')
        'gold'

        Arguments:

          *context: zero or more dictionaries, ContextStack instances, or objects
            with which to populate the initial context stack.  None
            arguments will be skipped.  Items in the *context list are
            added to the stack in order so that later items in the argument
            list take precedence over earlier items.  This behavior is the
            same as the constructor's.

          **kwargs: additional key-value data to add to the context stack.
            As these arguments appear after all items in the *context list,
            in the case of key conflicts these values take precedence over
            all items in the *context list.  This behavior is the same as
            the constructor's.

        N)r   r	   r   ÚextendÚpush)r   Úkwargsr    Úitemr   r   r   Úcreate“   s   '

zContextStack.createc                 C   sœ   |dkrz|   ¡ W S  ty   tddƒ‚w | d¡}z	|  |d ¡}W n ty0   t|dƒ‚w |dd… D ]}t||ƒ}|tu rKt|dt|ƒ ƒ‚q7|S )aä
  
        Resolve a dotted name against the current context stack.

        This function follows the rules outlined in the section of the
        spec regarding tag interpolation.  This function returns the value
        as is and does not coerce the return value to a string.

        Arguments:

          name: a dotted or non-dotted name.

          default: the value to return if name resolution fails at any point.
            Defaults to the empty string per the Mustache spec.

        This method queries items in the stack in order from last-added
        objects to first (last in, first out).  The value returned is
        the value of the key in the first item that contains the key.
        If the key is not found in any item in the stack, then the default
        value is returned.  The default value defaults to None.

        In accordance with the spec, this method queries items in the
        stack for a key differently depending on whether the item is a
        hash, object, or neither (as defined in the module docstring):

        (1) Hash: if the item is a hash, then the key's value is the
            dictionary value of the key.  If the dictionary doesn't contain
            the key, then the key is considered not found.

        (2) Object: if the item is an an object, then the method looks for
            an attribute with the same name as the key.  If an attribute
            with that name exists, the value of the attribute is returned.
            If the attribute is callable, however (i.e. if the attribute
            is a method), then the attribute is called with no arguments
            and that value is returned.  If there is no attribute with
            the same name as the key, then the key is considered not found.

        (3) Neither: if the item is neither a hash nor an object, then
            the key is considered not found.

        *Caution*:

          Callables are handled differently depending on whether they are
          dictionary values, as in (1) above, or attributes, as in (2).
          The former are returned as-is, while the latter are first
          called and that value returned.

          Here is an example to illustrate:

          >>> def greet():
          ...     return "Hi Bob!"
          >>>
          >>> class Greeter(object):
          ...     greet = None
          >>>
          >>> dct = {'greet': greet}
          >>> obj = Greeter()
          >>> obj.greet = greet
          >>>
          >>> dct['greet'] is obj.greet
          True
          >>> ContextStack(dct).get('greet')  #doctest: +ELLIPSIS
          <function greet at 0x...>
          >>> ContextStack(obj).get('greet')
          'Hi Bob!'

          TODO: explain the rationale for this difference in treatment.

        Ú.zempty context stackr   z
first parté   Nz
missing %s)ÚtopÚ
IndexErrorr   ÚsplitÚ_get_simpler   r   r   )r   ÚnameÚpartsÚresultÚpartr   r   r   ÚgetÍ   s$   E

ÿ

ÿ
ÿzContextStack.getc                 C   s4   t | jƒD ]}t||ƒ}|tur|  S qt|dƒ‚)z9
        Query the stack for a non-dotted name.

        zpart missing)Úreversedr   r   r   r   )r   r/   r'   r1   r   r   r   r.   2  s   
ÿ
zContextStack._get_simplec                 C   s   | j  |¡ dS )z/
        Push an item onto the stack.

        N)r   Úappend)r   r'   r   r   r   r%   >  s   zContextStack.pushc                 C   s
   | j  ¡ S )z?
        Pop an item off of the stack, and return it.

        )r   Úpopr   r   r   r   r6   E  ó   
zContextStack.popc                 C   s
   | j d S )z;
        Return the item last added to the stack.

        éÿÿÿÿ)r   r   r   r   r   r+   L  r7   zContextStack.topc                 C   s
   t | jŽ S )z2
        Return a copy of this instance.

        )r   r   r   r   r   r   ÚcopyS  r7   zContextStack.copyN)r   r   r   r   r   r#   Ústaticmethodr(   r3   r.   r%   r6   r+   r9   r   r   r   r   r   `   s    
9er   N)r   Zpystache.commonr   r   r   r   Úobjectr   r   r   r   r   r   r   r   r   Ú<module>   s   
*