
    BPcuG                     |   d Z ddlZddlZddlZddlZddlmZmZmZm	Z	m
Z
mZmZmZmZmZmZ ddlmZmZ ddlmZ ddlmZmZ ddlmZmZmZmZmZ dd	lm Z  dd
l!m"Z" ddl#m$Z$ ej%        j&        Z% G d d          Z'ere'Z(ne)Z( G d de(          Z* G d de(          Z+ G d de(          Z, G d de+e,          Z-dS )z?
The ultimate base functionality for every Inkscape extension.
    N)DictListTupleTypeOptionalCallableAnyUnionIOTYPE_CHECKINGcast)ArgumentParser	Namespace)etree   )IBaseElementISVGDocumentElement)filename_argAbortExtensionABORT_STATUSerrormsg
do_nothing)load_svg)NSS)localizec                   d   e Zd ZdZdZi Zd Zd Zd ZddZ	e
d             Ze
d	ee         d
eegef         fd            Zd Ze
d             ZdefdZd Zd Zd Zd Zd Zd Zd Zed d            Zed             Zed!d            Z ed             Z!ed"d            Z"e#d             Z$dS )#InkscapeExtensionzg
    The base class extension, provides argument parsing and basic
    variable handling features.
    Fc                    t          j        | j                   d | _        t	                      | _        d | _        t          | j                  | _	        | j	        
                    dddt          dd            | j	        
                    dt          d d	           |                     | j	                   t                       d S )
N)description
input_file?
INPUT_FILEz-Filename of the input file (default is stdin))nargsmetavartypehelpdefaultz--outputzCOptional output filename for saving the result (default is stdout).)r%   r'   r&   )r   update	extra_nssfile_ior   optionsdocumentr   __doc__
arg_parseradd_argumentr   stradd_argumentsr   selfs    ,/usr/share/inkscape/extensions/inkex/base.py__init__zInkscapeExtension.__init__?   s    
4>""" {{(T\BBB$$ @ 	% 	
 	
 	
 	$$V	 	% 	
 	
 	
 	4?+++




    c                     dS )zAdd any extra arguments to your extension handle, use:

        def add_arguments(self, pars):
            pars.add_argument("--num-cool-things", type=int, default=3)
            pars.add_argument("--pos-in-doc", type=str, default="doobry")
        N )r3   parss     r4   r1   zInkscapeExtension.add_arguments[   s      r6   c                 D    | j                             |          | _        dS )z0Parse the given arguments and set 'self.options'N)r.   
parse_argsr+   )r3   argss     r4   parse_argumentsz!InkscapeExtension.parse_argumentse   s     11$77r6   methodc                       fd}|S )a<  Used by add_argument to match a tab selection with an object method

        pars.add_argument("--tab", type=self.arg_method(), default="foo")
        ...
        self.options.tab(arguments)
        ...
        .. code-block:: python
        .. def method_foo(self, arguments):
        ..     # do something
        c                 2    d|                      d                                                               dd          }	 t          |          S # t          $ r9}|                    d          rt          cY d }~S t          d|           |d }~ww xY w)N_"-zCan not find method )striplowerreplacegetattrAttributeError
startswithr   r   )valuenameerrorprefixr3   s      r4   _innerz,InkscapeExtension.arg_method.<locals>._innerw   s    ==S!1!1!7!7!9!9==EEc3OODOtT***! O O O??3'' &%%%%%%%$%BD%B%BCCNOs$   A 
BB8B>BBr8   )r3   rM   rN   s   `` r4   
arg_methodzInkscapeExtension.arg_methodj   s/    	O 	O 	O 	O 	O 	O r6   c                      d } | S )a  Parses a number descriptor. e.g:
        ``1,2,4-5,7,9-`` is parsed to ``1, 2, 4, 5, 7, 9, 10, ..., lastvalue``

        .. versionadded:: 1.2

        Usage:

        .. code-block:: python

            # in add_arguments()
            pars.add_argument("--pages", type=self.arg_number_ranges(), default=1-)
            # later on, pages is then a list of ints
            pages = self.options.pages(lastvalue)

        c                      ddd fd	S )Nr   c                     t          j        dfd|           } t          t          t          j        d|                     } t          fd| D                       } | S )Nz(\d+|)\s?-\s?(\d+|)c                 ^   |                      d          p|                      d          dk    s}d                    t          t          t	          t          |                      d          p          t          |                      d          p          dz                                 ndS )Nr       ,)groupjoinmapr0   rangeint)m	lastvalue
startvalues    r4   <lambda>zUInkscapeExtension.arg_number_ranges.<locals>._inner.<locals>.method.<locals>.<lambda>   s     GGAJJ4!''!**;; "hh! #AGGAJJ$<* = = #AGGAJJ$;) < <q @      r6   z(\d+)c                      h | ]
}|k    |S r8   r8   ).0ir]   s     r4   	<setcomp>zVInkscapeExtension.arg_number_ranges.<locals>._inner.<locals>.method.<locals>.<setcomp>   s    BBBQ1	>>q>>>r6   )resubrY   r[   findalltuple)pagesr]   r^   s    ``r4   r>   zCInkscapeExtension.arg_number_ranges.<locals>._inner.<locals>.method   sz    *
 
 
 
 
    CHe!<!<==BBBB%BBBCCr6   c                       | |          S )N)r^   r8   )r]   r^   r>   rJ   s     r4   r_   zEInkscapeExtension.arg_number_ranges.<locals>._inner.<locals>.<lambda>   s    66yZ4 4 4 r6   )r   r8   )rJ   r>   s   `@r4   rN   z3InkscapeExtension.arg_number_ranges.<locals>._inner   s;       ,      r6   r8   )rN   s    r4   arg_number_rangesz#InkscapeExtension.arg_number_ranges   s    &	 	 	6 r6   r+   returnc                 "     dt           f fd}|S )aI  Used by add_argument to match an option with a class

        Types to choose from are given by the options list

        .. versionadded:: 1.2

        Usage:

        .. code-block:: python

            pars.add_argument("--class", type=self.arg_class([ClassA, ClassB]),
                              default="ClassA")
        rJ   c                 z    |                      d          }D ]}||j        k    r|c S t          d|           )NrB   zCan not find class )rD   __name__r   )rJ   rK   rb   r+   s      r4   rN   z+InkscapeExtension.arg_class.<locals>._inner   sU    ;;s##D  1:%%HHH & !=t!=!=>>>r6   )r0   )r+   rN   s   ` r4   	arg_classzInkscapeExtension.arg_class   s/     	?# 	? 	? 	? 	? 	? 	? r6   c                 V    t          dt          |           j         d| d           dS )zWrite a debug messagezDEBUG<z> 
N)r   r%   rn   )r3   msgs     r4   debugzInkscapeExtension.debug   s5     	8$t**-8888899999r6   c                 $    t          |            dS )zWrite a non-error messageN)r   )rr   s    r4   rr   zInkscapeExtension.msg   s     	r6   Nc                    	 |t           j        dd         }|                     |           | j        j        t           j        | j        _        n'dt          j        vr| j        j        t          j        d<   | j        j        || j        _        | 	                                 | 
                    |                                            nL# t          $ r?}t          t          |                     t          j        t                      Y d}~nd}~ww xY w|                                  dS # |                                  w xY w)z*Main entrypoint for any Inkscape ExtensionNr   DOCUMENT_PATH)sysargvr=   r+   r    stdinosenvironoutputload_rawsave_raweffectr   r   r0   exitr   clean_up)r3   r<   r|   errs       r4   runzInkscapeExtension.run   s   	|x|  &&&|&.*-)'' 
22.2l.E
?+|"*&,#MMOOOMM$++--(((( 	# 	# 	#SXXH\""""""""	# MMOOOOODMMOOOOs0   CC 
D- 
D5D
D- DD- -Ec                    t          | j        j        t                    r:t	          | j        j        d          | _        |                     | j                  }n|                     | j        j                  }|| _        dS )z:Load the input stream or filename, save everything to selfrbN)
isinstancer+   r    r0   openr*   loadr,   )r3   r,   s     r4   r}   zInkscapeExtension.load_raw   sg     dl-s33 	: 7>>DLyy..HHyy!899H r6   c                    |                      |          rt          | j        j        t                    rJt          | j        j        d          5 }|                     |           ddd           dS # 1 swxY w Y   dS t          j        dk    rXdt          j
        vrJd | j        j        _        ddt          dt          fd	}d
 }|| j        j        _        || j        j        _        |                     | j        j                   dS dS )z3Save to the output stream, use everything from selfwbNwin32PYTEST_CURRENT_TESTc                     dS )NFr8   r2   s    r4   r_   z,InkscapeExtension.save_raw.<locals>.<lambda>  s     r6   r   offsetwhencec                      t          d          )Nz9We can't seek in the stream passed by Inkscape on WindowsrH   )r   r   s     r4   seek_replacementz4InkscapeExtension.save_raw.<locals>.seek_replacement      ,W  r6   c                       t          d          )Nz9We can't tell in the stream passed by Inkscape on Windowsr   r8   r6   r4   tell_replacementz4InkscapeExtension.save_raw.<locals>.tell_replacement  r   r6   )r   )has_changedr   r+   r|   r0   r   saverw   platformrz   r{   seekabler[   seektell)r3   retstreamr   r   s        r4   r~   zInkscapeExtension.save_raw   sb    C   	/$,-s33 /$,-t44 &IIf%%%& & & & & & & & & & & & & & & & & & <7**3HBJ3V3V 4F3EDL'0  c    
   0@DL',/?DL',		$,-.....3	/ 	/s   A22A69A6c                 0    t          d| j                   )z9Takes the input stream and creates a document for parsingzNo input handle for NotImplementedErrorrK   r3   r   s     r4   r   zInkscapeExtension.load  s     ""D"D"DEEEr6   c                 0    t          d| j                   )z*Save the given document to the output filezNo output handle for r   r   s     r4   r   zInkscapeExtension.save       ""E$)"E"EFFFr6   c                 0    t          d| j                   )z3Apply some effects on the document or local contextzNo effect handle for r   r2   s    r4   r   zInkscapeExtension.effect!  r   r6   c                 
    |duS )z)Return true if the output should be savedFr8   )r3   r   s     r4   r   zInkscapeExtension.has_changed&  s     %r6   c                 J    | j         | j                                          dS dS )z)Clean up any open handles and other itemsN)r*   closer2   s    r4   r   zInkscapeExtension.clean_up+  s.     <#L      $#r6   c                 x    |                                  }|rt          j                            |          S |r|S |S )a   
        Return the folder the svg is contained in.
        Returns None if there is no file.

        .. versionchanged:: 1.1
            A default path can be given which is returned in case no path to the
            SVG file can be determined.
        )document_pathrz   pathdirname)clsr'   r   s      r4   svg_pathzInkscapeExtension.svg_path1  sC       "" 	)7??4((( 	Nr6   c                 x    t           j                            t          j        | j                 j        pd          S )z,Return the folder the extension script is inrU   )rz   r   r   rw   modules
__module____file__r   s    r4   ext_pathzInkscapeExtension.ext_pathC  s)     ws{3>:CIrJJJr6   Tc                     |                      ||                                           }|r1t          j                            |          st          d|           |S )z^Return the full filename of the resource in the extension's dir

        .. versionadded:: 1.1)cwdzCould not find resource file: )absolute_hrefr   rz   r   isfiler   )r   rK   abort_on_failfilenames       r4   get_resourcezInkscapeExtension.get_resourceI  s_     $$Ts||~~$>> 	N!9!9 	N !L(!L!LMMMr6   c                 B    t           j                            dd          S )a  Returns the saved location of the document

         * Normal return is a string containing the saved location
         * Empty string means the document was never saved
         * 'None' means this version of Inkscape doesn't support DOCUMENT_PATH

        DO NOT READ OR WRITE TO THE DOCUMENT FILENAME!

         * Inkscape may have not written the latest changes, leaving you reading old
           data.
         * Inkscape will not respect anything you write to the file, causing data loss.

        .. versionadded:: 1.1
        rv   N)rz   r{   getr   s    r4   r   zInkscapeExtension.document_pathT  s    " z~~ot444r6   ~/c                 ,   t           j                            |          }t           j                            |          st           j                            |          }t           j                            |          s]|;|                     |          }|t          d          |dk    rt          d          t           j                            ||          }t           j                            t           j                            |                    S )a  
        Process the filename such that it's turned into an absolute filename
        with the working directory being the directory of the loaded svg.

        User's home folder is also resolved. So '~/a.png` will be `/home/bob/a.png`

        Default is a fallback working directory to use if the svg's filename is not
        available.

        .. versionchanged:: 1.1
            If you set default to None, then the user will be given errors if
            there's no working directory available from Inkscape.
        NzSCan not use relative path, Inkscape isn't telling us the current working directory.rU   z8The SVG must be saved before you can use relative paths.)rz   r   
expanduserisabsr   r   rX   realpath)r   r   r'   r   s       r4   r   zInkscapeExtension.absolute_hrefg  s      7%%h//w}}X&& 	4w))(33Hw}}X&& 	3{ll7++;(5   "99(R   w||C22Hw 2 28 < <===r6   c                 *    t          |           j        S )z&Return a fixed name for this extension)r%   rn   r2   s    r4   rK   zInkscapeExtension.name  s     Dzz""r6   )r>   N)T)r   N)%rn   r   __qualname__r-   	multi_inxr)   r5   r1   r=   rO   staticmethodrj   r   r   r   r0   r	   ro   rs   rr   stdoutr   r}   r~   r   r   r   r   r   classmethodr   r   r   r   r   propertyrK   r8   r6   r4   r   r   6   s0        
 II  8  8 8 8
   0 - - \-^ 4: (C5#:*>    \0: : :
   \
 F    0	! 	! 	!/ / /<F F F
G G G
G G G
     
! ! !    [" K K [K
    [ 5 5 [5$ > > > [>B # # X# # #r6   r   c                   >     e Zd ZdZdZdZ fdZ fdZ fdZ xZ	S )TempDirMixinzF
    Provide a temporary directory for extensions to stash files.
    rU   inktmpc                 H    d | _          t                      j        |i | d S r   )tempdirsuperr5   )r3   r<   kwargs	__class__s      r4   r5   zTempDirMixin.__init__  s,    $)&)))))r6   c                     ddl m}  || j        | j                  | _        t
          j                            | j        j                  | _	        t                                                       dS )zCreate the temporary directoryr   )TemporaryDirectory)rM   suffixN)tempfiler   
dir_prefix
dir_suffix_tempdirrz   r   r   rK   r   r   r}   )r3   r   r   s     r4   r}   zTempDirMixin.load_raw  su     	0///// +*?4?
 
 
 w''(:;;r6   c                     d| _         | j                                         t                                                       dS )zDelete the temporary directoryN)r   r   cleanupr   r   r3   r   s    r4   r   zTempDirMixin.clean_up  s<     r6   )
rn   r   r   r-   r   r   r5   r}   r   __classcell__r   s   @r4   r   r     s          JJ* * * * *            r6   r   c                   T     e Zd ZU dZdZeee         df         ed<    fdZ	d Z
 xZS )SvgInputMixinzI
    Expects the file input to be an svg document and will parse it.
    r8   .
select_allc                     t                                                       | j                            ddt          dg d           | j                            ddt          dg d           d S )	Nz--idappendidsz$id attribute of object to manipulate)actionr%   destr'   r&   z--selected-nodesselected_nodesz-id:subpath:position of selected nodes, if any)r   r5   r.   r/   r0   r   s    r4   r5   zSvgInputMixin.__init__  s    $$7 	% 	
 	
 	
 	$$!@ 	% 	
 	
 	
 	
 	
r6   c                 J   t          |          }t          j        |          | _        |                                | _         | j        j        j        | j        j	          | j        j        s7| j
        r0 | j                                        j        | j
         | j        _        |S )z5Load the stream as an svg xml etree and make a backup)r   copydeepcopyoriginal_documentgetrootsvg	selectionsetr+   r   r   descendantsfilter)r3   r   r,   s      r4   r   zSvgInputMixin.load  s     F##!%x!8!8(0(8(8(:(: 011x! 	Qdo 	Q!>!5!5!7!7!>!PDHr6   )rn   r   r   r-   r   r   r   r   __annotations__r5   r   r   r   s   @r4   r   r     st          
 24Jd<(#-.333
 
 
 
 
*	 	 	 	 	 	 	r6   r   c                   2    e Zd ZdZdZed             Zd ZdS )SvgOutputMixinz
    Expects the output document to be an svg document and will write an etree xml.

    A template can be specified to kick off the svg document building process.
    a{  <svg viewBox="0 0 {width} {height}"
        width="{width}{unit}" height="{height}{unit}"
        xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"
        xmlns:xlink="http://www.w3.org/1999/xlink"
        xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
        xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
    </svg>c           	          |                     dd           t          t           | j        j        di |                    S )z
        Opens a template svg document for building, the kwargs
        MUST include all the replacement values in the template, the
        default template has 'width' and 'height' of the document.
        unitrU   r8   )
setdefaultr   r0   templateformat)r   r   s     r4   get_templatezSvgOutputMixin.get_template  sF     	&"%%%/CL/99&99::;;;r6   c                    t          | j        t          t          f          r| j        }ndt	          | j                  j        v rAt          t          | j                  }|                                	                                }n-t          dt	          | j                  j         ddz             	 |                    |           dS # t          $ r, |                    |                    d                     Y dS w xY w)z)Save the svg document to the given streamElementzUnknown type of document: z can notzsave.zutf-8N)r   r,   bytesr0   r%   rn   r   r   r   tostring
ValueErrorwrite	TypeErrorencode)r3   r   r,   docs       r4   r   zSvgOutputMixin.save  s     dmeS\22 
	}HH$t}--666udm,,C{{}}--//HHST$--@-@-ISSS  
	3LL""""" 	3 	3 	3LL11222222	3s   4C 2D DN)rn   r   r   r-   r   r   r   r   r8   r6   r4   r   r     sO         H < < [<3 3 3 3 3r6   r   c                       e Zd ZdZd ZdS )SvgThroughMixinzS
    Combine the input and output svg document handling (usually for effects).
    c                 r    t          j        | j                  }t          j        | j                  }||k    S )z+Return true if the svg document has changed)r   r   r   r,   )r3   r   originalresults       r4   r   zSvgThroughMixin.has_changed  s2     >$"899..6!!r6   N)rn   r   r   r-   r   r8   r6   r4   r  r    s-         " " " " "r6   r  ).r-   rz   rd   rw   r   typingr   r   r   r   r   r   r	   r
   r   r   r   argparser   r   lxmlr   interfaces.IElementr   r   utilsr   r   r   r   r   elements._parserr   elements._utilsr   localizationr   r   bufferr   _Baseobjectr   r   r   r  r8   r6   r4   <module>r     sc  &  
			 				 



                           / . . . . . . .       B B B B B B B B S S S S S S S S S S S S S S & & & & & &             " " " " " "		W# W# W# W# W# W# W# W#t
  EEE    5   B& & & & &E & & &R,3 ,3 ,3 ,3 ,3U ,3 ,3 ,3^
" 
" 
" 
" 
"m^ 
" 
" 
" 
" 
"r6   