o
    pf&                     @   s   d Z ddlmZmZmZ ddlZddlZddlZddlZddl	m
Z
 ddlmZ ddl	mZmZ dd	lmZ ejrSdd
lmZmZmZmZmZmZmZmZ ddlmZ G dd deZeddZdS )zB`Registry` class mapping protocols and FS URLs to their `Opener`.
    )absolute_importprint_functionunicode_literalsN   )ResourceReadOnly   )Opener)EntryPointErrorUnsupportedProtocol)parse_fs_url)CallableDictIteratorListTextTupleTypeUnionFSc                   @   sx   e Zd ZdZdddZdd Zdd	 Zed
d Zdd Z					dddZ
				dddZej			dddZdS )Registryz"A registry for `Opener` instances.osfsFc                 C   s   || _ || _i | _dS )a  Create a registry object.

        Arguments:
            default_opener (str, optional): The protocol to use, if one
                is not supplied. The default is to use 'osfs', so that the
                FS URL is treated as a system path if no protocol is given.
            load_extern (bool, optional): Set to `True` to load openers from
                PyFilesystem2 extensions. Defaults to `False`.

        N)default_openerload_extern
_protocols)selfr   r    r   K/home/ertert/spirit/venv/lib/python3.10/site-packages/fs/opener/registry.py__init__   s   
zRegistry.__init__c                 C   s   d | jS )Nz<fs-registry {!r}>)format	protocols)r   r   r   r   __repr__+   s   zRegistry.__repr__c                 C   sN   t |tr|n| }t |tsJ d|jsJ d|jD ]}|| j|< q|S )a  Install an opener.

        Arguments:
            opener (`Opener`): an `Opener` instance, or a callable that
                returns an opener instance.

        Note:
            May be used as a class decorator. For example::

                registry = Registry()
                @registry.install
                class ArchiveOpener(Opener):
                    protocols = ['zip', 'tar']

        zOpener instance requiredzmust list one or more protocols)
isinstancer   r    r   )r   opener_openerprotocolr   r   r   install/   s   
zRegistry.installc                 C   s>   t | j}| jr|dd tdD  t tj|}|S )z(`list`: the list of supported protocols.c                 s   s    | ]}|j V  qd S )N)name).0entry_pointr   r   r   	<genexpr>M   s
    
z%Registry.protocols.<locals>.<genexpr>	fs.opener)	listr   r   extendpkg_resourcesiter_entry_pointscollectionsOrderedDictfromkeys)r   r   r   r   r   r    G   s   

zRegistry.protocolsc              
   C   s   |p| j }| jrttd|d}nd}|du r+|| jv r$| j| }|S td|z| }W n t	yD } zt
d|d}~ww t|tsNt
dz| }W |S  t	yg } zt
d|d}~ww )a  Get the opener class associated to a given protocol.

        Arguments:
            protocol (str): A filesystem protocol.

        Returns:
            Opener: an opener instance.

        Raises:
            ~fs.opener.errors.UnsupportedProtocol: If no opener
                could be found for the given protocol.
            EntryPointLoadingError: If the returned entry point
                is not an `Opener` subclass or could not be loaded
                successfully.

        r+   Nzprotocol '{}' is not supportedzcould not load entry point; {}z$entry point did not return an openerz could not instantiate opener; {})r   r   nextr.   r/   r   r
   r   load	Exceptionr	   
issubclassr   )r   r%   r)   opener_instancer#   	exceptionr   r   r   
get_openerT   s@   



zRegistry.get_openerT.c                 C   sL   d|vr
d ||}t|}|j}|j}| |}	|	|||||}
|
|fS )aX  Open a filesystem from a FS URL.

        Returns a tuple of a filesystem object and a path. If there is
        no path in the FS URL, the path value will be `None`.

        Arguments:
            fs_url (str): A filesystem URL.
            writeable (bool, optional): `True` if the filesystem must be
                writeable.
            create (bool, optional): `True` if the filesystem should be
                created if it does not exist.
            cwd (str): The current working directory.

        Returns:
            (FS, str): a tuple of ``(<filesystem>, <path from url>)``

        z://z{}://{})r   r   r%   pathr9   open_fs)r   fs_url	writeablecreatecwddefault_protocolparse_resultr%   	open_pathr#   r<   r   r   r   open   s   
zRegistry.openc           	      C   s:   ddl m} t||r|}|S | j|||||d\}}|S )az  Open a filesystem from a FS URL (ignoring the path component).

        Arguments:
            fs_url (str): A filesystem URL. If a filesystem instance is
                given instead, it will be returned transparently.
            writeable (bool, optional): `True` if the filesystem must
                be writeable.
            create (bool, optional): `True` if the filesystem should be
                created if it does not exist.
            cwd (str): The current working directory (generally only
                relevant for OS filesystems).
            default_protocol (str): The protocol to use if one is not
                supplied in the FS URL (defaults to ``"osfs"``).

        Returns:
            ~fs.base.FS: A filesystem instance.

        Caution:
            The ``writeable`` parameter only controls whether the
            filesystem *needs* to be writable, which is relevant for
            some archive filesystems. Passing ``writeable=False`` will
            **not** make the return filesystem read-only. For this,
            consider using `fs.wrap.read_only` to wrap the returned
            instance.

        r   r   )r>   r?   r@   rA   )baser   r"   rD   )	r   r=   r>   r?   r@   rA   r   _fs_pathr   r   r   r<      s   #
	
zRegistry.open_fsc                 c   st    ddl m} dd }t||r|r|| |V  dS | j||||d}|r*|| z
|V  W |  dS |  w )a*  Get a context manager to open and close a filesystem.

        Arguments:
            fs_url (FS or str): A filesystem instance or a FS URL.
            create (bool, optional): If `True`, then create the filesystem if
                it doesn't already exist.
            writeable (bool, optional): If `True`, then the filesystem
                must be writeable.
            cwd (str): The current working directory, if opening a
                `~fs.osfs.OSFS`.

        Sometimes it is convenient to be able to pass either a FS object
        *or* an FS URL to a function. This context manager handles the
        required logic for that.

        Example:
            The `~Registry.manage_fs` method can be used to define a small
            utility function::

                >>> def print_ls(list_fs):
                ...     '''List a directory.'''
                ...     with manage_fs(list_fs) as fs:
                ...         print(' '.join(fs.listdir()))

            This function may be used in two ways. You may either pass
            a ``str``, as follows::

                >>> print_list('zip://projects.zip')

            Or, an filesystem instance::

                >>> from fs.osfs import OSFS
                >>> projects_fs = OSFS('~/')
                >>> print_list(projects_fs)

        r   r   c                 S   s   |   ddrtddd S )N	read_onlyT/)r;   )getmetagetr   )fsr   r   r   assert_writeable  s   
z,Registry.manage_fs.<locals>.assert_writeable)r?   r>   r@   N)rE   r   r"   r<   close)r   r=   r?   r>   r@   r   rM   rF   r   r   r   	manage_fs   s   -

zRegistry.manage_fsN)r   F)TFr:   r   )FFr:   r   )FFr:   )__name__
__module____qualname____doc__r   r!   r&   propertyr    r9   rD   r<   
contextlibcontextmanagerrO   r   r   r   r   r      s.    

<
*
1r   T)r   )rS   
__future__r   r   r   typingr0   rU   r.   errorsr   rE   r   r	   r
   parser   TYPE_CHECKINGr   r   r   r   r   r   r   r   r   objectr   registryr   r   r   r   <module>   s"   (  