B
    Afxa,                 @  s   d Z ddlmZ ddlmZ ddlmZmZmZm	Z	 ddl
mZmZmZmZ ddlmZ ddlmZmZmZ G d	d
 d
ed
dZG dd deZefddddd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ZdS )z
    pint.definitions
    ~~~~~~~~~~~~~~~~

    Functions and classes related to unit definitions.

    :copyright: 2016 by Pint Authors, see AUTHORS for more details.
    :license: BSD, see LICENSE for more details.
    )annotations)
namedtuple)CallableIterableOptionalUnion   )	ConverterLogarithmicConverterOffsetConverterScaleConverter)DefinitionSyntaxError)ParserHelperUnitsContainer_is_dimc               @  s$   e Zd ZdZedd dddZdS )PreprocessedDefinitiona  Splits a definition into the constitutive parts.

    A definition is given as a string with equalities in a single line::

        ---------------> rhs
        a = b = c = d = e
        |   |   |   -------> aliases (optional)
        |   |   |
        |   |   -----------> symbol (use "_" for no symbol)
        |   |
        |   ---------------> value
        |
        -------------------> name

    Attributes
    ----------
    name : str
    value : str
    symbol : str or None
    aliases : tuple of str
    rhs : tuple of str
    str)
definitionreturnc             C  s   | dd\}}| }tdd | dD }|d tdd |dd  D  }}|rl|d |dd  fnd |f\}}|dkrd }td	d |D }| |||||S )
N=r   c             s  s   | ]}|  V  qd S )N)strip).0Zres r   /lib/python3.7/site-packages/pint/definitions.py	<genexpr>4   s    z5PreprocessedDefinition.from_string.<locals>.<genexpr>r   c             S  s   g | ]}|d kr|qS ) r   )r   xr   r   r   
<listcomp>6   s    z6PreprocessedDefinition.from_string.<locals>.<listcomp>_c             S  s   g | ]}|d kr|qS )r   r   )r   r   r   r   r   r   :   s    )splitr   tuple)clsr   name	rhs_partsvaluealiasessymbolr   r   r   from_string/   s    $$z"PreprocessedDefinition.from_stringN)__name__
__module____qualname____doc__classmethodr'   r   r   r   r   r      s   r   z#name symbol aliases value rhs_partsc               @  s   e Zd ZdZdd ZdS )_NotNumericz.Internal exception. Do not expose outside Pintc             C  s
   || _ d S )N)r$   )selfr$   r   r   r   __init__B   s    z_NotNumeric.__init__N)r(   r)   r*   r+   r/   r   r   r   r   r-   ?   s   r-   r   type)snon_int_typec             C  s"   t | |}t|rt| |jS )zTry parse a string into a number (without using eval).

    Parameters
    ----------
    s : str
    non_int_type : type

    Returns
    -------
    Number

    Raises
    ------
    _NotNumeric
        If the string cannot be parsed as a number.
    )r   r'   lenr-   scale)r1   r2   phr   r   r   numeric_parseF   s    r6   c               @  s   e Zd ZdZdddddddZed	d
ddZed	d
ddZee	fddddddZ
edd
ddZedd
ddZed	d
ddZedd
ddZddddd Zed!d
d"d#Zdd
d$d%Zd&S )'
DefinitionaB  Base class for definitions.

    Parameters
    ----------
    name : str
        Canonical name of the unit/prefix/etc.
    symbol : str or None
        A short name or symbol for the definition.
    aliases : iterable of str
        Other names for the unit/prefix/etc.
    converter : callable or Converter or None
    r   zOptional[str]zIterable[str]z$Optional[Union[Callable, Converter]])r"   r&   r%   	converterc             C  s2   t |trtd|| _|| _t|| _|| _d S )NzPThe converter parameter cannot be an instance of `str`. Use `from_string` method)
isinstancer   	TypeError_name_symbolr    _aliases
_converter)r.   r"   r&   r%   r8   r   r   r   r/   m   s    

zDefinition.__init__bool)r   c             C  s   | j jS )N)r>   is_multiplicative)r.   r   r   r   r@      s    zDefinition.is_multiplicativec             C  s   | j jS )N)r>   is_logarithmic)r.   r   r   r   rA      s    zDefinition.is_logarithmicz"Union[str, PreprocessedDefinition]r0   z'Definition')r   r2   r   c             C  sl   t |trt|}|jdr,t||S |jdrDt||S |jdr\t	||S t
||S dS )zParse a definition.

        Parameters
        ----------
        definition : str or PreprocessedDefinition
        non_int_type : type

        Returns
        -------
        Definition or subclass of Definition
        z@alias [-N)r9   r   r   r'   r"   
startswithAliasDefinitionDimensionDefinitionendswithPrefixDefinitionUnitDefinition)r!   r   r2   r   r   r   r'      s    

zDefinition.from_stringc             C  s   | j S )N)r;   )r.   r   r   r   r"      s    zDefinition.namec             C  s   | j p
| jS )N)r<   r;   )r.   r   r   r   r&      s    zDefinition.symbolc             C  s
   t | jS )N)r?   r<   )r.   r   r   r   
has_symbol   s    zDefinition.has_symbolc             C  s   | j S )N)r=   )r.   r   r   r   r%      s    zDefinition.aliasesNone)aliasr   c               s&   t  fdd|D } j|  _d S )Nc             3  s   | ]}| j kr|V  qd S )N)r=   )r   a)r.   r   r   r      s    z)Definition.add_aliases.<locals>.<genexpr>)r    r=   )r.   rL   r   )r.   r   add_aliases   s    zDefinition.add_aliasesr	   c             C  s   | j S )N)r>   )r.   r   r   r   r8      s    zDefinition.converterc             C  s   | j S )N)r"   )r.   r   r   r   __str__   s    zDefinition.__str__N)r(   r)   r*   r+   r/   propertyr@   rA   r,   floatr'   r"   r&   rJ   r%   rN   r8   rO   r   r   r   r   r7   _   s   r7   c               @  s*   e Zd ZdZeefddddddZdS )	rH   zDefinition of a prefix::

        <prefix>- = <amount> [= <symbol>] [= <alias>] [ = <alias> ] [...]

    Example::

        deca- =  1e+1  = da- = deka-
    z"Union[str, PreprocessedDefinition]r0   z'PrefixDefinition')r   r2   r   c          
   C  s   t |trt|}tdd |jD }|jr<|jd}n|j}ytt	|j
|}W n: tk
r } ztd|j d|j
 W d d }~X Y nX | |jd|||S )Nc             s  s   | ]}| d V  qdS )rC   N)r   )r   rL   r   r   r   r      s    z/PrefixDefinition.from_string.<locals>.<genexpr>rC   zPrefix definition ('z"') must contain only numbers, not )r9   r   r   r'   r    r%   r&   r   r   r6   r$   r-   
ValueErrorr"   rstrip)r!   r   r2   r%   r&   r8   exr   r   r   r'      s    

(zPrefixDefinition.from_stringN)r(   r)   r*   r+   r,   rQ   r'   r   r   r   r   rH      s   rH   c            	      sN   e Zd ZdZddddddd	d
d fddZeefddddddZ  ZS )rI   a_  Definition of a unit::

        <canonical name> = <relation to another unit or dimension> [= <symbol>] [= <alias>] [ = <alias> ] [...]

    Example::

        millennium = 1e3 * year = _ = millennia

    Parameters
    ----------
    reference : UnitsContainer
        Reference units.
    is_base : bool
        Indicates if it is a base unit.

    NFr   zOptional[str]zIterable[str]r	   zOptional[UnitsContainer]r?   rK   )r"   r&   r%   r8   	referenceis_baser   c               s"   || _ || _t |||| d S )N)rU   rV   superr/   )r.   r"   r&   r%   r8   rU   rV   )	__class__r   r   r/      s    	zUnitDefinition.__init__z"Union[str, PreprocessedDefinition]r0   z'UnitDefinition')r   r2   r   c          
     s  t |trt|}d|jkr|jdd\}}y*t fdddd |dD D }W q tk
r } ztd|j	 d|j W d d }~X Y qX n
|j}i }t
| }tdd | D sd	}n$td
d | D rd}ntdt|}|st|j}nnd|krB|dddkr6t|j|d }n
t|j}n4d|krnd|krnt|j|d |d }ntd| |j	|j|j|||S )N;r   c             3  s$   | ]\}}|  t| fV  qd S )N)r   r6   )r   keyr$   )r2   r   r   r     s   z-UnitDefinition.from_string.<locals>.<genexpr>c             s  s   | ]}| d V  qdS ):N)r   )r   partr   r   r   r     s    zUnit definition ('z.') must contain only numbers in modifier, not c             s  s   | ]}t |V  qd S )N)r   )r   rZ   r   r   r   r     s    Fc             s  s   | ]}t |V  qd S )N)r   )r   rZ   r   r   r   r     s    TzCannot mix dimensions and units in the same definition. Base units must be referenced only to dimensions. Derived units must be referenced only to units.offsetg        ZlogbaseZ	logfactorz(Unable to assign a converter to the unit)r9   r   r   r'   r$   r   dictr-   rR   r"   r   anykeysallr   r   r   r4   getr   r
   r&   r%   )r!   r   r2   r8   	modifiersrT   rV   rU   r   )r2   r   r'      sL    



*
zUnitDefinition.from_string)NF)	r(   r)   r*   r+   r/   r,   rQ   r'   __classcell__r   r   )rX   r   rI      s
     rI   c            	      sN   e Zd ZdZddddddd	d
d fddZeefddddddZ  ZS )rF   zDefinition of a dimension::

        [dimension name] = <relation to other dimensions>

    Example::

        [density] = [mass] / [volume]
    NFr   zOptional[str]zIterable[str]zOptional[Converter]zOptional[UnitsContainer]r?   rK   )r"   r&   r%   r8   rU   rV   r   c               s$   || _ || _t j|||d d d S )N)r8   )rU   rV   rW   r/   )r.   r"   r&   r%   r8   rU   rV   )rX   r   r   r/   K  s    	zDimensionDefinition.__init__z"Union[str, PreprocessedDefinition]r0   z'DimensionDefinition')r   r2   r   c             C  st   t |trt|}t|j|}|s,d}n$tdd | D rHd}ntdt	||d}| |j
|j|j|||S )NTc             s  s   | ]}t |V  qd S )N)r   )r   rZ   r   r   r   r   d  s    z2DimensionDefinition.from_string.<locals>.<genexpr>FzeBase dimensions must be referenced to None. Derived dimensions must only be referenced to dimensions.)r2   )r9   r   r   r'   r   r$   ra   r`   r   r   r"   r&   r%   )r!   r   r2   r8   rV   rU   r   r   r   r'   Y  s"    

zDimensionDefinition.from_string)NF)	r(   r)   r*   r+   r/   r,   rQ   r'   rd   r   r   )rX   r   rF   A  s
     rF   c                  sD   e Zd ZdZdddd fddZeefdd	d d
ddZ  ZS )rE   zAdditional alias(es) for an already existing unit::

        @alias <canonical name or previous alias> = <alias> [ = <alias> ] [...]

    Example::

        @alias meter = my_meter
    r   zIterable[str]rK   )r"   r%   r   c               s   t  j|d |d d d S )N)r"   r&   r%   r8   )rW   r/   )r.   r"   r%   )rX   r   r   r/     s    zAliasDefinition.__init__z"Union[str, PreprocessedDefinition]r0   )r   r2   r   c             C  s:   t |trt|}|jtdd   }t|t|j	S )Nz@alias )
r9   r   r   r'   r"   r3   lstriprE   r    r#   )r!   r   r2   r"   r   r   r   r'     s    

zAliasDefinition.from_string)	r(   r)   r*   r+   r/   r,   rQ   r'   rd   r   r   )rX   r   rE   x  s   rE   N)r+   Z
__future__r   collectionsr   typingr   r   r   r   Z
convertersr	   r
   r   r   errorsr   utilr   r   r   r   	Exceptionr-   rQ   r6   r7   rH   rI   rF   rE   r   r   r   r   <module>	   s   
)`!a7