U
    CvfuM                     @  s  d dl mZ d dlZd dlZd dlZd dlmZ d dlZd dl	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 dl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" d dl#m$Z$ d dl%m&Z&m'Z'm(Z(m)Z)m*Z* d dl+m,Z, dddddZ-eeegZ.G dd deZ/G dd de/Z0dd Z1dd Z2d3ddZ3dd Z4d d! Z5e5fd"d#Z6d$d% Z7d&d' Z8d4d*d+Z9d,d- Z:G d.d/ d/eZ;G d0d1 d1eZ<e<ed2< dS )5    )annotationsN)suppress)coding)BACKEND_ENTRYPOINTSBackendArrayBackendEntrypointWritableCFDataStore_normalize_pathfind_root_and_grouprobust_getitem)CachingFileManagerDummyFileManager)	HDF5_LOCKNETCDFC_LOCKcombine_locksensure_lockget_write_lock)encode_nc3_attr_valueencode_nc3_variable)StoreBackendEntrypoint)pop_to)indexing)
FrozenDictclose_on_erroris_remote_urimodule_availabletry_read_magic_number_from_path)Variablenativebiglittle)=><|c                   @  s*   e Zd ZdZdd Zdd Zd
ddZd	S )BaseNetCDF4Array)	datastoredtypeshapevariable_namec                 C  s>   || _ || _|  }|j| _|j}|tkr4td}|| _d S )NO)r&   r)   	get_arrayr(   r'   strnp)selfr)   r&   arrayr'    r0   </tmp/pip-unpacked-wheel-h316xyqg/xarray/backends/netCDF4_.py__init__4   s    
zBaseNetCDF4Array.__init__c              	   C  sB   | j j0 | jdd}|||< | j jr4| j jdd W 5 Q R X d S )NF
needs_lock)r&   lockr+   	autocloseclose)r.   keyvaluedatar0   r0   r1   __setitem__C   s
    
zBaseNetCDF4Array.__setitem__Tc                 C  s   t dd S )NzVirtual Method)NotImplementedError)r.   r4   r0   r0   r1   r+   J   s    zBaseNetCDF4Array.get_arrayN)T)__name__
__module____qualname__	__slots__r2   r;   r+   r0   r0   r0   r1   r%   1   s   r%   c                   @  s*   e Zd ZdZd
ddZdd Zdd Zd	S )NetCDF4ArrayWrapperr0   Tc              	   C  sD   | j |}|j| j }|d tt |d W 5 Q R X |S )NF)r&   _acquire	variablesr)   Zset_auto_maskandscaler   AttributeErrorZset_auto_chartostring)r.   r4   dsvariabler0   r0   r1   r+   Q   s    

zNetCDF4ArrayWrapper.get_arrayc                 C  s   t || jt jj| jS N)r   Zexplicit_indexing_adapterr(   ZIndexingSupportZOUTER_getitem)r.   r8   r0   r0   r1   __getitem__Z   s       zNetCDF4ArrayWrapper.__getitem__c              	   C  sr   | j jrtjttd}ntj}z.| j j | j	dd}|||}W 5 Q R X W n  t
k
rl   d}t
|Y nX |S )N)ZcatchFr3   zThe indexing operation you are attempting to perform is not valid on netCDF4.Variable object. Try loading your data into memory first by calling .load().)r&   	is_remote	functoolspartialr   RuntimeErroroperatorgetitemr5   r+   
IndexError)r.   r8   rO   Zoriginal_arrayr/   msgr0   r0   r1   rH   _   s    
zNetCDF4ArrayWrapper._getitemN)T)r=   r>   r?   r@   r+   rI   rH   r0   r0   r0   r1   rA   N   s   
	rA   c                 C  s,   t jjddt j fD ]}|| } q| S )NT)Zallows_unicode)r   stringsZEncodedStringCoderZCharacterArrayCoderencode)varZcoderr0   r0   r1   _encode_nc4_variablev   s
    rU   c                 C  s   | t k	rtd| dd S )Nzunexpected dtype encoding zM. This shouldn't happen: please file a bug report at github.com/pydata/xarray)r,   AssertionError)r'   r0   r0   r1   $_check_encoding_dtype_is_vlen_string   s    
rW   NETCDF4Fc                 C  s>   |dkrt | S d| jkr8| jd }t| |r8td| jS )NrX   r'   zLencoding dtype=str for vlen strings is only supported with format='NETCDF4'.)
_nc4_dtypeencodingrW   
ValueErrorr'   )rT   Z	nc_formatraise_on_invalid_encodingZencoded_dtyper0   r0   r1   _get_datatype   s    

r]   c                 C  s\   d| j kr | j d}t| n8tj| jr4t}n$| jjdkrH| j}nt	d| j |S )Nr'   )iufcSz(unsupported dtype for netCDF4 variable: )
rZ   poprW   r   rR   Zis_unicode_dtyper'   r,   kindr[   )rT   r'   r0   r0   r1   rY      s    

rY   c                 C  s
   |  |S rG   )ZcreateGroup)Zdatasetnamer0   r0   r1   _netcdf4_create_group   s    rf   c                 C  s   |dkr| S t |tstd|dd}|D ]Z}z| j| } W q2 tk
r } z(|dkrj|| |} ntd| |W 5 d }~X Y q2X q2| S d S )N>    N/zgroup must be a string or Nonerh   rzgroup not found: )
isinstancer,   r[   stripsplitgroupsKeyErrorOSError)rE   groupmodeZcreate_grouppathr8   er0   r0   r1   _nc4_require_group   s    
$rt   c                 C  s*   | j jdkr&d|kr&t|d |d< d S )Nrb   
_FillValue)r'   rd   r-   Zstring_)r:   
attributesr0   r0   r1   _ensure_fill_value_valid   s    rw   c                 C  s`   | j jdkrB| j| j d}t| j|| j| j} | j	dd  | j
dddkr\td| S )N)r!   r$   r!   endianr   z]Attempt to write non-native endian type, this is not supported by the netCDF4 python library.)r'   	byteorderr:   ZastypeZnewbyteorderr   dimsattrsrZ   rc   getr<   )rT   r:   r0   r0   r1   _force_native_endianness   s    r}   TnetCDF4c              	     s^   d krd | j  }ddh}dddddd	d
ddh	|rBd |rPd |s|dd k	r|d }t fddt|| j| jD }	d|k}
|
o|d| jk}|	s|r|d= t fdd| jD }|s|rd| kr|d= |D ]}||kr||= q|r:fdd|D }|rZt	d|d|dn t
|D ]}|krB||= qB|S )Nr0   sourceoriginal_shapezlib	complevel
fletcher32
contiguous
chunksizesshuffleru   r'   compressionleast_significant_digitZcompression_optsc                 3  s$   | ]\}}}||ko| kV  qd S rG   r0   ).0ra   ddimunlimited_dimsr0   r1   	<genexpr>   s   z1_extract_nc4_variable_encoding.<locals>.<genexpr>c                 3  s   | ]}| kV  qd S rG   r0   )r   r   r   r0   r1   r     s     c                   s   g | ]}| kr|qS r0   r0   r   k)valid_encodingsr0   r1   
<listcomp>  s      z2_extract_nc4_variable_encoding.<locals>.<listcomp>z#unexpected encoding parameters for z
 backend: z. Valid encodings are: )rZ   copyaddr|   anyzipr(   rz   keysr[   list)rF   raise_on_invalidZlsd_okayZ	h5py_okaybackendr   rZ   Zsafe_to_dropr   Zchunks_too_bigZhas_original_shapeZchanged_shapeZvar_has_unlim_dimr   invalidr0   )r   r   r1   _extract_nc4_variable_encoding   sX    




r   c                 C  s    t | }|jjdko|jdkS )N)Urb      )r-   Zasarrayr'   rd   size)r9   Zarrr0   r0   r1   _is_list_of_strings  s    
r   c                
   @  s   e Zd ZdZdZddedfddZed&d
dZd'ddZ	e
dd Zdd Zdd Zdd Zdd Zdd Zd(ddZdd Zdd Zd)d d!Zd"d# Zd$d% ZdS )*NetCDF4DataStorezStore for reading and writing data via the Python-NetCDF4 library.

    This store supports NetCDF3, NetCDF4 and OpenDAP datasets.
    )r6   formatrJ   r5   	_filename_group_manager_modeNFc                 C  s   dd l }t||jrL|d kr*t|\}}nt||jk	r@td|}t|}|| _|| _|| _	| j
j| _| j
 | _t| j| _t|| _|| _d S )Nr   zDmust supply a root netCDF4.Dataset if the group argument is provided)r~   rj   Datasetr
   typer[   r   r   r   r   rE   Z
data_modelr   filepathr   r   rJ   r   r5   r6   )r.   managerrp   rq   r5   r6   r~   rootr0   r0   r1   r2   5  s$    

zNetCDF4DataStore.__init__ri   rX   Tc                 C  s   dd l }t|tjrt|}t|ts0td|d kr<d}|d kr|dkr`t|rZt}qt	}n,|d ksr|
drxt	}nt}t|t|g}t||||d}t|j|||d}| |||||
dS )Nr   zJcan only read bytes or file-like objects with engine='scipy' or 'h5netcdf'rX   ri   )clobberdisklesspersistr   )rq   kwargs)rp   rq   r5   r6   )r~   rj   osPathLikefspathr,   r[   r   r   NETCDF4_PYTHON_LOCK
startswithr   r   dictr   r   )clsfilenamerq   r   rp   r   r   r   r5   Z
lock_makerr6   r~   Z	base_lockr   r   r0   r0   r1   openO  s>    

      zNetCDF4DataStore.openc              	   C  s,   | j |}t|| j| j}W 5 Q R X |S rG   )r   Zacquire_contextrt   r   r   )r.   r4   r   rE   r0   r0   r1   rB     s    zNetCDF4DataStore._acquirec                 C  s   |   S rG   )rB   r.   r0   r0   r1   rE     s    zNetCDF4DataStore.dsc           	        s    j }tt|| } fdd  D }t|| i }  }|d k	rT||   }|d k	r|dkr~d|d< d |d< nd|d< t	||d< t
||d | j|d<  j|d	<  j|d
< t||||S )Nc                   s   i | ]}|  |qS r0   )	getncattrr   rT   r0   r1   
<dictcomp>  s      z8NetCDF4DataStore.open_store_variable.<locals>.<dictcomp>r   Tr   Fr   r   r   r'   )
dimensionsr   ZLazilyIndexedArrayrA   ncattrsrw   filtersupdatechunkingtupler   r   r(   r'   r   )	r.   re   rT   r   r:   rv   rZ   r   r   r0   r   r1   open_store_variable  s(    





z$NetCDF4DataStore.open_store_variablec                   s   t  fdd jj D S )Nc                 3  s"   | ]\}}|  ||fV  qd S rG   )r   r   r   vr   r0   r1   r     s    z1NetCDF4DataStore.get_variables.<locals>.<genexpr>)r   rE   rC   itemsr   r0   r   r1   get_variables  s    
zNetCDF4DataStore.get_variablesc                   s   t  fdd j D S )Nc                 3  s   | ]}| j |fV  qd S rG   )rE   r   r   r   r0   r1   r     s     z-NetCDF4DataStore.get_attrs.<locals>.<genexpr>)r   rE   r   r   r0   r   r1   	get_attrs  s    zNetCDF4DataStore.get_attrsc                 C  s   t dd | jj D S )Nc                 s  s   | ]\}}|t |fV  qd S rG   )lenr   r0   r0   r1   r     s     z2NetCDF4DataStore.get_dimensions.<locals>.<genexpr>)r   rE   r   r   r   r0   r0   r1   get_dimensions  s    zNetCDF4DataStore.get_dimensionsc                 C  s   ddd | j j D iS )Nr   c                 S  s   h | ]\}}|  r|qS r0   )Zisunlimitedr   r0   r0   r1   	<setcomp>  s     z0NetCDF4DataStore.get_encoding.<locals>.<setcomp>)rE   r   r   r   r0   r0   r1   get_encoding  s
     
zNetCDF4DataStore.get_encodingc                 C  s    |s|nd }| j j||d d S )N)r   )rE   ZcreateDimension)r.   re   lengthZis_unlimitedZ
dim_lengthr0   r0   r1   set_dimension  s    zNetCDF4DataStore.set_dimensionc                 C  s<   | j dkrt|}t|r*| j|| n| j|| d S NrX   )r   r   r   rE   Zsetncattr_stringZ	setncattr)r.   r8   r9   r0   r0   r1   set_attribute  s
    
zNetCDF4DataStore.set_attributec                 C  s(   t |}| jdkrt|}nt|}|S r   )r}   r   rU   r   )r.   rF   r0   r0   r1   encode_variable  s
    

z NetCDF4DataStore.encode_variablec                 C  s   t || j|d}|j }|dd }|tkrF|d k	rFtd|dt|||d}|| jj	krn| jj	| }	nZ| jj
|||j|dd|dd	|d
d|dd|dd|dd|d|d}	|	| t|| }
|
|jfS )N)r\   ru   znetCDF4 does not yet support setting a fill value for variable-length strings (https://github.com/Unidata/netcdf4-python/issues/730). Either remove '_FillValue' from encoding on variable zH or set {'dtype': 'S1'} in encoding to use the fixed width NC_CHAR type.)r   r   r   Fr      r   Tr   r   r   r   r   )varnamedatatyper   r   r   r   r   r   r   rx   r   
fill_value)r]   r   r{   r   rc   r,   r<   r   rE   rC   ZcreateVariablerz   r|   Z	setncattsrA   r:   )r.   re   rF   Zcheck_encodingr   r   r{   r   rZ   Znc4_vartargetr0   r0   r1   prepare_variable  sF      

	  






z!NetCDF4DataStore.prepare_variablec                 C  s   | j   d S rG   )rE   syncr   r0   r0   r1   r     s    zNetCDF4DataStore.syncc                 K  s   | j jf | d S rG   )r   r7   )r.   r   r0   r0   r1   r7      s    zNetCDF4DataStore.close)	ri   rX   NTFFNNF)T)F)FN)r=   r>   r?   __doc__r@   r   r2   classmethodr   rB   propertyrE   r   r   r   r   r   r   r   r   r   r   r7   r0   r0   r0   r1   r   $  sD      
         0


		   
0r   c                   @  s2   e Zd ZdZedZdZdZdd ZdddZ	dS )NetCDF4BackendEntrypointa  
    Backend for netCDF files based on the netCDF4 package.

    It can open ".nc", ".nc4", ".cdf" files and will be choosen
    as default for these files.

    Additionally it can open valid HDF5 files, see
    https://h5netcdf.org/#invalid-netcdf-files for more info.
    It will not be detected as valid backend for such files, so make
    sure to specify ``engine="netcdf4"`` in ``open_dataset``.

    For more information about the underlying library, visit:
    https://unidata.github.io/netcdf4-python

    See Also
    --------
    backends.NetCDF4DataStore
    backends.H5netcdfBackendEntrypoint
    backends.ScipyBackendEntrypoint
    r~   zLOpen netCDF (.nc, .nc4 and .cdf) and most HDF5 files using netCDF4 in XarrayzYhttps://docs.xarray.dev/en/stable/generated/xarray.backends.NetCDF4BackendEntrypoint.htmlc                 C  sd   t |trt|rdS t|}|d k	r0|dS ztj|\}}W n tk
rZ   Y dS X |dkS )NT)s   CDFs   HDF

F>   .nc4.nc.cdf)	rj   r,   r   r   r   r   rr   splitext	TypeError)r.   filename_or_objZmagic_number_extr0   r0   r1   guess_can_open   s    
z'NetCDF4BackendEntrypoint.guess_can_openTNri   rX   Fc                 C  s\   t |}tj||
||	|||||d	}t }t|  |j||||||||d}W 5 Q R X |S )N)rq   r   rp   r   r   r   r5   r6   )mask_and_scaledecode_timesconcat_charactersdecode_coordsdrop_variables
use_cftimedecode_timedelta)r	   r   r   r   r   open_dataset)r.   r   r   r   r   r   r   r   r   rp   rq   r   r   r   r   r5   r6   storeZstore_entrypointrE   r0   r0   r1   r   -  s2    

z%NetCDF4BackendEntrypoint.open_dataset)TTTTNNNNri   rX   TFFNF)
r=   r>   r?   r   r   	availabledescriptionurlr   r   r0   r0   r0   r1   r     s,                  r   Znetcdf4)rX   F)FTFr~   N)=
__future__r   rK   rN   r   
contextlibr   Znumpyr-   Zxarrayr   Zxarray.backends.commonr   r   r   r   r	   r
   r   Zxarray.backends.file_managerr   r   Zxarray.backends.locksr   r   r   r   r   Zxarray.backends.netcdf3r   r   Zxarray.backends.storer   Zxarray.coding.variablesr   Zxarray.corer   Zxarray.core.utilsr   r   r   r   r   Zxarray.core.variabler   Z_endian_lookupr   r%   rA   rU   rW   r]   rY   rf   rt   rw   r}   r   r   r   r   r0   r0   r0   r1   <module>   sL   $	(	
     
E aY