ó
dòôdc           @` s  d  Z  d d l m Z m Z m Z m Z d d l Td d l Z d d l	 Z	 d d l
 Z
 d d l m Z d d l m Z d d	 l m Z d d
 l m Z d d l m Z d d d g Z d „  Z e j j d e j j e j e j e j ƒ f d „  ƒ  Yƒ Z d e f d „  ƒ  YZ d S(   uF   Class that groups settings for easier setting creation and management.i    (   t   absolute_importt   divisiont   print_functiont   unicode_literals(   t   *Ni   (   t   utilsi   (   t   meta(   t	   persistor(   t   settingsu   create_groupsu   Groupu   GroupWalkCallbacksc         C` s^   |  j  d d ƒ } | d k r' g  } n  t |    } x$ | D] } | j t | ƒ g ƒ q: W| S(   u_  
  Create a hierarchy of setting groups (`Group` instances) from a dictionary
  containing attributes for the groups. This function simplifies adding setting
  groups (via `Group.add`).
  
  Groups are specified under the `'groups'` key as a list of dictionaries.
  
  Only `'groups'` and the names of parameters for `Group.__init__` are valid
  keys for `setting_dict`. Other keys raise `TypeError`.
  
  Example:
    settings = create_groups({
      'name': 'main',
      'groups': [
        {
          'name': 'procedures'
        },
        {
          'name': 'constraints'
        }
      ]
    })
  u   groupsN(   t   popt   Nonet   Groupt   addt   create_groups(   t   setting_dictt   group_dictst   groupt
   group_dict(    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyR      s    	R   c           B` sµ  e  Z d  Z d( d( d( d( e d „ Z e d „  ƒ Z e d „  ƒ Z e d „  ƒ Z	 e d „  ƒ Z
 e d „  ƒ Z e d „  ƒ Z d „  Z d	 „  Z d
 „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d( d „ Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d( d „ Z d „  Z d „  Z  d „  Z! d „  Z" d „  Z# d „  Z$ d( e% e% d( d  „ Z& d! „  Z' d" „  Z( d# „  Z) d$ „  Z* d( d% „ Z+ d& „  Z, d' „  Z- RS()   uÏ  
  This class:
  * allows to create a group of related settings (`Setting` objects),
  * allows to store existing setting groups,
  * can perform certain operations on all settings and nested groups at once.
    
  Unless otherwise stated, "settings" in the rest of the documentation for
  this class refers to both `Setting` and `Group` instances.
  
  Attributes:
  
  * `name` (read-only) - A name (string) that uniquely identifies the setting
    group.
  
  * `display_name` (read-only) - Setting group name in human-readable format.
  
  * `description` (read-only) - A more detailed description of the group. By
    default, description is derived from `display_name`.
  
  * `tags` - A set of arbitrary tags attached to the group. Tags can be used to
    e.g. iterate over a specific subset of settings.
  
  * `setting_attributes` (read-only) - Dictionary of (setting attribute: value)
    pairs to assign to each new setting created in the group. Attributes in
    individual settings override these attributes. `setting_attributes` are not
    applied to already created settings that are later added to the group via
    `add()`.
  
  * `recurse_setting_attributes` (read-only) - If `True`, `setting_attributes`
    is recursively applied to child settings of any depth. If a child group
    defines its own `setting_attributes`, it will override its parent's
    `setting_attributes`. If `False`, `setting_attributes` will only be applied
    to immediate child settings.
  c         C` sÁ   t  j j |  ƒ t  j j |  ƒ t  j | ƒ | |  _ t  j | |  j ƒ |  _ t  j | |  j ƒ |  _	 | d  k	 r~ t | ƒ n t ƒ  |  _ | |  _ | |  _ t j ƒ  |  _ g  |  _ d  |  _ d  S(   N(   t   utils_t   SettingParentMixint   __init__t   SettingEventsMixint   check_setting_namet   _namet   get_processed_display_namet   _display_namet   get_processed_descriptiont   _descriptionR
   t   sett   _tagst   _setting_attributest   _recurse_setting_attributest   collectionst   OrderedDictt	   _settingst   _setting_listt   _settings_iterator(   t   selft   namet   display_namet   descriptiont   tagst   setting_attributest   recurse_setting_attributes(    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyR   g   s    	$			c         C` s   |  j  S(   N(   R   (   R%   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyR&   †   s    c         C` s   |  j  S(   N(   R   (   R%   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyR'   Š   s    c         C` s   |  j  S(   N(   R   (   R%   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyR(   Ž   s    c         C` s   |  j  S(   N(   R   (   R%   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyR)   ’   s    c         C` s    |  j  d  k	 r t |  j  ƒ Sd  S(   N(   R   R
   t   dict(   R%   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyR*   –   s    c         C` s   |  j  S(   N(   R   (   R%   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyR+   ›   s    c         C` s   t  j |  |  j ƒ S(   N(   t   pgutilst   stringify_objectR&   (   R%   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyt   __str__Ÿ   s    c         C` s   t  j |  |  j ƒ S(   N(   R-   t   reprify_objectR&   (   R%   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyt   __repr__¢   s    c         C` s^   t  j | k r |  j | ƒ Sy |  j | SWn, t k
 rY t d j | |  j ƒ ƒ ‚ n Xd S(   ux  
    Access the setting or group by its name (string).
    
    If a setting is inside a nested group, you can access the setting as
    follows:
      
      settings['main']['file_extension']
    
    As a more compact alternative, you may specify a setting path:
    
      settings['main/file_extension']
    
    If the name or path does not exist, raise `KeyError`.
    u$   setting "{}" not found in group "{}"N(   R   t   SETTING_PATH_SEPARATORt   _get_setting_from_pathR"   t   KeyErrort   formatR&   (   R%   t   setting_name_or_path(    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyt   __getitem__¥   s    	c         C` sM   t  j | k r< y |  j | ƒ Wn t k
 r4 t SXt Sn | |  j k Sd  S(   N(   R   R2   R3   R4   t   Falset   TrueR"   (   R%   R6   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyt   __contains__½   s    c         C` s§   | j  t j ƒ } |  } xF | d  D]: } | | k rE | j | } q# t d j | | ƒ ƒ ‚ q# Wy | | d } Wn- t k
 r¢ t d j | d | ƒ ƒ ‚ n X| S(   Niÿÿÿÿu&   group "{}" in path "{}" does not existu#   setting "{}" not found in path "{}"(   t   splitR   R2   R"   R4   R5   (   R%   t   setting_patht   setting_path_componentst   current_groupt
   group_namet   setting(    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyR3   È   s    		c         c` s   x |  j  D] } | Vq
 Wd S(   u#  Iterates over child settings or groups.
    
    This method does not iterate over nested groups. Use `walk()` in that case.
    
    By default, the children are iterated in the order they were created or
    added into the group. The order of children can be modified via `reorder()`.
    N(   R#   (   R%   R@   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyt   __iter__Ú   s    c         C` s   t  |  j ƒ S(   N(   t   lenR"   (   R%   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyt   __len__å   s    c         C` s   t  |  j ƒ S(   N(   t   reversedR#   (   R%   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyt   __reversed__è   s    c         C` s   t  j |  | ƒ S(   uw   
    This is a wrapper method for `setting.utils.get_setting_path()`. Consult the
    method for more information.
    (   R   t   get_setting_path(   R%   t   relative_path_group(    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyt   get_pathë   s    c         C` s[   xT | D]L } t  | t j t f ƒ r7 |  j | ƒ } n |  j | ƒ } |  j | ƒ q Wd S(   uQ  
    Add settings to the group.
    
    The order of settings in the list corresponds to the order in which the
    settings are iterated.
    
    `setting_list` is a list that can contain `Setting` objects, `Group`
    instances or dictionaries representing `Setting` objects to be created.
    
    Each dictionary contains (attribute name: value) pairs, where
    `'attribute name'` is a string that represents an argument passed when
    instantiating the setting. The following attributes must always be
    specified:
      * `'type'` - Type of the Setting object to instantiate.
      * `'name'` - Setting name.
    
    The `'name'` attribute must not contain forward slashes (`'/'`) (which are
    used to access settings via paths).
    
    For more attributes, check the documentation of the setting classes. Some
    `Setting` subclasses may require specifying additional required attributes.
    
    Multiple settings with the same name and in different nested groups are
    possible. Each such setting can be accessed like any other:
    
      settings['main/file_extension']
      settings['advanced/file_extension']
    
    Settings created from dictionaries are by default assigned setting
    attributes specified during the initialization of this class. These
    attributes can be overridden by attributes in individual settings.
    N(   t
   isinstancet	   settings_t   SettingR   t   _add_settingt   _create_settingt   _set_as_parent_for_setting(   R%   t   setting_listR@   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyR   ò   s
    !c         C` su   | j  |  j k r- t d j | |  ƒ ƒ ‚ n  | |  k rQ t d j | ƒ ƒ ‚ n  | |  j | j  <|  j j | ƒ | S(   Nu   {} already exists in {}u"   cannot add {} as a child of itself(   R&   R"   t
   ValueErrorR5   R#   t   append(   R%   R@   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyRL     s    c         ` sM  y ˆ  d } Wn) t  k
 r9 t |  j d g ƒ ƒ ‚ n Xt j | ƒ } ‡  f d †  ˆ  Dƒ } y | d Wn) t  k
 r– t |  j d g ƒ ƒ ‚ n Xt j | d k rÌ t d j | d t j ƒ ƒ ‚ n  | d |  j	 k rû t d j | d ƒ ƒ ‚ n  x9 |  j
 ƒ  j ƒ  D]% \ } } | | k r| | | <qqW|  j | | ƒ } | S(   Nu   typec         ` s)   i  |  ] } | d  k r ˆ  | | “ q S(   u   type(    (   t   .0t   key(   t   setting_data(    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pys
   <dictcomp>1  s   	 u   nameu6   setting name "{}" must not contain path separator "{}"u   setting "{}" already exists(   R4   t	   TypeErrort(   _get_missing_required_attributes_messageRJ   t   process_setting_typeR   R2   RP   R5   R"   t   _get_setting_attributest   itemst   _instantiate_setting(   R%   RT   t   setting_typet   setting_data_copyt   setting_attributet   setting_attribute_valueR@   (    (   RT   sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyRM   '  s*    c         C` st   |  j  } | d  k r[ xC t |  j ƒ D]/ } | j s8 Pn  | j d  k	 r% | j } Pq% q% Wn  | d  k rp i  } n  | S(   N(   R   R
   RD   t   parentsR+   R*   (   R%   R*   t   group_or_parent(    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyRX   H  s    				c         C` s   y | |   } WnU t  k
 rg } |  j | | ƒ } | rL |  j | ƒ } n t | ƒ } t  | ƒ ‚ n X| |  j | d <|  j j | ƒ | S(   Nu   name(   RU   t   _get_missing_required_argumentsRV   t   strR"   R#   RQ   (   R%   R[   R\   R@   t   et   missing_required_argumentst   message(    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyRZ   Y  s    c         C` s5   |  j  | j ƒ } g  | D] } | | k r | ^ q S(   N(   t   _get_required_argument_namesR   (   R%   R[   RT   t   required_arg_namest   arg_name(    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyRa   j  s    c         C` sx   t  j | ƒ } | d d  k	 r) | d n g  } t | d ƒ t | ƒ } | d d | !} | d d k rt | d =n  | S(   Ni   i    u   self(   t   inspectt
   getargspecR
   RB   (   R%   t   funct   arg_spect   arg_default_valuest   num_required_argst   required_args(    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyRf   n  s     
c         C` s   d j  d j | ƒ ƒ S(   Nu5   missing the following required setting attributes: {}u   , (   R5   t   join(   R%   t   attribute_names(    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyRV   y  s    c         C` s.   y |  | } Wn t  k
 r" | SX| j Sd S(   u‹   
    Return the value of the setting specified by its name or path. If the
    setting does not exist, return `default_value` instead.
    N(   R4   t   value(   R%   R6   t   default_valueR@   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyt	   get_value}  s
    c         C` sS   t  j ƒ  } x@ | D]8 } |  j | ƒ \ } } t |  | | ƒ } | | | <q W| S(   u  
    Return an ordered dictionary of
    `(setting_name.attribute_name, attribute_value)` key-value pairs given the
    list of `setting_name.attribute_name` elements.
    
    If `attribute_name` is omitted in a list element, the `value` attribute is
    assumed.
    
    If any attribute does not exist, raise `AttributeError`. If any setting does
    not exist, raise `KeyError`. If the key has more than one separator for
    attributes (`setting.utils.SETTING_ATTRIBUTE_SEPARATOR`), raise
    `ValueError`.
    
    Example:
      group.get_attributes([
        'main/file_extension',
        'main/file_extension.display_name'])
    
    returns
      
      {
        'main/file_extension': 'png',
        'main/file_extension.display_name': 'File Extension'
      }
    (   R    R!   t    _get_setting_and_attribute_namest   getattr(   R%   R*   t   setting_attributes_and_valuest   setting_name_and_attributet   setting_namet   attribute_nameRr   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyt   get_attributes‰  s    c         C` s8   t  j g  |  j ƒ  D] } | j d ƒ | j f ^ q ƒ S(   us   
    Return an ordered dictionary of `(setting_name, setting_value)` pairs for
    all settings in this group.
    u   root(   R    R!   t   walkRH   Rr   (   R%   R@   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyt
   get_values®  s    c         C` sy   | j  t j ƒ } t | ƒ d k r3 | } d } n< t | ƒ d k rT | \ } } n t d j | t j ƒ ƒ ‚ | | f S(   Ni   u   valuei   u-   "{}" cannot have more than one "{}" character(   R;   R   t   SETTING_ATTRIBUTE_SEPARATORRB   RP   R5   (   R%   Rx   t   partsRy   Rz   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyRu   ¶  s    		c         C` s2   x+ | j  ƒ  D] \ } } |  | j | ƒ q Wd S(   u5  
    Set values to specified settings via a dictionary of `(setting name, value)`
    key-value pairs.
    
    If any setting does not exist, raise `KeyError`.
    
    Example:
      group.set_values({
        'main/file_extension': 'png',
        'main/output_directory': '/sample/directory',
      })
    N(   RY   t	   set_value(   R%   t   settings_and_valuesRy   Rr   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyt
   set_valuesÃ  s    c         C` s   y |  j  | } Wn& t k
 r9 t d j | ƒ ƒ ‚ n X|  j j | ƒ | d k  ry t t |  j ƒ | d d ƒ } n  |  j j | | ƒ d S(   u8  Reorders a child setting to the new position.
    
    `setting_name` is the name of the child setting.
    
    A negative position functions as an n-th to last position (-1 for last, -2
    for second to last, etc.).
      
    Raises:
    * `ValueError` - `setting_name` does not match any child setting.
    u   setting "{}" not foundi    i   N(   R"   R4   R5   R#   t   removet   maxRB   t   insert(   R%   Ry   t   new_positionR@   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyt   reorderÓ  s    #c         C` sc   x\ | D]T } | |  j  k rF |  j  | } |  j  | =|  j j | ƒ q t d j | ƒ ƒ ‚ q Wd S(   u|   
    Remove settings from the group specified by their names.
    
    If any setting does not exist, raise `KeyError`.
    u   setting "{}" not foundN(   R"   R#   Rƒ   R4   R5   (   R%   t   setting_namesRy   R@   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyRƒ   ê  s    
c         c` s>  | d k r! t j d t ƒ } n  | d k r9 t ƒ  } n  |  g } xõ | r9y | d j ƒ  } WnE t k
 r¦ | d |  k r“ | j | d ƒ n  | j d ƒ qE n Xt	 | t
 ƒ r| | ƒ rð | j d | ƒ | r| j | ƒ | Vqq6| rE | j d | ƒ qE q6qE qE | | ƒ rE | j | ƒ | VqE qE qE Wd S(   u-  
    Return a generator that walks (iterates over) all settings in the group,
    including settings in nested groups. The generator performs a pre-order
    traversal.
    
    If `include_setting_func` is `None`, iterate over all settings. Otherwise,
    `include_setting_func` is a function that should return `True` if a setting
    should be yielded and `False` if a setting should be skipped. The function
    must accept one positional parameter - the current setting or group.
    
    If `include_if_parent_skipped` is `False`, settings or groups within a
    parent group that does not match `include_setting_func` are skipped,
    `True` otherwise. If `True` and `include_groups` is `True`, the parent group
    will still be ignored by `walk_callbacks`.
    
    If `include_groups` is `True`, yield setting groups as well.
    
    `walk_callbacks` is an `GroupWalkCallbacks` instance that invokes additional
    commands during the walk of the group. By default, the callbacks do nothing.
    For more information, see the `GroupWalkCallbacks` class.
    t   return_valuei    N(   R
   R-   t   create_empty_funcR9   t   GroupWalkCallbackst   _nextt   StopIterationt   on_end_group_walkR	   RI   R   R…   t   on_visit_groupt   on_visit_setting(   R%   t   include_setting_funct   include_groupst   include_if_parent_skippedt   walk_callbackst   groupst   setting_or_group(    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyR|   ø  s6    		c         C` sb   |  j  d k r$ t |  j ƒ |  _  n  y t |  j  ƒ } Wn  t k
 rY d |  _  t ‚ n X| Sd S(   uP   
    Return the next element when iterating the settings. Used by `walk()`.
    N(   R$   R
   t   iterR#   t   nextR   (   R%   t   next_element(    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyRŒ   8  s    	
c         C` s4   d „  } x$ |  j  d | ƒ D] } | j ƒ  q Wd S(   u^   
    Reset all settings in this group. Ignore settings with the `'ignore_reset'`
    tag.
    c         S` s   d |  j  k S(   Nu   ignore_reset(   R)   (   R@   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyt   _has_ignore_reset_tagL  s    R‘   N(   R|   t   reset(   R%   Rš   R@   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyR›   G  s    	c         O` s   t  j j |  g | | Ž S(   u  Loads settings in the current group from the specified setting source(s).
    
    See `setting.persistor.Persistor.load()` for information about parameters.
    
    If the `tags` attribute contains `'ignore_load'`, this method will have no
    effect.
    (   t
   persistor_t	   Persistort   load(   R%   t   argst   kwargs(    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyRž   R  s    c         O` s   t  j j |  g | | Ž S(   u  Saves values of settings from the current group to the specified setting
    source(s).
    
    See `setting.persistor.Persistor.save()` for information about parameters.
    
    If the `tags` attribute contains `'ignore_save'`, this method will have no
    effect.
    (   Rœ   R   t   save(   R%   RŸ   R    (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyR¡   \  s    	c         C` s   d „  } | d k r i  } n  x\ |  j d | ƒ D]H } | j d ƒ | k rY | j ƒ  q1 | | j d ƒ } | j | Œ  q1 Wd S(   uÊ  
    Initialize GUI for all settings. Ignore settings with the
    `'ignore_initialize_gui'` tag.
    
    Settings that are not provided with a readily available GUI can have their
    GUI initialized using the `custom_gui` dict. `custom_gui` contains
    (setting name, list of arguments to `setting.Setting.set_gui()`) pairs. The
    'enable GUI update?' boolean in the list is optional and defaults to `True`.
    For more information about parameters in the list, see
    `setting.Setting.set_gui()`.
    
    Example:
    
      file_extension_entry = gtk.Entry()
      ...
      main_settings.initialize_gui({
        'file_extension': [SettingGuiTypes.entry, file_extension_entry]
        ...
      })
    c         S` s   d |  j  k S(   Nu   ignore_initialize_gui(   R)   (   R@   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyt   _should_not_ignore}  s    R‘   u   rootN(   R
   R|   RH   t   set_gui(   R%   t
   custom_guiR¢   R@   t   set_gui_args(    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyt   initialize_guig  s    		c         C` sÀ   d „  } g  } g  } xg |  j  d | ƒ D]S } y | j j ƒ  Wq( t j k
 rz } | j t | ƒ ƒ | j | j ƒ q( Xq( W| r¼ d j | ƒ } t j | d | d d | d | ƒ‚ n  d S(	   u’  
    Apply GUI element values, entered by the user, to settings.
    Ignore settings with the `'ignore_apply_gui_value_to_setting'` tag.
    
    This method will not have any effect on settings with automatic
    GUI-to-setting value updating.
    
    Raises:
    
    * `SettingValueError` - One or more values are invalid. The exception
    message contains messages from all invalid settings.
    c         S` s   d |  j  k S(   Nu!   ignore_apply_gui_value_to_setting(   R)   (   R@   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyR¢   ˜  s    R‘   u   
R@   i    t   messagesR   N(	   R|   t   guit   update_setting_valueRJ   t   SettingValueErrorRQ   Rb   R@   Rp   (   R%   R¢   t   exception_messagest   exception_settingsR@   Rc   t   exception_message(    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyt   apply_gui_values_to_settingsŠ  s     	
c         C` sR   t  |  j ƒ } d | k r2 t | d ƒ | d <n  d | k rN |  j | d <n  | S(   u¬  Returns a dictionary representing the group, appropriate for saving it
    (e.g. via `Group.save()`).
    
    The dictionary contains (attribute name, attribute value) pairs.
    Specifically, the dictionary contains:
    * `name` attribute
    * all keyword argument names and values passed to `__init__()` that were
      used to instantiate the group.
    
    The list of child settings is not provided by this method.
    u   tagsu   name(   R,   t   _dict_on_initt   listR&   (   R%   R   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyt   to_dict­  s    N(.   t   __name__t
   __module__t   __doc__R
   R9   R   t   propertyR&   R'   R(   R)   R*   R+   R/   R1   R7   R:   R3   RA   RC   RE   RH   R   RL   RM   RX   RZ   Ra   Rf   RV   Rt   R{   R}   Ru   R‚   R‡   Rƒ   R8   R|   RŒ   R›   Rž   R¡   R¦   R®   R±   (    (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyR   @   s^   %									)		!						%					;			
	#	#R‹   c           B` s   e  Z d  Z d „  Z RS(   ue  
  This class defines callbacks called during `Group.walk()`. By default, the
  callbacks do nothing.
  
  `on_visit_setting` is called before the current `Setting` object is yielded.
  `on_visit_group` is called before the current `Group` object is yielded.
  `on_end_group_walk` is called after all children of the current `Group` object
  are visited.
  c         C` s(   t  j |  _ t  j |  _ t  j |  _ d  S(   N(   R-   t
   empty_funcR   R   RŽ   (   R%   (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyR   Ð  s    (   R²   R³   R´   R   (    (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyR‹   Å  s   	(   R´   t
   __future__R    R   R   R   t   future.builtinst   future.utilst   futureR    Ri   t    R   R-   R   t   meta_R   Rœ   R   RJ   R   t   __all__R   t   python_2_unicode_compatiblet   with_metaclasst	   GroupMetaR   R   R   t   objectR‹   (    (    (    sO   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/setting/group.pyt   <module>   s(   "
		&	(ÿ ÿ „                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       # -*- coding: utf-8 -*-

"""Metaclasses for settings and mappings of types."""

from __future__ import absolute_import, division, print_function, unicode_literals
from future.builtins import *

import collections
import functools
import inspect
import re
import types

from .. import utils as pgutils


class _TypeMap(object):
  
  def __init__(self, description=None):
    self._description = description
    
    self._name_to_type_map = collections.OrderedDict()
    self._type_to_names_map = collections.defaultdict(list)
  
  def __getitem__(self, type_or_name):
    if isinstance(type_or_name, types.StringTypes):
      try:
        return self._name_to_type_map[type_or_name]
      except KeyError:
        raise TypeError(self._get_error_message(type_or_name))
    else:
      return_all_names = False
      
      if isinstance(type_or_name, (list, tuple)):
        type_ = type_or_name[0]
        if len(type_or_name) > 1:
          return_all_names = type_or_name[1]
      else:
        type_ = type_or_name
      
      if type_ not in self._type_to_names_map:
        raise TypeError(self._get_error_message(type_))
      
      names = self._type_to_names_map[type_]
      
      if return_all_names:
        return names
      else:
        return names[0]
  
  def __contains__(self, key):
    if isinstance(key, types.StringTypes):
      return key in self._name_to_type_map
    else:
      return key in self._type_to_names_map
  
  def __getattr__(self, name):
    try:
      return self._name_to_type_map[name]
    except KeyError:
      raise TypeError(self._get_error_message(name))
  
  def __hasattr__(self, name):
    return name in self._name_to_type_map
  
  def _get_error_message(self, value):
    error_message = 'unrecognized type "{}"'.format(value)
    if self._description:
      error_message += '; are you sure this is a {}?'.format(self._description)
    
    return error_message


SettingTypes = _TypeMap(description='setting type')
SettingGuiTypes = _TypeMap(description='setting GUI type')


class SettingMeta(type):
  """Metaclass for the `setting.Setting` class and its subclasses.
  
  The metaclass is responsible for the following:
  
  * Creating a mapping of `Setting` subclasses and human-readable names for
    easier specification of the `'type'` field when creating settings via
    `setting.Group.add()`.
  
  * Tracking names and values of arguments passed to instantiation of a setting.
    The names and values are then passed to `Setting.to_dict()` to allow
    persisting the setting with the arguments it was instantiated with.
  
  * Ensuring that `Setting` classes documented as abstract cannot be initialized
    (`TypeError` is raised on `__init__()`).
  """
  
  def __new__(mcls, name, bases, namespace):  # @NoSelf
    _handle_abstract_attribute(namespace)
    
    _set_init_wrapper(mcls, namespace)
    
    cls = super(SettingMeta, mcls).__new__(mcls, name, bases, namespace)
    
    _register_type_and_aliases(namespace, cls, name, SettingTypes, 'Setting')
    
    return cls
  
  @staticmethod
  def _get_init_wrapper(orig_init):
    
    @functools.wraps(orig_init)
    def init_wrapper(self, *args, **kwargs):
      if getattr(self, '_ABSTRACT', False):
        raise TypeError('cannot initialize abstract setting class "{}"'.format(
          self.__class__.__name__))
      
      # This check prevents a parent class' `__init__()` from overriding the
      # contents of `_dict_on_init`, which may have different arguments.
      if not hasattr(self, '_dict_on_init'):
        self._dict_on_init = dict(kwargs)
        # Exclude `self` as the first argument
        arg_names = inspect.getargspec(orig_init)[0][1:]
        for arg_name, arg in zip(arg_names, args):
          self._dict_on_init[arg_name] = arg
        
        if inspect.getargspec(orig_init)[1] is not None:
          raise TypeError(
            ('__init__ in Setting subclasses cannot accept variable positional arguments'
             ' (found in "{}")').format(self.__class__.__name__))
      
      orig_init(self, *args, **kwargs)
    
    return init_wrapper


class GroupMeta(type):
  """Metaclass for the `setting.Group` class.
  
  The metaclass is responsible for the following:
  
  * Tracking names and values of arguments passed to instantiation of a group.
    The names and values are then passed to `Group.to_dict()` to allow
    persisting the group with the arguments it was instantiated with.
  """
  
  def __new__(mcls, name, bases, namespace):  # @NoSelf
    _set_init_wrapper(mcls, namespace)
    
    cls = super(GroupMeta, mcls).__new__(mcls, name, bases, namespace)
    
    return cls
  
  @staticmethod
  def _get_init_wrapper(orig_init):
    
    @functools.wraps(orig_init)
    def init_wrapper(self, *args, **kwargs):
      # This check prevents a parent class' `__init__()` from overriding the
      # contents of `_dict_on_init`, which may have different arguments.
      if not hasattr(self, '_dict_on_init'):
        self._dict_on_init = dict(kwargs)
        # Exclude `self` as the first argument
        arg_names = inspect.getargspec(orig_init)[0][1:]
        for arg_name, arg in zip(arg_names, args):
          self._dict_on_init[arg_name] = arg
        
        if inspect.getargspec(orig_init)[1] is not None:
          raise TypeError('Group.__init__() cannot accept variable positional arguments')
      
      orig_init(self, *args, **kwargs)
    
    return init_wrapper


class PresenterMeta(type):
  """Metaclass for the `setting.Presenter` class and its subclasses.
  
  The metaclass is responsible for the following:
  
  * Creating a mapping of `Presenter` subclasses and human-readable names for
    easier specification of the `'gui_type'` field when creating settings via
    `setting.Group.add()`.
  
  * Ensuring that `Presenter` classes documented as abstract cannot be
    initialized (`TypeError` is raised on `__init__()`).
  """
  
  def __new__(mcls, name, bases, namespace):  # @NoSelf
    _handle_abstract_attribute(namespace)
    
    _set_init_wrapper(mcls, namespace)
    
    cls = super(PresenterMeta, mcls).__new__(mcls, name, bases, namespace)
    
    _register_type_and_aliases(namespace, cls, name, SettingGuiTypes, 'Presenter')
    
    return cls
  
  @staticmethod
  def _get_init_wrapper(orig_init):
    
    @functools.wraps(orig_init)
    def init_wrapper(self, *args, **kwargs):
      if getattr(self, '_ABSTRACT', False):
        raise TypeError('cannot initialize abstract presenter class "{}"'.format(
          self.__class__.__name__))
      
      orig_init(self, *args, **kwargs)
    
    return init_wrapper


def _set_init_wrapper(mcls, namespace):
  # Only wrap `__init__` if the (sub)class defines or overrides it.
  # Otherwise, the argument list of `__init__` for a subclass would be
  # overridden the parent class' `__init__` argument list.
  if '__init__' in namespace:
    namespace['__init__'] = mcls._get_init_wrapper(namespace['__init__'])


def _handle_abstract_attribute(namespace):
  if '_ABSTRACT' not in namespace:
    namespace['_ABSTRACT'] = False


def _register_type_and_aliases(namespace, cls, type_name, type_map, base_class_name):
  processed_type_name = pgutils.safe_decode(type_name, 'utf-8')
  human_readable_name = _get_human_readable_class_name(processed_type_name, base_class_name)
  
  if human_readable_name not in type_map._name_to_type_map:
    if not namespace['_ABSTRACT']:
      type_map._name_to_type_map[human_readable_name] = cls
      type_map._type_to_names_map[cls].append(human_readable_name)
      
      if '_ALIASES' in namespace:
        for alias in namespace['_ALIASES']:
          if alias not in type_map._name_to_type_map:
            type_map._name_to_type_map[alias] = cls
          else:
            raise TypeError(
              'alias "{}" matches a {} class name or is already specified'.format(
                alias, base_class_name))
          
          type_map._type_to_names_map[cls].append(alias)
  else:
    raise TypeError(
      'Setting subclass with the name "{}" already exists ({})'.format(
        cls.__name__, type_map._name_to_type_map[human_readable_name]))


def _get_human_readable_class_name(name, suffix_to_strip=None):
  processed_name = name
  
  if suffix_to_strip and processed_name.endswith(suffix_to_strip):
    processed_name = processed_name[:-len(suffix_to_strip)]
  
  # Converts the class name in CamelCase to snake_case.
  # Source: https://stackoverflow.com/a/1176023
  processed_name = re.sub(r'(?<!^)(?=[A-Z])', '_', processed_name).lower()
  
  return processed_name
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                