B
    Afxal6  ã               @   sª   d Z ddlZddlmZ ddlmZ ddlmZmZ ddl	m
Z
mZ ddlmZmZmZmZmZ G d	d
„ d
eƒZG dd„ deƒZG dd„ dƒZeZeZdd„ Zdd„ ZdS )zã
    pint.systems
    ~~~~~~~~~~~~

    Functions and classes related to system definitions and conversions.

    :copyright: 2016 by Pint Authors, see AUTHORS for more details.
    :license: BSD, see LICENSE for more details.
é    Né   )Ú_babel_systems)Úbabel_parse)Ú
DefinitionÚUnitDefinition)ÚDefinitionSyntaxErrorÚRedefinitionError)ÚSharedRegistryObjectÚSourceIteratorÚgetattr_maybe_raiseÚloggerÚto_units_containerc               @   sŠ   e Zd ZdZe d¡Zdd„ Zedd„ ƒZ	dd„ Z
d	d
„ Zdd„ Zdd„ Zedd„ ƒZdd„ Zdd„ Zdd„ Zeefdd„ƒZdd„ ZdS )ÚGroupaÂ  A group is a set of units.

    Units can be added directly or by including other groups.

    Members are computed dynamically, that is if a unit is added to a group X
    all groups that include X are affected.

    The group belongs to one Registry.

    It can be specified in the definition file as::

        @group <name> [using <group 1>, ..., <group N>]
            <definition 1>
            ...
            <definition N>
        @end
    z6@group\s+(?P<name>\w+)\s*(using\s(?P<used_groups>.*))*c             C   sP   || _ tƒ | _tƒ | _tƒ | _| | jj| j < |dkrF| jjd  |¡ d| _dS )a,  
        :param name: Name of the group. If not given, a root Group will be created.
        :type name: str
        :param groups: dictionary like object groups and system.
                        The newly created group will be added after creation.
        :type groups: dict[str | Group]
        ÚrootN)	ÚnameÚsetÚ_unit_namesÚ_used_groupsÚ_used_byÚ	_REGISTRYÚ_groupsÚ
add_groupsÚ_computed_members)Úselfr   © r   ú+lib/python3.7/site-packages/pint/systems.pyÚ__init__0   s    zGroup.__init__c             C   sN   | j dkrHt| jƒ| _ x$|  ¡ D ]\}}|  j |jO  _ q W t| j ƒ| _ | j S )z…Names of the units that are members of the group.

        Calculated to include to all units in all included _used_groups.

        N)r   r   r   Úiter_used_groupsÚmembersÚ	frozenset)r   Ú_Úgroupr   r   r   r   U   s    
zGroup.membersc             C   s.   d| _ | jj}x| jD ]}||  ¡  qW dS )z?Invalidate computed members in this Group and all parent nodes.N)r   r   r   r   Úinvalidate_members)r   Údr   r   r   r   r"   f   s    zGroup.invalidate_membersc             c   sH   t | jƒ}| jj}x0|rB| ¡ }|| }||jO }||| fV  qW d S )N)r   r   r   r   Úpop)r   Úpendingr#   r   r!   r   r   r   r   m   s    

zGroup.iter_used_groupsc             C   s&   x |   ¡ D ]\}}||kr
dS q
W dS )NTF)r   )r   Ú
group_namer   r    r   r   r   Úis_used_groupv   s    zGroup.is_used_groupc             G   s&   x|D ]}| j  |¡ qW |  ¡  dS )zAdd units to group.N)r   Úaddr"   )r   Ú
unit_namesÚ	unit_namer   r   r   Ú	add_units|   s    
zGroup.add_unitsc             C   s
   t | jƒS )N)r   r   )r   r   r   r   Únon_inherited_unit_namesƒ   s    zGroup.non_inherited_unit_namesc             G   s&   x|D ]}| j  |¡ qW |  ¡  dS )zRemove units from group.N)r   Úremover"   )r   r)   r*   r   r   r   Úremove_units‡   s    
zGroup.remove_unitsc             G   sb   | j j}xL|D ]D}|| }| | j¡r8td| j|f ƒ‚| j |¡ |j | j¡ qW |  ¡  dS )zAdd groups to group.z+Cyclic relationship found between %s and %sN)	r   r   r'   r   Ú
ValueErrorr   r(   r   r"   )r   Úgroup_namesr#   r&   Úgrpr   r   r   r   Ž   s    
zGroup.add_groupsc             G   sD   | j j}x.|D ]&}|| }| j |¡ |j | j¡ qW |  ¡  dS )zRemove groups from group.N)r   r   r   r-   r   r   r"   )r   r0   r#   r&   r1   r   r   r   Úremove_groups    s    
zGroup.remove_groupsc             C   sJ  t |ƒ}t|ƒ\}}| j |¡}|dkr4td| ƒ‚| ¡ d  ¡ }| ¡ d }|rntdd„ | d¡D ƒƒ}	nd}	g }
x¬|D ]¤\}}d	|krt	j
||d
}t|tƒsºtdt|ƒ |d‚y||ƒ W n< ttfk
r } z|jdkrî||_|‚W dd}~X Y nX |
 |j¡ q||
 | ¡ ¡ q|W | |ƒ}|j|
Ž  |	rF|j|	Ž  |S )aE  Return a Group object parsing an iterable of lines.

        Parameters
        ----------
        lines : list[str]
            iterable
        define_func : callable
            Function to define a unit in the registry; it must accept a single string as
            a parameter.

        Returns
        -------

        Nz!Invalid Group header syntax: '%s'r   Úused_groupsc             s   s   | ]}|  ¡ V  qd S )N)Ústrip)Ú.0Úar   r   r   ú	<genexpr>Æ   s    z#Group.from_lines.<locals>.<genexpr>ú,r   ú=)Únon_int_typez7Only UnitDefinition are valid inside _used_groups, not )Úlineno)r
   ÚnextÚ
_header_reÚsearchr/   Ú	groupdictr4   ÚtupleÚsplitr   Zfrom_stringÚ
isinstancer   r   Ústrr   r;   Úappendr   r+   r   )ÚclsÚlinesZdefine_funcr:   r;   ÚheaderÚrr   Úgroupsr0   r)   ÚlineZ
definitionÚexr1   r   r   r   Ú
from_lines«   s@    




zGroup.from_linesc             C   s   t | |ƒ | jS )N)r   r   )r   Úitemr   r   r   Ú__getattr__ê   s    
zGroup.__getattr__N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚreÚcompiler=   r   Úpropertyr   r"   r   r'   r+   r,   r.   r   r2   ÚclassmethodÚfloatrL   rN   r   r   r   r   r      s   
%	>r   c               @   sn   e Zd ZdZe d¡Zdd„ Zdd„ Zdd„ Z	e
d	d
„ ƒZdd„ Zdd„ Zdd„ Zdd„ Zeefdd„ƒZdS )ÚSystemaâ  A system is a Group plus a set of base units.

    Members are computed dynamically, that is if a unit is added to a group X
    all groups that include X are affected.

    The System belongs to one Registry.

    It can be specified in the definition file as::

        @system <name> [using <group 1>, ..., <group N>]
            <rule 1>
            ...
            <rule N>
        @end

    The syntax for the rule is:

        new_unit_name : old_unit_name

    where:
        - old_unit_name: a root unit part which is going to be removed from the system.
        - new_unit_name: a non root unit which is going to replace the old_unit.

    If the new_unit_name and the old_unit_name, the later and the colon can be omitted.
    z7@system\s+(?P<name>\w+)\s*(using\s(?P<used_groups>.*))*c             C   s4   || _ i | _tƒ | _tƒ | _d| _| | jj| j < dS )zH
        :param name: Name of the group
        :type name: str
        N)r   Ú
base_unitsr   Úderived_unitsr   r   r   Z_systems)r   r   r   r   r   r     s    zSystem.__init__c             C   s
   t | jƒS )N)Úlistr   )r   r   r   r   Ú__dir__)  s    zSystem.__dir__c             C   s:   t | |ƒ t| j| jd | d ƒ}|d k	r.|S t| j|ƒS )Nr    )r   Úgetattrr   r   )r   rM   Úur   r   r   rN   ,  s
    
zSystem.__getattr__c          
   C   s~   | j j}| jd krxtƒ | _xP| jD ]F}y|  j|| jO  _W q" tk
rf   t d 	|| j
¡¡ Y q"X q"W t| jƒ| _| jS )Nz!Could not resolve {} in System {})r   r   r   r   r   r   ÚKeyErrorr   ZwarningÚformatr   r   )r   r#   r&   r   r   r   r   3  s    
zSystem.membersc             C   s
   d| _ dS )z?Invalidate computed members in this Group and all parent nodes.N)r   )r   r   r   r   r"   G  s    zSystem.invalidate_membersc             G   s   |  j t|ƒO  _ |  ¡  dS )zAdd groups to group.N)r   r   r"   )r   r0   r   r   r   r   K  s    zSystem.add_groupsc             G   s   |  j t|ƒ8  _ |  ¡  dS )zRemove groups from group.N)r   r   r"   )r   r0   r   r   r   r2   Q  s    zSystem.remove_groupsc             C   s0   |r*| j tkr*t| j  }t|ƒ}|j| S | j S )z!translate the name of the system.)r   r   r   Zmeasurement_systems)r   Úlocaler   r   r   r   Úformat_babelW  s
    

zSystem.format_babelc                s¶  t |ƒ}t|ƒ\}}| j |¡}|d kr4td| ƒ‚| ¡ d  ¡ }| ¡ d }|rntdd„ | d¡D ƒƒ}	nd}	i }
g }x|D ]ú\}}| ¡ }d|kr2| d¡\}‰ | ¡ ˆ  ¡  }‰ ˆ t	|ˆ ƒd	 ƒkrÜtd
| ƒ‚t
||ƒd	 | jƒ}ˆ |krtdƒ‚‡ fdd„| ¡ D ƒ}d	|ˆ   ||< ||
ˆ < q‚|}t
||ƒd	 ƒ}t|ƒd	kr\tdƒ‚t|ƒ ¡ \‰ }|d	| i|
ˆ < q‚W | |ƒ}|j|	Ž  |jjf |
Ž | jt|ƒO  _|S )Nz!Invalid System header syntax '%s'r   r3   c             s   s   | ]}|  ¡ V  qd S )N)r4   )r5   r6   r   r   r   r7   o  s    z$System.from_lines.<locals>.<genexpr>r8   )r   ú:r   z>In `%s`, the unit at the right of the `:` must be a root unit.z(Old unit must be a component of new unitc                s"   i | ]\}}|ˆ krd | |“qS )éÿÿÿÿr   )r5   Únew_unitÚvalue)Úold_unitr   r   ú
<dictcomp>”  s   z%System.from_lines.<locals>.<dictcomp>zIThe new base must be a root dimension if not discarded unit is specified.)r
   r<   r=   r>   r/   r?   r4   r@   rA   rC   r   r   ÚitemsÚlenÚdictÚpopitemr   rY   ÚupdaterZ   r   )rE   rF   Zget_root_funcr:   r;   rG   rH   r   rI   r0   Zbase_unit_namesZderived_unit_namesrJ   re   Znew_unit_expandedZnew_unit_dictZold_unit_dictrf   Úsystemr   )rg   r   rL   _  sR    




zSystem.from_linesN)rO   rP   rQ   rR   rS   rT   r=   r   r\   rN   rU   r   r"   r   r2   rb   rV   rW   rL   r   r   r   r   rX   ï   s   
rX   c               @   s$   e Zd Zdd„ Zdd„ Zdd„ ZdS )ÚListerc             C   s
   || _ d S )N)r#   )r   r#   r   r   r   r   ¸  s    zLister.__init__c             C   s   t | j ¡ ƒS )N)r[   r#   Úkeys)r   r   r   r   r\   »  s    zLister.__dir__c             C   s   t | |ƒ | j| S )N)r   r#   )r   rM   r   r   r   rN   ¾  s    
zLister.__getattr__N)rO   rP   rQ   r   r\   rN   r   r   r   r   ro   ·  s   ro   c                s   G ‡ fdd„dt ƒ}|S )Nc                   s   e Zd Z” ZdS )z build_group_class.<locals>.GroupN)rO   rP   rQ   r   r   )Úregistryr   r   r   È  s   r   )Ú_Group)rq   r   r   )rq   r   Úbuild_group_classÇ  s    rs   c                s   G ‡ fdd„dt ƒ}|S )Nc                   s   e Zd Z” ZdS )z"build_system_class.<locals>.SystemN)rO   rP   rQ   r   r   )rq   r   r   rX   Ï  s   rX   )Ú_System)rq   rX   r   )rq   r   Úbuild_system_classÎ  s    ru   )rR   rS   Zbabel_namesr   Úcompatr   Zdefinitionsr   r   Úerrorsr   r   Úutilr	   r
   r   r   r   r   rX   ro   rr   rt   rs   ru   r   r   r   r   Ú<module>	   s   	 V I