3
v^8                 @   s  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	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 d dlmZ d dlmZ d dlmZmZ d dlmZ d dlmZ dZ G dd dZ!eG dd de!Z"dddZ#G dd deZ$e$ Z%dS )    N)datetime)urljoin)settings)SuspiciousFileOperation)Filelocks)file_move_safe)setting_changed)timezone)	safe_join)get_random_string)deconstructible)filepath_to_uri)
LazyObjectcached_property)import_string)get_valid_filenameStorageFileSystemStorageDefaultStoragedefault_storageget_storage_classc               @   s   e Zd ZdZd"ddZd#ddZdd	 Zd
d Zd$ddZdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! ZdS )%r   z
    A base storage class, providing some default behaviors that all other
    storage systems can inherit or override, as necessary.
    rbc             C   s   | j ||S )z)Retrieve the specified file from storage.)_open)selfnamemode r   =/usr/lib/python3.6/site-packages/django/core/files/storage.pyopen"   s    zStorage.openNc             C   s<   |dkr|j }t|ds"t||}| j||d}| j||S )z
        Save new content to the file specified by name. The content should be
        a proper File object or any Python file-like object, ready to be read
        from the beginning.
        Nchunks)
max_length)r   hasattrr   get_available_name_save)r   r   contentr!   r   r   r   save&   s    

zStorage.savec             C   s   t |S )z
        Return a filename, based on the provided filename, that's suitable for
        use in the target storage system.
        )r   )r   r   r   r   r   get_valid_name8   s    zStorage.get_valid_namec             C   s   d|t d|f S )z
        Return an alternative filename, by adding an underscore and a random 7
        character alphanumeric string (before the file extension, if one
        exists) to the filename.
        z%s_%s%s   )r   )r   	file_rootfile_extr   r   r   get_alternative_name?   s    zStorage.get_alternative_namec             C   s   t jj|\}}t jj|\}}x| j|s<|rt||krt jj|| j||}|dkr\q"t|| }|dkr"|d|  }|std| t jj|| j||}q"W |S )z
        Return a filename that's free on the target storage system and
        available for new content to be written to.
        Nr   zStorage can not find an available filename for "%s". Please make sure that the corresponding file field allows sufficient "max_length".)	ospathsplitsplitextexistslenjoinr+   r   )r   r   r!   Zdir_name	file_namer)   r*   Z
truncationr   r   r   r#   G   s    zStorage.get_available_namec             C   s,   t jj|\}}t jjt jj|| j|S )z
        Validate the filename by calling get_valid_name() and return a filename
        to be passed to the save() method.
        )r,   r-   r.   normpathr2   r'   )r   filenamedirnamer   r   r   generate_filenamee   s    zStorage.generate_filenamec             C   s   t ddS )z
        Return a local filesystem path where the file can be retrieved using
        Python's built-in open() function. Storage systems that can't be
        accessed using open() should *not* implement this method.
        z,This backend doesn't support absolute paths.N)NotImplementedError)r   r   r   r   r   r-   n   s    zStorage.pathc             C   s   t ddS )zD
        Delete the specified file from the storage system.
        z4subclasses of Storage must provide a delete() methodN)r8   )r   r   r   r   r   deletey   s    zStorage.deletec             C   s   t ddS )z
        Return True if a file referenced by the given name already exists in the
        storage system, or False if the name is available for a new file.
        z5subclasses of Storage must provide an exists() methodN)r8   )r   r   r   r   r   r0      s    zStorage.existsc             C   s   t ddS )z
        List the contents of the specified path. Return a 2-tuple of lists:
        the first item being directories, the second item being files.
        z5subclasses of Storage must provide a listdir() methodN)r8   )r   r-   r   r   r   listdir   s    zStorage.listdirc             C   s   t ddS )zQ
        Return the total size, in bytes, of the file specified by name.
        z2subclasses of Storage must provide a size() methodN)r8   )r   r   r   r   r   size   s    zStorage.sizec             C   s   t ddS )zu
        Return an absolute URL where the file's contents can be accessed
        directly by a Web browser.
        z1subclasses of Storage must provide a url() methodN)r8   )r   r   r   r   r   url   s    zStorage.urlc             C   s   t ddS )z
        Return the last accessed time (as a datetime) of the file specified by
        name. The datetime will be timezone-aware if USE_TZ=True.
        z?subclasses of Storage must provide a get_accessed_time() methodN)r8   )r   r   r   r   r   get_accessed_time   s    zStorage.get_accessed_timec             C   s   t ddS )z
        Return the creation time (as a datetime) of the file specified by name.
        The datetime will be timezone-aware if USE_TZ=True.
        z>subclasses of Storage must provide a get_created_time() methodN)r8   )r   r   r   r   r   get_created_time   s    zStorage.get_created_timec             C   s   t ddS )z
        Return the last modified time (as a datetime) of the file specified by
        name. The datetime will be timezone-aware if USE_TZ=True.
        z?subclasses of Storage must provide a get_modified_time() methodN)r8   )r   r   r   r   r   get_modified_time   s    zStorage.get_modified_time)r   )N)N)__name__
__module____qualname____doc__r   r&   r'   r+   r#   r7   r-   r9   r0   r:   r;   r<   r=   r>   r?   r   r   r   r   r      s    


	c               @   s   e Zd ZdZejejB ejB eeddB Z	d.ddZ
dd Zd	d
 Zedd Zedd Zedd Zedd Zedd Zd/ddZdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- ZdS )0r   z%
    Standard filesystem storage
    ZO_BINARYr   Nc             C   s(   || _ || _|| _|| _tj| j d S )N)	_location	_base_url_file_permissions_mode_directory_permissions_moder	   connect_clear_cached_properties)r   locationbase_urlfile_permissions_modedirectory_permissions_moder   r   r   __init__   s
    zFileSystemStorage.__init__c             K   sp   |dkr&| j jdd | j jdd nF|dkr>| j jdd n.|dkrV| j jdd n|d	krl| j jd
d dS )z$Reset setting based property values.
MEDIA_ROOTbase_locationNrJ   	MEDIA_URLrK   FILE_UPLOAD_PERMISSIONSrL   !FILE_UPLOAD_DIRECTORY_PERMISSIONSrM   )__dict__pop)r   settingkwargsr   r   r   rI      s    z*FileSystemStorage._clear_cached_propertiesc             C   s   |d kr|S |S )Nr   )r   valuerV   r   r   r   _value_or_setting   s    z#FileSystemStorage._value_or_settingc             C   s   | j | jtjS )N)rY   rD   r   rO   )r   r   r   r   rP      s    zFileSystemStorage.base_locationc             C   s   t jj| jS )N)r,   r-   abspathrP   )r   r   r   r   rJ      s    zFileSystemStorage.locationc             C   s6   | j d k	r&| j jd r&|  j d7  _ | j| j tjS )N/)rE   endswithrY   r   rQ   )r   r   r   r   rK      s    zFileSystemStorage.base_urlc             C   s   | j | jtjS )N)rY   rF   r   rR   )r   r   r   r   rL      s    z'FileSystemStorage.file_permissions_modec             C   s   | j | jtjS )N)rY   rG   r   rS   )r   r   r   r   rM      s    z,FileSystemStorage.directory_permissions_moder   c             C   s   t t| j||S )N)r   r   r-   )r   r   r   r   r   r   r      s    zFileSystemStorage._openc       
      C   s  | j |}tj j|}yL| jd k	rRtjd}ztj|| jdd W d tj| X ntj|dd W n  tk
r   td| Y nX xyt|drt|j	 | ntj
|| jd}d }zTtj|tj x@|j D ]4}|d krt|trdnd}	tj||	}|j| qW W d tj| |d k	r*|j  n
tj| X W n* tk
rb   | j|}| j |}Y qX P qW | jd k	rtj|| j |jd	d
S )Nr   T)exist_okz!%s exists and is not a directory.temporary_file_pathi  wbZwt\r[   )r-   r,   r6   rM   umaskmakedirsFileExistsErrorr"   r   r^   r   OS_OPEN_FLAGSr   lockZLOCK_EXr    
isinstancebytesfdopenwriteZunlockcloser#   rL   chmodreplace)
r   r   r%   	full_path	directoryZ	old_umaskfd_filechunkr   r   r   r   r$      sF    







zFileSystemStorage._savec             C   sV   |st d| j|}y&tjj|r0tj| n
tj| W n tk
rP   Y nX d S )Nz-The name argument is not allowed to be empty.)AssertionErrorr-   r,   isdirrmdirremoveFileNotFoundError)r   r   r   r   r   r9   (  s    
zFileSystemStorage.deletec             C   s   t jj| j|S )N)r,   r-   r0   )r   r   r   r   r   r0   6  s    zFileSystemStorage.existsc             C   sR   | j |}g g  }}x4tj|D ]&}|j r:|j|j q |j|j q W ||fS )N)r-   r,   scandiris_dirappendr   )r   r-   Zdirectoriesfilesentryr   r   r   r:   9  s    

zFileSystemStorage.listdirc             C   s   t | j|S )N)r   rJ   )r   r   r   r   r   r-   C  s    zFileSystemStorage.pathc             C   s   t jj| j|S )N)r,   r-   getsize)r   r   r   r   r   r;   F  s    zFileSystemStorage.sizec             C   s8   | j d krtdt|}|d k	r,|jd}t| j |S )Nz&This file is not accessible via a URL.r[   )rK   
ValueErrorr   lstripr   )r   r   r<   r   r   r   r<   I  s    

zFileSystemStorage.urlc             C   s(   t jrtj|jtjdS tj|S dS )z
        If timezone support is enabled, make an aware datetime object in UTC;
        otherwise make a naive one in the local timezone.
        )tzinfoN)r   USE_TZr   utcfromtimestamprl   r
   utcfromtimestamp)r   tsr   r   r   _datetime_from_timestampQ  s    z*FileSystemStorage._datetime_from_timestampc             C   s   | j tjj| j|S )N)r   r,   r-   getatime)r   r   r   r   r   r=   \  s    z#FileSystemStorage.get_accessed_timec             C   s   | j tjj| j|S )N)r   r,   r-   getctime)r   r   r   r   r   r>   _  s    z"FileSystemStorage.get_created_timec             C   s   | j tjj| j|S )N)r   r,   r-   getmtime)r   r   r   r   r   r?   b  s    z#FileSystemStorage.get_modified_time)NNNN)r   )r@   rA   rB   rC   r,   O_WRONLYO_CREATO_EXCLgetattrrd   rN   rI   rY   r   rP   rJ   rK   rL   rM   r   r$   r9   r0   r:   r-   r;   r<   r   r=   r>   r?   r   r   r   r   r      s.    

?
c             C   s   t | p
tjS )N)r   r   DEFAULT_FILE_STORAGE)Zimport_pathr   r   r   r   f  s    c               @   s   e Zd Zdd ZdS )r   c             C   s   t   | _d S )N)r   _wrapped)r   r   r   r   _setupk  s    zDefaultStorage._setupN)r@   rA   rB   r   r   r   r   r   r   j  s   )r   r   r   r   r   )N)&r,   r   urllib.parser   django.confr   django.core.exceptionsr   django.core.filesr   r   Zdjango.core.files.mover   django.core.signalsr	   django.utilsr
   django.utils._osr   django.utils.cryptor   django.utils.deconstructr   django.utils.encodingr   django.utils.functionalr   r   django.utils.module_loadingr   django.utils.textr   __all__r   r   r   r   r   r   r   r   r   <module>   s2      6
