ó
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
 y d d l Z Wn e k
 r d d l Z n Xd d l Z d d l m Z d d l Z d d l m Z d d l m Z d d d	 f \ Z Z Z d
 Z e j j d e j j e	 j e  f d     Y Z d e f d     YZ d e f d     YZ  d e f d     YZ! e j j d e f d     Y Z" e# d  Z$ e# d  Z% e# d  Z& e# d  Z' d S(   uF   Managing items of a GIMP image (e.g. layers) in a tree-like structure.i    (   t   absolute_importt   divisiont   print_functiont   unicode_literals(   t   *N(   t   pdbi   (   t   objectfilter(   t   utilsi   u   foldert   ItemTreec           B` sę   e  Z d  Z d e e j j d  Z e	 d    Z
 e	 d    Z d   Z d   Z d   Z d   Z e e e d  Z d	   Z e e e d
  Z e e e d  Z d   Z d   Z d   Z e j d    Z d   Z d   Z RS(   u  Interface to store `gimp.Item` objects in a tree-like structure.
  
  Use one of the subclasses for items of a certain type:
  
    * `LayerTree` for layers,
    
    * `ChannelTree` for channels,
    
    * `VectorTree` for vectors (paths).
  
  Each item in the tree is an `Item` instance. Each item contains `gimp.Item`
  attributes and additional derived attributes.
  
  Items can be directly accessed via their ID or name. Both ID and name are
  unique in the entire tree (GIMP readily ensures that item names are unique).
  
  Item groups (e.g. layer groups) are inserted twice in the tree - as folders
  and as items. Parents of items are always folders.
  
  `ItemTree` is a static data structure, i.e. it does not account for
  modifications, additions or removal of GIMP items by GIMP procedures outside
  this class. To refresh the contents of the tree, create a new `ItemTree`
  instance instead.
  
  Attributes:
  
  * `image` (read-only) - GIMP image to generate item tree from.
  
  * `name` (read-only) - Optional name of the item tree. The name is currently
    used as an identifier of the persistent source for tags in items. See
    `Item.tags` for more information.
  
  * `is_filtered` - If `True`, ignore items that do not match the filter
    (`ObjectFilter`) in this object when iterating.
  
  * `filter` - `ObjectFilter` instance that allows filtering items based on
    rules.
  c         C` s_   | |  _  | |  _ | |  _ | |  _ t j |  j  |  _ t j   |  _	 i  |  _
 |  j   d  S(   N(   t   _imaget   _namet   is_filteredt   _filter_match_typet   pgobjectfiltert   ObjectFiltert   filtert   collectionst   OrderedDictt	   _itemtreet   _itemtree_namest   _build_tree(   t   selft   imaget   nameR   t   filter_match_type(    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt   __init__J   s    					c         C` s   |  j  S(   N(   R	   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR   e   s    c         C` s   |  j  S(   N(   R
   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR   i   s    c         C` s/   y |  j  | SWn t k
 r* |  j | SXd S(   uC  Returns an `Item` object by its ID or original name.
    
    An item's ID is the `Item.raw.ID` attribute. An item's original name is the
    `Item.orig_name` attribute.
    
    To access an item group as a folder, pass a tuple `(ID or name, 'folder')`.
    For example:
        
        item_tree['Frames', 'folder']
    N(   R   t   KeyErrorR   (   R   t
   id_or_name(    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt   __getitem__m   s    c         C` s   | |  j  k p | |  j k S(   uŃ   Returns `True` if an `Item` object is in the item tree, regardless of
    filters. Return `False` otherwise. The `Item` object is specified by its
    `Item.raw.ID` attribute or its `orig_name` attribute.
    (   R   R   (   R   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt   __contains__}   s    c         C` s   t  g  |  D] } | ^ q
  S(   u  Returns the number of items in the tree.
    
    This includes immediate children of the image and nested children. Empty
    item groups (i.e. groups with no children) are excluded.
    
    The returned number of items depends on whether `is_filtered` is `True` or
    `False`.
    (   t   len(   R   t   item(    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt   __len__   s    	c         C` s   |  j  d t d t  S(   u  Iterates over items, excluding folders and empty item groups.
    
    If the `is_filtered` attribute is `False`, iterate over all items. If
    `is_filtered` is `True`, iterate only over items that match the filter.
    
    Yields:
    
    * `item` - The current `Item` object.
    t   with_folderst   with_empty_groups(   t   itert   False(   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt   __iter__   s    
c         c` s»   x“ |  j  j   D]£ } t } | r; | j t k r; t } n  | rq | j t k rq t j | j	  d rq t } n  | r„ | r„ |  j
 r„ |  j j |  r„ t } q„ n  | r | Vq q Wd S(   u  Iterates over items, optionally including folders and empty item groups.
    
    Parameters:
    
    * `with_folders` - If `True`, include folders. Topmost folders are yielded
      first. Items are always yielded after all of its parent folders.
    
    * `with_empty_groups` - If `True`, include empty item groups. Empty item
      groups as folders are still yielded if `with_folders` is `True`.
    
    * `filtered` - If `True` and `is_filtered` attribute is also `True`, iterate
      only over items matching the filter. Set this to `False` if you need to
      iterate over all items.
    
    Yields:
    
    * `item` - The current `Item` object.
    i   N(   R   t   valuest   Truet   typet   TYPE_FOLDERR$   t
   TYPE_GROUPR   t   gimp_item_get_childrent   rawR   R   t   is_match(   R   R!   R"   t   filteredR   t   should_yield_item(    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR#      s    	&	"c         c` s#   x |  j  j   D] } | Vq Wd S(   uĆ   Iterates over all items.
    
    This is equivalent to `iter(with_folders=True, with_empty_groups=True,
    filtered=False)`.
    
    Yields:
    
    * `item` - The current `Item` object.
    N(   R   R&   (   R   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt   iter_allæ   s    
c         C` s   |  j  | | | | d  S(   uÆ   Returns the previous item in the tree.
    
    Depending on the values of parameters, some items may be skipped. For the
    description of the parameters, see `iter()`.
    u   prev(   t
   _prev_next(   R   R   R!   R"   R.   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt   prevĢ   s    c         C` s   |  j  | | | | d  S(   u«   Returns the next item in the tree.
    
    Depending on the values of parameters, some items may be skipped. For the
    description of the parameters, see `iter()`.
    u   next(   R1   (   R   R   R!   R"   R.   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt   nextŌ   s    c         C` sļ   | } xā t  rź t | |  } | d  k r. Pn  | rJ | j t k r_ Pq_ n | j t k r_ q	 n  | r | j t k r¾ t j | j  d r¾ Pq¾ n, | j t k r¾ t j | j  d r¾ q	 n  | rę |  j	 rę |  j
 j |  rē Pqē q	 Pq	 W| S(   Ni   (   R'   t   getattrt   NoneR(   R)   R*   R   R+   R,   R   R   R-   (   R   R   R!   R"   R.   t   adjacent_attr_namet   adjacent_item(    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR1   Ü   s,    	c         C` s   t  j |  j  |  _ d S(   u7   Resets the filter, creating a new empty `ObjectFilter`.N(   R   R   R   R   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt   reset_filterż   s    c   	   
   C` sŃ  g  } x¤ |  j  |  j  D] } |  j |  r | j t | t g  g  d  d  |  j   | j t | t g  g  d  d  |  j   q | j t | t	 g  g  d  d  |  j   q W| } g  } x| rG| j
 d  } | j |  | j t k r!| |  j | j j t f <| |  j | j t f <t | j  } | j |  g  } x¤ |  j | j  D] } |  j |  r¹| j t | t | g  d  d  |  j   | j t | t | g  d  d  |  j   qQ| j t | t	 | g  d  d  |  j   qQW| | _ | | _ xJ t |  D] } | j d |  qWq¼ | |  j | j j <| |  j | j <q¼ WxK t d t |  d  D]0 } | | d | | _ | | d | | _ qbWt |  d k rĶ| d | d _ | d | d _ n  d  S(   Ni    i   iž’’’i’’’’(   t   _get_children_from_imageR	   t	   _is_groupt   appendt   ItemR)   R5   R
   R*   t	   TYPE_ITEMt   popR(   R   R,   t   IDt
   FOLDER_KEYR   t	   orig_namet   listt   parentst   _get_children_from_raw_itemt   _orig_childrent   childrent   reversedt   insertt   rangeR   t
   _prev_itemt
   _next_item(	   R   t   child_itemst   raw_itemt	   item_treet	   item_listR   t   parents_for_childt
   child_itemt   i(    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR     sJ    (+,	"%&		 c         C` s   d S(   u   Returns a list of immediate child items from the specified image.
    
    If no child items exist, an empty list is returned.
    N(    (   R   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR9   6  s    c         C` s   | j  S(   uj   Returns a list of immediate child items.
    
    If no child items exist, an empty list is returned.
    (   RF   (   R   RM   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyRD   >  s    c         C` s   t  j |  S(   N(   R   t   gimp_item_is_group(   R   RM   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR:   E  s    N(   t   __name__t
   __module__t   __doc__R5   R'   R   R   t	   MATCH_ALLR   t   propertyR   R   R   R   R    R%   R$   R#   R0   R2   R3   R1   R8   R   t   abct   abstractmethodR9   RD   R:   (    (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR   !   s(   '				$		!		5	t	   LayerTreec           B` s#   e  Z d    Z d   Z d   Z RS(   c         C` s   | j  S(   N(   t   layers(   R   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR9   K  s    c         C` s   | j  S(   N(   R\   (   R   RM   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyRD   N  s    c         C` s   t  | t j  S(   N(   t
   isinstancet   gimpt
   GroupLayer(   R   RM   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR:   Q  s    (   RT   RU   R9   RD   R:   (    (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR[   I  s   		t   ChannelTreec           B` s   e  Z d    Z RS(   c         C` s   | j  S(   N(   t   channels(   R   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR9   W  s    (   RT   RU   R9   (    (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR`   U  s   t
   VectorTreec           B` s   e  Z d    Z RS(   c         C` s   | j  S(   N(   t   vectors(   R   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR9   ]  s    (   RT   RU   R9   (    (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyRb   [  s   R<   c           B` sp  e  Z d  Z d d d d d d  Z e d    Z e d    Z e d    Z e j	 d    Z e d    Z
 e
 j	 d    Z
 e d    Z e d	    Z e d
    Z 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 e d  Z d   Z d   Z d   Z d   Z RS(   u'	  Wrapper for a `gimp.Item` object containing additional attributes.
  
  Note that the attributes will not be up to date if changes were made to the
  original `gimp.Item` object.
  
  Attributes:
  
  * `raw` (read-only) - Underlying `gimp.Item` object wrapped by this instance.
  
  * `type` (read-only) - Item type - one of the following:
      * `TYPE_ITEM` - regular item
      * `TYPE_GROUP` - item group (item whose raw `gimp.Item` is a group with
        children; this `Item` has no children and acts as a regular item)
      * `TYPE_FOLDER` - item containing children (raw item is a group with
        children)
  
  * `parents` - List of `Item` parents for this item, sorted from the topmost
    parent to the bottommost (immediate) parent.
  
  * `children` - List of `Item` children for this item.
  
  * `depth` (read-only) - Integer indicating the depth of the item in the item
    tree. 0 means the item is at the top level. The greater the depth, the lower
    the item is in the item tree.
  
  * `parent` (read-only) - Immediate `Item` parent of this object.
    If this object has no parent, return `None`.
  
  * `name` - Item name as a string, initially equal to `orig_name`. Modify this
     attribute instead of `gimp.Item.name` to avoid modifying the original item.
  
  * `prev` - Previous `Item` in the `ItemTree`, or `None` if there is no
    previous item.
  
  * `next` - Next `Item` in the `ItemTree`, or `None` if there is no next item.
  
  * `tags` - Set of arbitrary strings attached to the item. Tags can be used for
    a variety of purposes, such as special handling of items with specific tags.
    Tags are stored persistently in the `gimp.Item` object (`item` attribute) as
    parasites. The name of the parasite source is given by the
    `tags_source_name` attribute.
  
  * `orig_name` (read-only) - Original `gimp.Item.name` as a string. This
    attribute may be used to access `Item`s in `ItemTree`.
  
  * `orig_parents` (read-only) - Initial `parents` of this item.
  
  * `orig_children` (read-only) - Initial `children` of this item.
  
  * `orig_tags` (read-only) - Initial `tags` of this item.
  
  * `tags_source_name` - Name of the persistent source for the `tags` attribute.
    Defaults to `'tags'` if `None`. If `type` is `FOLDER`, `'_folder'` is
    appended to `tags_source_name`.
  c         C` s  | d  k r t d   n  | |  _ | |  _ | d  k	 r? | n g  |  _ | d  k	 rZ | n g  |  _ | |  _ | |  _ t j	 | j
  |  _
 t | r | n d |  j  |  _ |  j   |  _ |  j
 |  _ |  j |  _ |  j |  _ t |  j  |  _ d d d d g |  _ g  |  _ d  S(   Nu   item cannot be Noneu   tagsu   nameu   _parentsu	   _childrenu   _tags(   R5   t	   TypeErrort	   _raw_itemt   _typet   _parentst	   _childrenRJ   RK   t   pgutilst   safe_decode_gimpR   t   _get_effective_tags_source_namet   _tags_source_namet
   _load_tagst   _tagst
   _orig_namet   _orig_parentsRE   t   sett
   _orig_tagst   _item_attributest   _saved_states(   R   RM   t	   item_typeRC   RF   t	   prev_itemt	   next_itemt   tags_source_name(    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR     s$    				c         C` s   |  j  S(   N(   Re   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR,   ø  s    c         C` s   |  j  S(   N(   Rf   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR(   ¼  s    c         C` s   |  j  S(   N(   Rg   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyRC   Ą  s    c         C` s   | |  _  d  S(   N(   Rg   (   R   RC   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyRC   Ä  s    c         C` s   |  j  S(   N(   Rh   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyRF   Č  s    c         C` s   | |  _  d  S(   N(   Rh   (   R   RF   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyRF   Ģ  s    c         C` s   t  |  j  S(   N(   R   Rg   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt   depthŠ  s    c         C` s   |  j  r |  j  d Sd  S(   Ni’’’’(   Rg   R5   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt   parentŌ  s    c         C` s   |  j  S(   N(   RJ   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR2   Ų  s    c         C` s   |  j  S(   N(   RK   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR3   Ü  s    c         C` s   |  j  S(   N(   Rn   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt   tagsą  s    c         C` s   |  j  S(   N(   Rl   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyRx   ä  s    c         C` s   |  j  S(   N(   Ro   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyRA   č  s    c         C` s   t  |  j  S(   N(   R#   Rp   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt   orig_parentsģ  s    c         C` s   t  |  j  S(   N(   R#   RE   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt   orig_childrenš  s    c         C` s   t  |  j  S(   N(   R#   Rr   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt	   orig_tagsō  s    c         C` s   t  j |  |  j  S(   N(   Ri   t   stringify_objectRA   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt   __str__ų  s    c         C` s1   t  j |  d j |  j t t |  j   g   S(   Nu    (   Ri   t   reprify_objectt   joinRA   t   strR(   R,   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt   __repr__ū  s    c         ` s'     j  j   f d     j D  d S(   u   Saves the current values of item's attributes that can be modified.
    
    To restore the last saved values, call `pop_state()`.
    c         ` s"   i  |  ] } t    |  |  q S(    (   R4   (   t   .0t	   attr_name(   R   (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pys
   <dictcomp>  s   	 N(   Rt   R;   Rs   (   R   (    (   R   sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt
   push_state’  s    	c         C` sY   y |  j  j   } Wn t k
 r' d SXx* | j   D] \ } } t |  | |  q5 Wd S(   uā   Sets the values of item's attributes to the values from the last call to
    `push_state()`.
    
    Calling `pop_state()` without any saved state (e.g. when `push_state()` has
    never been called before) does nothing.
    N(   Rt   R>   t
   IndexErrort   itemst   setattr(   R   t   saved_statesR   t
   attr_value(    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt	   pop_state  s    c         C` sO   |  j  |  _ t |  j  |  _ t |  j  |  _ | rK t |  j  |  _	 n  d S(   uv   Resets the item's attributes to the values upon its instantiation.
    
    Is `tags` is `True`, also reset tags.
    N(
   Ro   R   RB   Rp   Rg   RE   Rh   Rq   Rr   Rn   (   R   R{   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt   reset  s
    c         C` s1   | |  j  k r d S|  j  j |  |  j   d S(   u   Adds the specified tag to the item.
    
    If the tag already exists, do nothing. The tag is saved to the item
    persistently.
    N(   Rn   t   addt
   _save_tags(   R   t   tag(    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt   add_tag!  s    c         C` sH   | |  j  k r* t d j | |     n  |  j  j |  |  j   d S(   ue   Removes the specified tag from the item.
    
    If the tag does not exist, raise `ValueError`.
    u   tag "{}" not found in {}N(   Rn   t
   ValueErrort   formatt   removeR   (   R   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt
   remove_tag.  s    c         C` s   t  |  j |  j |  j  d S(   u$   Saves tags persistently to the item.N(   t   set_tags_for_raw_itemRe   Rn   Rl   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR   :  s    c         C` s   t  |  j |  j  S(   N(   t   get_tags_from_raw_itemRe   Rl   (   R   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyRm   >  s    N(   RT   RU   RV   R5   R   RX   R,   R(   RC   t   setterRF   Ry   Rz   R2   R3   R{   Rx   RA   R|   R}   R~   R   R   R   R   R$   R   R   R   R   Rm   (    (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR<   a  s8   8							c         C` s`   |  j  t | |   } | rU y t j | j  } Wn t k
 rP t   } n X| St   Sd S(   u„   Obtains a set of tags from a `gimp.Item` instance, i.e. a raw item.
  
  `tags_source_name` is the name of the persistent source (parasite) to obtain
  tags from.
  N(   t   parasite_findRk   t   picklet   loadst   datat	   ExceptionRq   (   RM   t   source_nameRu   t   parasiteR{   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR   B  s    c         C` sU   t  |  | |  | rQ |  j t j t | |  t j t j Bt j	 |    n  d  S(   N(
   t   remove_tags_from_raw_itemt   parasite_attachR^   t   ParasiteRk   t	   gimpenumst   PARASITE_PERSISTENTt   PARASITE_UNDOABLER   t   dumps(   RM   R{   R   Ru   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR   T  s    c         C` s   |  j  t | |   d  S(   N(   t   parasite_detachRk   (   RM   R   Ru   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyR”   _  s    c         C` s    | t  k r |  d t S|  Sd  S(   Nu   _(   R)   R@   (   R   Ru   (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyRk   c  s    ((   RV   t
   __future__R    R   R   R   t   future.builtinst   future.utilst   futureRY   R   t   cPickleR   t   ImportErrorR^   R   R¤   t    R   R   R   Ri   R=   R*   R)   R@   t   python_2_unicode_compatiblet   with_metaclasst   ABCMetat   objectR   R[   R`   Rb   R<   R5   R   R   R”   Rk   (    (    (    sJ   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/pygimplib/itemtree.pyt   <module>   s8   "
(’ (ą                                                                                                                                                                                                                                                           # -*- coding: utf-8 -*-

"""Logging-related classes."""

# NOTE: In order to allow logging errors as early as possible (before plug-in
# initialization):
# * we are breaking the 'all imports at the beginning of module' convention
#   for some modules,
# * the `future` library is not imported in case some modules in the library are
#   not available in the installed Python distribution and would thus cause an
#   `ImportError` to be raised.

from __future__ import absolute_import, division, print_function, unicode_literals

str = unicode

import datetime
import io
import os
import sys
import traceback

from . import _path_dirs


_LOG_MODES = ('none', 'exceptions', 'files', 'gimp_console')

_exception_logger = None


def log_output(
      log_mode,
      log_dirpaths,
      log_stdout_filename,
      log_stderr_filename,
      log_header_title='',
      gimp_console_message_delay_milliseconds=0):
  """
  Enable logging of output.
  
  Parameters:
  
  * `log_mode` - The log mode. Possible values:
    
    * 'none' - Do not log anything.
    
    * 'exceptions' - Only log exceptions to the error log file.
    
    * 'files' - Redirect `stdout` and `stderr` to log files.
    
    * 'gimp_console' - Redirect `stdout` and `stderr` to the GIMP error console.
  
  * `log_dirpaths` - List of directory paths for log files. If the first path is
    invalid or permission to write is denied, subsequent directories are used.
    For the `'gimp_console'` mode, this parameter has no effect.
  
  * `log_stdout_filename` - Filename of the log file to write standard output
    to. Applies to the `'files'` mode only.
  
  * `log_stderr_filename` - Filename of the log file to write error output to.
    Applies to the `'exceptions'` and `'files'` modes only.
  
  * `log_header_title` - Optional title in the log header, written before the
    first output to the log files. Applies to the `'exceptions'` and `'files'`
    modes only.
  
  * `gimp_console_message_delay_milliseconds` - The delay to display messages to
    the GIMP console in milliseconds. Only applies to the `'gimp_console'` mode.
  """
  _restore_orig_state(log_mode)
  
  if log_mode == 'none':
    return
  
  if log_mode == 'exceptions':
    _redirect_exception_output_to_file(
      log_dirpaths, log_stderr_filename, log_header_title)
  elif log_mode == 'files':
    stdout_file = create_log_file(log_dirpaths, log_stdout_filename)
    
    if stdout_file is not None:
      sys.stdout = SimpleLogger(stdout_file, log_header_title)
    
    stderr_file = create_log_file(log_dirpaths, log_stderr_filename)
    
    if stderr_file is not None:
      sys.stderr = SimpleLogger(stderr_file, log_header_title)
  elif log_mode == 'gimp_console':
    from . import pdbutils as pgpdbutils
    
    sys.stdout = pgpdbutils.GimpMessageFile(
      message_delay_milliseconds=gimp_console_message_delay_milliseconds)
    sys.stderr = pgpdbutils.GimpMessageFile(
      message_prefix='Error: ',
      message_delay_milliseconds=gimp_console_message_delay_milliseconds)
  else:
    raise ValueError('invalid log mode "{}"; allowed values: {}'.format(
      log_mode, ', '.join(_LOG_MODES)))


def get_log_header(log_header_title):
  return '\n'.join(('', '=' * 80, log_header_title, str(datetime.datetime.now()), '\n'))


def create_log_file(log_dirpaths, log_filename, mode='a'):
  """
  Create a log file in the first file path that can be written to.
  
  Return the log file upon successful creation, `None` otherwise.
  """
  log_file = None
  
  for log_dirpath in log_dirpaths:
    try:
      _path_dirs.make_dirs(log_dirpath)
    except OSError:
      continue
    
    try:
      log_file = io.open(os.path.join(log_dirpath, log_filename), mode, encoding='utf-8')
    except IOError:
      continue
    else:
      break
  
  return log_file


def _restore_orig_state(log_mode):
  global _exception_logger
  
  for file_ in [_exception_logger, sys.stdout, sys.stderr]:
    if (file_ is not None
        and hasattr(file_, 'close')
        and file_ not in [sys.__stdout__, sys.__stderr__]):
      try:
        file_.close()
      except IOError:
        # An exception could occur for an invalid file descriptor.
        pass
  
  _exception_logger = None
  sys.excepthook = sys.__excepthook__
   
  sys.stdout = sys.__stdout__
  sys.stderr = sys.__stderr__


def _redirect_exception_output_to_file(log_dirpaths, log_filename, log_header_title):
  global _exception_logger
  
  def create_file_upon_exception_and_log_exception(exc_type, exc_value, exc_traceback):
    global _exception_logger
    
    _exception_log_file = create_log_file(log_dirpaths, log_filename)
    
    if _exception_log_file is not None:
      _exception_logger = SimpleLogger(_exception_log_file, log_header_title)
      log_exception(exc_type, exc_value, exc_traceback)
      
      sys.excepthook = log_exception
    else:
      sys.excepthook = sys.__excepthook__
  
  def log_exception(exc_type, exc_value, exc_traceback):
    global _exception_logger
    
    _exception_logger.write(
      ''.join(traceback.format_exception(exc_type, exc_value, exc_traceback)))
  
  sys.excepthook = create_file_upon_exception_and_log_exception


class SimpleLogger(object):
  """
  This class wraps a file object to write a header before the first output.
  """
  
  def __init__(self, file_, log_header_title):
    self._log_file = file_
    self._log_header_title = log_header_title
  
  def write(self, data):
    if self._log_header_title:
      self._write(get_log_header(self._log_header_title))
    
    self._write(data)
    
    self.write = self._write
  
  def _write(self, data):
    self._log_file.write(str(data))
    self.flush()
  
  def flush(self):
    self._log_file.flush()
  
  def close(self):
    self._log_file.close()


# Original version by Peter Otten:
# http://mail.python.org/pipermail/python-list/2007-May/438106.html
class Tee(object):
  """
  This class copies `stdout` or `stderr` output to a specified file,
  much like the Unix `tee` command.
  
  This class acts as a file-like object containing the `write()` and `flush()`
  methods.
  
  Attributes:
  
  * `stream` - Either `sys.stdout` or `sys.stderr`. Other objects are invalid
    and raise `ValueError`.
    
  * `log_header_title` - Header text to write when writing into the file
    for the first time.
  """
  
  def __init__(
        self, stream, file_, log_header_title=None, start=True, flush_output=False):
    """
    Parameters:
    
    * `file_` - File or file-like object to write to.
    
    * `start` - If `True`, start `Tee` upon instantiation. To start later, pass
      `start=False` and call `start()` when desired.
    
    * `flush_output` - If `True`, flush output after each write.
    """
    self._streams = {sys.stdout: 'stdout', sys.stderr: 'stderr'}
    
    self.log_header_title = log_header_title if log_header_title is not None else ''
    self.flush_output = flush_output
    
    self._file = None
    self._is_running = False
    
    self._orig_stream = None
    self._stream_name = ''
    self._stream = None
    
    self.stream = stream
    
    if start:
      self.start(file_)
  
  def __del__(self):
    if self.is_running():
      self.stop()
  
  @property
  def stream(self):
    return self._stream
  
  @stream.setter
  def stream(self, value):
    self._stream = value
    if value in self._streams:
      self._stream_name = self._streams[value]
    else:
      raise ValueError('invalid stream; must be sys.stdout or sys.stderr')
  
  def start(self, file_):
    """
    Start `Tee` if not started during the object instantiation.
    
    Parameters:
    
    * `file_` - File or file-like object to write to.
    """
    self._orig_stream = self.stream
    setattr(sys, self._stream_name, self)
    
    self._file = file_
    self._is_running = True
  
  def stop(self):
    """
    Stop `Tee`, i.e. stop writing to the file.
    """
    setattr(sys, self._stream_name, self._orig_stream)
    self._file.close()
    
    self._file = None
    self._is_running = False
  
  def is_running(self):
    """
    Return `True` if `Tee` is running (i.e. writing to file), `False` otherwise.
    """
    return self._is_running
  
  def write(self, data):
    """
    Write output to the stream and the specified file.
    
    If `log_header_title` is not empty, write the log header before the first
    output.
    """
    if self.log_header_title:
      self._file.write(get_log_header(self.log_header_title))
    
    self._write_with_flush(data)
    
    if not self.flush_output:
      self.write = self._write
    else:
      self.write = self._write_with_flush
  
  def _write(self, data):
    self._file.write(data)
    self._stream.write(data)

  def _write_with_flush(self, data):
    self._file.write(data)
    self._file.flush()
    self._stream.write(data)
    self._stream.flush()
  
  def flush(self):
    self._file.flush()
    self._stream.flush()
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                