3
d<                 @   s,  d 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lmZmZ d	d
lmZmZmZ ddlmZmZmZmZmZmZmZ d	dlmZmZ djZe	eZ G dd dej!Z"G dd de"Z#G dd de#Z$G dd de"Z%G dd de$Z&G dd de&Z'G dd de&Z(dd Z)dS )z

Base I/O specifications for Nipype interfaces
.............................................

Define the API for the I/O of interfaces

    N)isclass)deepcopy)warn)Version)
TraitError)TraitDictObjectTraitListObject   )md5hash_infilehash_timestamp   )traitsFileStr	Undefined	isdefinedhas_metadataOutputMultiObject)config__version__z{:.10f}c                   s   e Zd ZdZeZ fddZdd Zdd Zdd	 Z	d
d Z
dd Z fddZeZ fddZd!ddZd"ddZd#ddZd$ddZedd Z fdd Z  ZS )%BaseTraitedSpeca  
    Provide a few methods necessary to support nipype interface api

    The inputs attribute of interfaces call certain methods that are not
    available in traits.HasTraits. These are provided here.

    new metadata:

    * usedefault : set this to True if the default value of the trait should be
      used. Unless this is set, the attributes are set to traits.Undefined

    new attribute:

    * get_hashval : returns a tuple containing the state of the trait as a dict
      and hashvalue corresponding to dict.

    XXX Reconsider this in the long run, but it seems like the best
    solution to move forward on the refactoring.
    c                sv   t t| jf | tjdd i }x&| j D ]}| j | js,t||< q,W | jf ddi| | j	  | jf | dS )zInitialize handlers and inputsT)Zreraise_exceptionstrait_change_notifyFN)
superr   __init__r   Zpush_exception_handlercopyable_trait_names
usedefaultr   	trait_set_generate_handlers)selfkwargsZundefined_traitstrait)	__class__ >/tmp/pip-build-7vycvbft/nipype/nipype/interfaces/base/specs.pyr   <   s    zBaseTraitedSpec.__init__c             c   s,   x&t | j D ]}|| j | fV  qW dS )z0Name, trait generator for user modifiable traitsN)sortedr   r   )r   namer#   r#   r$   itemsL   s    zBaseTraitedSpec.itemsc             C   sD   g }x.t | j j D ]\}}|jd||f  qW djdj|S )z4Return a well-formatted representation of the traitsz%s = %sz
{}

)r%   	trait_getr'   appendformatjoin)r   Zoutstrr&   valuer#   r#   r$   __repr__Q   s    zBaseTraitedSpec.__repr__c             C   sp   t dd d}| jf |}x|D ]}| j| j| q W t dd d}| jf |}x|D ]}| j| j| qVW dS )z]Find all traits with the 'xor' metadata and attach an event
        handler to them.
        c             S   s   | d k	S )Nr#   )tr#   r#   r$   <lambda>\   s    z4BaseTraitedSpec._generate_handlers.<locals>.<lambda>)xorc             S   s   | d k	S )Nr#   )r/   r#   r#   r$   r0   `   s    )
deprecatedN)dictZtrait_namesZon_trait_change	_xor_warn_deprecated_warn)r   Zhas_xorZxorselemZhas_deprecationr2   r#   r#   r$   r   X   s    

z"BaseTraitedSpec._generate_handlersc             C   sp   t |rl| j | }xV|jD ]L}||kr*qt t| |r| jf ddid| ti d||f }t|qW dS )z!Generates warnings for xor traitsr   Fz%szFInput "%s" is mutually exclusive with input "%s", which is already setN)r   r   r1   getattrr   r   IOError)r   objr&   oldnew
trait_specZ
trait_namemsgr#   r#   r$   r4   e   s    
zBaseTraitedSpec._xor_warnc       
      C   s   t |r| j | }d|| jjjdd f }d|j }|jrj|j| j kr^t|d|j  d|j }nd}dj	|||f}	t
t|j| jk rt|	nL|jr|	d	||jf 7 }	t|	 |jr| jf d
did| td|j |i dS )z6Checks if a user assigns a value to a deprecated traitz'Input %s in interface %s is deprecated.Z	InputSpecr   z2Will be removed or raise an error as of release %sz Replacement trait %s not foundzIt has been replaced by %s.  z-Unsetting old value %s; setting new value %s.r   Fz%sN)r   r   r"   __name__splitr2   new_namer   r   r,   r   strpackage_versionr   r   r   )
r   r9   r&   r:   r;   r<   Zmsg1Zmsg2Zmsg3r=   r#   r#   r$   r5   x   s2    
z BaseTraitedSpec._deprecated_warnc                s"   t t| jf |}| j|t}|S )zReturns traited class as a dict

        Augments the trait get function to return a dictionary without
        notification handles
        )r   r   r)   _clean_containerr   )r   r    out)r"   r#   r$   r)      s    zBaseTraitedSpec.trait_getc                s$   t t| jf |}| j|dd}|S )zReturns traited class as a dict

        Augments the trait get function to return a dictionary without
        any traits. The dictionary does not contain any attributes that
        were Undefined
        T)skipundefined)r   r   r)   rE   )r   r    rF   )r"   r#   r$   get_traitsfree   s    zBaseTraitedSpec.get_traitsfreeNFc             C   s   t |tst |trZi }xt|j D ].\}}t|rH| j||||< q&|s&|||< q&W nt |tsxt |tsxt |trg }xB|D ]:}t|r|j	| j|| q|s|j	| q|j	d qW t |trt|}nd}t|r|}n|s|}|S )z;Convert a traited obejct into a pure python representation.N)

isinstancer   r3   listr'   r   rE   r   tupler*   )r   objektZundefinedvalrG   rF   keyvalr#   r#   r$   rE      s2    





z BaseTraitedSpec._clean_containerTc             C   s   t | j|j|||S )z\
        Return has_metadata for the requested trait name in this
        interface
        )r   r!   Z
trait_type)r   r&   metadatar-   	recursiver#   r#   r$   r      s    zBaseTraitedSpec.has_metadatac          	   C   s   g }g }xt | j j D ]v\}}t| s| j|ddr<q| j|dd oX| j|d }|j|| j|||df |j|| j|d||df qW |tt|j	 j
 fS )a  Return a dictionary of our items with hashes for each file.

        Searches through dictionary items and if an item is a file, it
        calculates the md5 hash of the file contents and stores the
        file name and hash value as the new key value.

        However, the overall bunch hash is calculated only on the hash
        value of a file. The path and name of the file are not used in
        the overall hash calculation.

        Returns
        -------
        list_withhash : dict
            Copy of our dictionary with the new file hashes included
            with each file.
        hashvalue : str
            The md5 hash value of the traited spec

        nohashT
hash_filesFZname_source)hash_methodrR   )r%   r)   r'   r   r   r*   _get_sorteddictr
   rC   encode	hexdigest)r   rS   Zlist_withhashZlist_nofilenamer&   rN   rR   r#   r#   r$   get_hashval   s"    zBaseTraitedSpec.get_hashvalc       	   	   C   sT  t |trPg }x<t|j D ],\}}t|r|j|| j||||df qW n t |ttfrg }x,|D ]$}t|rh|j| j||||d qhW t |trt|}nd }t|rP|ot |t	t
fotjj|r6|d krtjdd}|j dkrt|}n$|j dkrt|}ntd| |r0||f}n|}nt |trLt|}n|}|S )N)rS   rR   Z	executionrS   	timestampcontentzUnknown hash method: %s)rI   r3   r%   r'   r   r*   rT   rJ   rK   rC   bytesospathisfiler   getlowerr   r   	Exceptionfloat
_float_fmt)	r   rL   ZdictwithhashrS   rR   rF   rM   rN   hashr#   r#   r$   rT     sT    








zBaseTraitedSpec._get_sorteddictc             C   s   | j  S )N)r   )r   r#   r#   r$   __all__H  s    zBaseTraitedSpec.__all__c                sH   t t| j }x4| jD ]*}| j|}|jtr|jj| |||< qW |S )a  
        Override __getstate__ so that OutputMultiObjects are correctly pickled.

        >>> class OutputSpec(TraitedSpec):
        ...     out = OutputMultiObject(traits.List(traits.Int))
        >>> spec = OutputSpec()
        >>> spec.out = [[4]]
        >>> spec.out
        [4]

        >>> spec.__getstate__()['out']
        [[4]]

        >>> spec.__setstate__(spec.__getstate__())
        >>> spec.out
        [4]

        )	r   r   __getstate__rd   r!   Zis_trait_typer   handler	get_value)r   staterM   Z_trait_spec)r"   r#   r$   re   L  s    

zBaseTraitedSpec.__getstate__)NF)NT)N)FNT)r@   
__module____qualname____doc__nipype_versionrD   r   r'   r.   r   r4   r5   r)   r^   rH   rE   r   rW   rT   propertyrd   re   __classcell__r#   r#   )r"   r$   r   %   s"   $

#

1
:r   c               @   s   e Zd ZdZejZdS )TraitedSpeczQCreate a subclass with strict traits.

    This is used in 90% of the cases.
    N)r@   ri   rj   rk   r   ZDisallow_r#   r#   r#   r$   ro   g  s   ro   c               @   s   e Zd ZdS )BaseInterfaceInputSpecN)r@   ri   rj   r#   r#   r#   r$   rq   p  s   rq   c               @   s   e Zd ZdZdd ZdS )DynamicTraitedSpeczA subclass to handle dynamic traits

    This class is a workaround for add_traits and clone_traits not
    functioning well together.
    c          
   C   s   t | }||kr|| S t| j |}x(| j D ]}|| jj kr0t| |}q0W | j|d}x,| j D ] }yt||}W qf   Y qfX qfW | j|d}|jf | |S )z
        Replace the ``__deepcopy__`` member with a traits-friendly implementation.

        A bug in ``__deepcopy__`` for ``HasTraits`` results in weird cloning behaviors.
        )memo)	idr   r)   r   __dict__keysr7   Zclone_traitsr   )r   rs   Zid_selfZdup_dictrM   rp   dupr#   r#   r$   __deepcopy__{  s     
zDynamicTraitedSpec.__deepcopy__N)r@   ri   rj   rk   rx   r#   r#   r#   r$   rr   t  s   rr   c               @   s(   e Zd ZedddZejddddZdS )CommandLineInputSpecz%sz$Additional parameters to the command)argstrdesczEnvironment variablesT)r{   r   rQ   N)r@   ri   rj   r   argsr   Z
DictStrStrenvironr#   r#   r#   r$   ry     s   ry   c               @   s   e Zd ZeddddZdS )StdOutCommandLineInputSpecz> %sr   T)rz   positionZgenfileN)r@   ri   rj   r   out_filer#   r#   r#   r$   r~     s   r~   c               @   s(   e Zd ZejddddZejddZdS )MpiCommandLineInputSpecFz.Whether or not to run the command with mpiexecT)r{   r   zeNum processors to specify to mpiexec. Do not specify if this is managed externally (e.g. through SGE))r{   N)r@   ri   rj   r   ZBoolZuse_mpiZIntZn_procsr#   r#   r#   r$   r     s   r   c             C   s   | j dkrdS t|  r*t| dr*| j  g }t| r>| j  n| j}tdd d}x4t|jf |j D ]\}}|j	t||j
d qhW |S )zhProvides information about file inputs to copy or link to cwd.
    Necessary for pipeline operation
    Nnormalize_filenamesc             S   s   | d k	S )Nr#   )r/   r#   r#   r$   r0     s    z#get_filecopy_info.<locals>.<lambda>)copyfile)rM   copy)Z
input_specr   hasattrr   inputsr3   r%   r   r'   r*   r   )clsinfor   rO   r&   specr#   r#   r$   get_filecopy_info  s    
r   )*rk   r[   inspectr   r   r   warningsr   Zpackaging.versionr   Ztraits.trait_errorsr   Ztraits.trait_handlersr   r   Zutils.filemanipr
   r   r   Ztraits_extensionr   r   r   r   r   r   r   r>   r   r   r+   rb   rl   Z	HasTraitsr   ro   rq   rr   ry   r~   r   r   r#   r#   r#   r$   <module>   s,   $
  D	"