
    ob&                         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"                  rd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e      Z ed      Zy)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                       e Zd ZdZddZd Zd Zed        Zd Z		 	 	 	 ddZ
	 	 	 	 ddZej                  	 	 	 dd	       Zy
)Registryz"A registry for `Opener` instances.c                 .    || _         || _        i | _        y)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   s      4/usr/lib/python3/dist-packages/fs/opener/registry.py__init__zRegistry.__init__   s     -&    c                 8    dj                  | j                        S )Nz<fs-registry {!r}>)format	protocols)r   s    r   __repr__zRegistry.__repr__+   s    #**4>>::r    c                     t        |t              r|n |       }t        |t              sJ d       |j                  sJ d       |j                  D ]  }|| j                  |<    |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protocols       r   installzRegistry.install/   si    " 'vv6&FH'6*F,FF*  C"CC )) 	0H(/DOOH%	0r    c                     t        | j                        }| j                  rS|j                  d t	        j
                  d      D               t        t        j                  j                  |            }|S )z(`list`: the list of supported protocols.c              3   4   K   | ]  }|j                     y w)N)name).0entry_points     r   	<genexpr>z%Registry.protocols.<locals>.<genexpr>M   s         s   	fs.opener)	listr   r   extendpkg_resourcesiter_entry_pointscollectionsOrderedDictfromkeys)r   r   s     r   r#   zRegistry.protocolsG   sd     $//*
 #0#B#B;#O  k55>>zJKJr    c                    |xs | j                   }| j                  r!t        t        j                  d|      d      }nd}|9|| j
                  v r| j
                  |   }|S t        dj                  |            	 |j                         }t        |t              st        d      	  |       }|S # t        $ r}t        dj                  |            d}~ww xY w# t        $ r}t        dj                  |            d}~ww xY 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.

        r1   Nzprotocol '{}' is not supportedzcould not load entry point; {}z$entry point did not return an openerz could not instantiate opener; {})r   r   nextr4   r5   r   r   r"   load	Exceptionr
   
issubclassr	   )r   r)   r/   opener_instancer'   	exceptions         r   
get_openerzRegistry.get_openerT   s   $ 2t22//XFK K 4??*"&//(";0 - *4;;HE $))+
 ff-%&LMM"((   %4;;IF   %6==iH s0   <B1 (C 1	C:CC	D%C??Dc                     d|vrdj                  ||      }t        |      }|j                  }|j                  }| 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)   pathr@   open_fs)r   fs_url	writeablecreatecwddefault_protocolparse_resultr)   	open_pathr'   rC   s              r   openzRegistry.open   sn    4 %%&6?F#F+(( %%	*..y&#N	!!r    c                 d    ddl m} t        ||      r|}|S | j                  |||||      \  }}|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   )rE   rF   rG   rH   )baser   r&   rK   )	r   rD   rE   rF   rG   rH   r   _fs_paths	            r   rC   zRegistry.open_fs   sM    F 	fb!C 
 #!1 # JC 
r    c              #      K   ddl m} d }t        ||      r|r ||       | y| j                  ||||      }|r ||       	 | |j	                          y# |j	                          w xY w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                 \    | j                         j                  dd      rt        d      y )N	read_onlyT/)rB   )getmetagetr   )fss    r   assert_writeablez,Registry.manage_fs.<locals>.assert_writeable  s(    zz|T2&C00 3r    )rF   rE   rG   N)rM   r   r&   rC   close)r   rD   rF   rE   rG   r   rW   rN   s           r   	manage_fszRegistry.manage_fs   sj     Z 		1 fb! (L,,vf	s,SC %					s   AA1A A1A..A1N)osfsF)TF.rZ   )FFr[   rZ   )FFr[   )__name__
__module____qualname____doc__r   r$   r*   propertyr#   r@   rK   rC   
contextlibcontextmanagerrY    r    r   r   r      s{    , ;0 
 
7x %"T /b  = =r    r   T)r   )r_   
__future__r   r   r   typingr6   ra   r4   errorsr   rM   r	   r
   r   parser   TYPE_CHECKINGr   r   r   r   r   r   r   r   r   objectr   registryrc   r    r   <module>rk      s[    I H     %  8 	OOOKv K\ %r    