B
    d                 @   s   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m	Z	m
Z
 ddlmZ d dlmZ d	gZG d
d dejZdd ZG dd	 d	ZdS )    N)OrderedDict)datetime)Path)OptionalTextIOUnion   )PegasusError)yamlWritablec               @   s   e Zd Zdd ZdS )_CustomEncoderc             C   s8   t |dr*t|jr| S td|tj| |S )z
        if isinstance(obj, Date):
                        return "whatever spec we come up with for Date such as ISO8601"
        elif isinstance(obj, Path):
            return obj.resolve
        __json__z__json__ is not callable for {})hasattrcallabler   	TypeErrorformatjsonJSONEncoderdefault)selfobj r   a/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/Pegasus/api/writable.pyr      s
    	

z_CustomEncoder.defaultN)__name__
__module____qualname__r   r   r   r   r   r      s   r   c             C   s4   t | tstd| tttdd |  D S )a+  Helper function to remove keys where their values are set to None to avoid cluttering yaml/json files

    :param _dict: object represented as a dict
    :type _dict: dict
    :raises ValueError: _dict must be of type dict
    :return: new dictionary with 'None' values removed
    :rtype: dict
    z+invalid _dict: {}; _dict must be of type {}c             S   s    g | ]\}}|d k	r||fqS )Nr   ).0kvr   r   r   
<listcomp>0   s    z%_filter_out_nones.<locals>.<listcomp>)
isinstancedictr   r   typer   items)_dictr   r   r   _filter_out_nones"   s    	
r%   c               @   sZ   e Zd ZdZdddhZdd Zeeddd	Zd
d Z	de
eeef  edddZdS )r   z6Derived class can be serialized to a json or yaml fileymlr
   r   c             C   s
   d | _ d S )N)_path)r   r   r   r   __init__8   s    zWritable.__init__)returnc             C   s&   | j dkrtd| jjt| j S )z
        Retrieve the path to which this object has been written to.

        :raises PegasusError: object has not yet been written to a file
        :return: resolved path to which this object has been written
        :rtype: Path
        Nz@{}.write(filename) must be called before trying to retrieve path)r'   r	   r   	__class__r   r   )r   r   r   r   path;   s
    	
zWritable.pathc             C   s   |  tjkr"tdj|tjdtdt t	 
dddfg}|tjtj| tdtd |d	kst|d
krtj||dd ntj||tddd dS )a;  Internal function to dump to file in either yaml or json formats

        :param file: file object to write to
        :type file: file
        :param _format: file format that can be "yml", "yaml", or "json
        :type _ext: str
        :raises ValueError: _format must be one of "yml", "yaml" or "json"
        z;invalid _ext: {_format}, extension must be one of {formats})_formatformatsz	x-pegasusz%m-%d-%yT%H:%M:%SZpython)Z	createdByZ	createdOnZapiLang)cls)object_pairs_hookr&   r
   T)Zallow_unicode   F)r/   indentensure_asciiN)lowerr   _FORMATS
ValueErrorr   r   getpassgetuserr   nowstrftimeupdater   loadsdumpsr   r
   dump)r   filer,   Zself_as_dictr   r   r   _writeM   s     	zWritable._writeN)r?   r,   c          	   C   s<  |  tjkrtd|dkr$| j}t|trt|}|jdd   }t	|d*}|tjkrl| 
|| n| 
|| W dQ R X t| | _nt|dr(y tt|j}|jdd }W n  tk
r   | 
|| Y nHX |tjkr| 
|| n| 
|| t|jtr8tt|j | _ntdj|ddS )a/  Serialize this class as either yaml or json and write to the given
        file. If file==None, this class will be written to a default file. The
        following classes have these defaults:

        .. table:: Default Files
            :widths: auto

            =====================  ===================
            Class                  Default Filename
            =====================  ===================
            SiteCatalog            sites.yml
            ReplicaCatalog         replicas.yml
            TransformationCatalog  transformations.yml
            Workflow               workflow.yml
            =====================  ===================

        :param file: path or file object (opened in "w" mode) to write to, defaults to None
        :type file: Optional[Union[str, TextIO]]
        :param _format: can be either "yml", "yaml" or "json", defaults to "yml"
        :type _format: str, optional
        :raises ValueError: _format must be one of "yml", "yaml" or "json"
        :raises TypeError: file must be a str or file object
        zPinvalid file format: {_format}, format should be one of 'yml', 'yaml', or 'json'Nr   wreadz){file} must be of type str or file object)r?   )r4   r   r5   r6   Z_DEFAULT_FILENAMEr    strr   suffixopenr@   resolver'   r   nameAttributeErrorr   r   )r   r?   r,   r+   extfr   r   r   writez   s4    


zWritable.write)Nr&   )r   r   r   __doc__r5   r(   propertyr   r+   r@   r   r   rC   r   rK   r   r   r   r   r   3   s   
-)r7   r   collectionsr   r   pathlibr   typingr   r   r   errorsr	   ZPegasusr
   __all__r   r   r%   r   r   r   r   r   <module>   s   