U
    tdE6                     @   sV   d Z ddlmZ ddlmZ dZG dd dZG dd deZG d	d
 d
e	edZ
dS )a
  Auxiliary classes for the default graph drawer in igraph.

This module contains heavy metaclass magic. If you don't understand
the logic behind these classes, probably you don't need them either.

igraph's default graph drawer uses various data sources to determine
the visual appearance of vertices and edges. These data sources
are the following (in order of precedence):

  - The keyword arguments passed to the L{igraph.plot()} function
    (or to L{igraph.Graph.__plot__()} as a matter of fact, since
    L{igraph.plot()} just passes these attributes on). For instance,
    a keyword argument named C{vertex_label} can be used to set
    the labels of vertices.

  - The attributes of the vertices/edges being drawn. For instance,
    a vertex that has a C{label} attribute will use that label when
    drawn by the default graph drawer.

  - The global configuration of igraph. For instance, if the global
    L{igraph.config.Configuration} instance has a key called
    C{plotting.vertex_color}, that will be used as a default color
    for the vertices.

  - If all else fails, there is a built-in default; for instance,
    the default vertex color is C{"red"}. This is hard-wired in the
    source code.

The logic above can be useful in other graph drawers as well, not
only in the default one, therefore it is refactored into the classes
found in this module. Different graph drawers may inspect different
vertex or edge attributes, hence the classes that collect the attributes
from the various data sources are generated in run-time using a
metaclass called L{AttributeCollectorMeta}. You don't have to use
L{AttributeCollectorMeta} directly, just implement a subclass of
L{AttributeCollectorBase} and it will ensure that the appropriate
metaclass is used. With L{AttributeCollectorBase}, you can use a
simple declarative syntax to specify which attributes you are
interested in. For example::

    class VisualEdgeBuilder(AttributeCollectorBase):
        arrow_size = 1.0
        arrow_width = 1.0
        color = ("black", palette.get)
        width = 1.0

    for edge in VisualEdgeBuilder(graph.es):
        print edge.color

The above class is a visual edge builder -- a class that gives the
visual attributes of the edges of a graph that is specified at
construction time. It specifies that the attributes we are interested
in are C{arrow_size}, C{arrow_width}, C{color} and C{width}; the
default values are also given. For C{color}, we also specify that
a method called {palette.get} should be called on every attribute
value to translate color names to RGB values. For the other three
attributes, C{float} will implicitly be called on all attribute values,
this is inferred from the type of the default value itself.

@see: AttributeCollectorMeta, AttributeCollectorBase
    )NoOptionError)Configuration)AttributeSpecificationAttributeCollectorBasec                   @   s   e Zd ZdZdZdddZdS )r   a  Class that describes how the value of a given attribute should be
    retrieved.

    The class contains the following members:

        - C{name}: the name of the attribute. This is also used when we
          are trying to get its value from a vertex/edge attribute of a
          graph.

        - C{alt_name}: alternative name of the attribute. This is used
          when we are trying to get its value from a Python dict or an
          L{igraph.Configuration} object. If omitted at construction time,
          it will be equal to C{name}.

        - C{default}: the default value of the attribute when none of
          the sources we try can provide a meaningful value.

        - C{transform}: optional transformation to be performed on the
          attribute value. If C{None} or omitted, it defaults to the
          type of the default value.

        - C{func}: when given, this function will be called with an
          index in order to derive the value of the attribute.
    )namealt_namedefault	transformaccessorfuncNc                 C   s|   t |tr|\}}|| _|| _|p$|| _|p.d | _|| _d | _| jrXt| jdsXt	d| jd krx| jd k	rxt
| j| _d S )N__call__ztransform must be callable)
isinstancetupler   r   r   r	   r   r
   hasattr	TypeErrortype)selfr   r   r   r	   r    r   Q/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/igraph/drawing/metamagic.py__init__c   s    


zAttributeSpecification.__init__)NNNN)__name__
__module____qualname____doc__	__slots__r   r   r   r   r   r   G   s   r   c                       s,   e Zd ZdZ fddZedd Z  ZS )AttributeCollectorMetaaY  Metaclass for attribute collector classes

    Classes that use this metaclass are intended to collect vertex/edge
    attributes from various sources (a Python dict, a vertex/edge sequence,
    default values from the igraph configuration and such) in a given
    order of precedence. See the module documentation for more details.
    This metaclass enables the user to use a simple declarative syntax
    to specify which attributes he is interested in. For each vertex/edge
    attribute, a corresponding class attribute must be defined with a
    value that describes the default value of that attribute if no other
    data source provides us with any suitable value. The default value
    can also be a tuple; in that case, the first element of the tuple
    is the actual default value, the second element is a converter
    function that will convert the attribute values to a format expected
    by the caller who uses the class being defined.

    There is a special class attribute called C{_kwds_prefix}; this is
    not used as an attribute declaration. It can contain a string which
    will be used to derive alternative names for the attributes when
    the attribute is accessed in a Python dict. This is useful in many
    situations; for instance, the default graph drawer would want to access
    the vertex colors using the C{color} vertex attribute, but when
    it looks at the keyword arguments passed to the original call of
    L{igraph.Graph.__plot__}, the C{vertex_color} keyword argument should
    be looked up because we also have colors for the edges. C{_kwds_prefix}
    will be prepended to the attribute names when they are looked up in
    a dict of keyword arguments.

    If you require a more fine-tuned behaviour, you can assign an
    L{AttributeSpecification} instance to a class attribute directly.

    @see: AttributeCollectorBase
    c           	         s   g }|  D ]Z\}}|dst|dr*qt|tr:|}n"t|trRt|f|}n
t||}|| q|dd }|r|D ] }|j|j	kr|d||jf |_	q|||d< | 
d| dd |D |d	< t | |||S )
N_r   Z_kwds_prefixz%s%s_attributesz
%s.Elementc                 s   s   | ]}|j V  qd S N)r   ).0	attr_specr   r   r   	<genexpr>   s     z1AttributeCollectorMeta.__new__.<locals>.<genexpr>Element)items
startswithr   r   r   dictappendgetr   r   record_generatorsuper__new__)	mcsr   basesattrsZ
attr_specsattrvaluer    prefix	__class__r   r   r*      s*    


 zAttributeCollectorMeta.__new__c                    s   G  fddd}||_ |S )zBGenerates a simple class that has the given slots and nothing elsec                       s"   e Zd ZdZe ZdddZdS )z8AttributeCollectorMeta.record_generator.<locals>.ElementzYA simple class that holds the attributes collected by the
            attribute collectorr   c                 S   s   |D ]\}}t | || qd S r   )setattr)r   r-   r.   r/   r   r   r   r      s    zAAttributeCollectorMeta.record_generator.<locals>.Element.__init__N)r   )r   r   r   r   r   r   r   r   slotsr   r   r"      s   r"   )r   )r+   r   r5   r"   r   r4   r   r(      s    
z'AttributeCollectorMeta.record_generator)r   r   r   r   r*   classmethodr(   __classcell__r   r   r1   r   r   u   s   "r   c                   @   s4   e Zd ZdZdddZdddZdd Zd	d
 ZdS )r   zBase class for attribute collector subclasses. Classes that inherit
    this class may use a declarative syntax to specify which vertex or edge
    attributes they intend to collect. See L{AttributeCollectorMeta} for
    the details.
    Nc                    sv   | j j  fddtt|D | _|| _|p0i | _| jD ]6}| |}|j	}t
| j|D ]\}}t||| qZq:dS )a  Constructs a new attribute collector that uses the given
        vertex/edge sequence and the given dict as data sources.

        @param seq: an L{igraph.VertexSeq} or L{igraph.EdgeSeq} class
          that will be used as a data source for attributes.
        @param kwds: a Python dict that will be used to override the
          attributes collected from I{seq} if necessary.
        c                    s   g | ]
}  qS r   r   )r   r   eltr   r   
<listcomp>   s     z3AttributeCollectorBase.__init__.<locals>.<listcomp>N)r2   r"   rangelen_cacheseqkwdsr   _collect_attributesr   zipr3   )r   r>   r?   r    values	attr_nameZ	cache_eltvalr   r8   r   r      s    	


zAttributeCollectorBase.__init__c                    sN  | j }| j}t|}|jdkr@|j|kr@||j dkr@dg| S |jdk	rj|jfddt|D S |dkrzt }z||j  W n t	k
r   d Y nX |
|jd rs n\ttrԈg| zt W n tk
r   g| Y nX  fddttD ttr2g| zt W n  tk
r^   g| Y nX tdsttt|k rt|d kr nd|t   qtz|d	|j  }W n tk
r   d}Y nX |dkr|j}ttD ]}| dkr||< q|jdk	rJ|jfd
dD S )aL  Collects graph visualization attributes from various sources.

        This method can be used to collect the attributes required for graph
        visualization from various sources. Attribute value sources are:

          - A specific value of a Python dict belonging to a given key. This dict
            is given by the argument M{self.kwds} at construction time, and
            the name of the key is determined by the argument specification
            given in M{attr_spec}.

          - A vertex or edge sequence of a graph, given in M{self.seq}

          - The global configuration, given in M{config}

          - A default value when all other sources fail to provide the value.
            This is also given in M{attr_spec}.

        @param  attr_spec: an L{AttributeSpecification} object which contains
                           the name of the attribute when it is coming from a
                           list of Python keyword arguments, the name of the
                           attribute when it is coming from the graph attributes
                           directly, the default value of the attribute and an
                           optional callable transformation to call on the values.
                           This can be used to ensure that the attributes are of
                           a given type.
        @param  config:    a L{Configuration} object to be used for determining the
                           defaults if all else fails. If C{None}, the global
                           igraph configuration will be used
        @return: the collected attributes
        labelNc                    s   g | ]} |qS r   r   )r   i)r   r   r   r:     s     z>AttributeCollectorBase._collect_attributes.<locals>.<listcomp>c                    s   g | ]}| p | qS r   r   )r   idx)r-   resultr   r   r:   &  s     extend   r   zplotting.%sc                    s   g | ]} |qS r   r   )r   x)r	   r   r   r:   P  s     )r?   r>   r<   r   r   r   r;   r   instanceKeyErrorr'   r   strr   r   listrI   r   r   r	   )r   r    configr?   r>   nr   rG   r   )r-   r   rH   r	   r   r@      sh    








z*AttributeCollectorBase._collect_attributesc                 C   s
   | j | S )zQReturns the collected attributes of the vertex/edge with the
        given index.)r=   )r   indexr   r   r   __getitem__T  s    z"AttributeCollectorBase.__getitem__c                 C   s
   t | jS r   )r<   r>   )r   r   r   r   __len__Y  s    zAttributeCollectorBase.__len__)N)N)r   r   r   r   r   r@   rS   rT   r   r   r   r   r      s
   

tr   )	metaclassN)r   configparserr   Zigraph.configurationr   __all__r   r   r   objectr   r   r   r   r   <module>   s   >.O