Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
22144 views
o

�Ul_0B�@szdZddlZddlZddlZddlmZddlmZddlm	Z	Gdd�de
ee	�ZGdd	�d	ee	�ZGd
d�de�Z
dS)a�
Improved container classes
==========================

The ``containers`` module defines improved container classes, such as lists:

 * `List`: a subclass of the builtin ``list`` class,  with added methods, such as ``index_append``;
 * `Bijectivelist`: a replacement for the ``list`` class for use with 1-1 relationships
    where index lookup via ``dict`` makes sense; and
 * `ShelveBijectivelist`: a replacement for the ``list`` class for use with 1-1 relationships
    where index lookup via ``shelve`` makes sense.
    This class uses ``shelve`` to cope with cases where a ``dict`` would be too large to store in memory.

AUTHORS:

- Paul Leopardi (2016-08-21): initial version

�N)�tmp_filename)�
SageObject)�Saveablec@seZdZdZdd�ZdS)�Lista�
    Subclass of ``list`` with added methods, such as ``index_append``.

    TESTS:

    ::

        sage: from boolean_cayley_graphs.containers import List
        sage: L = List([1,2,4])
        sage: print(L)
        [1, 2, 4]

        sage: from boolean_cayley_graphs.containers import List
        sage: L = List([1,2,4])
        sage: latex(L)
        \text{\texttt{[1,{ }2,{ }4]}}
    cCs8z|�|�}W|Styt|�}|�|�Y|Sw)ax
        Return the index of a given item, appending it if necessary.

        If the inherited list ``index`` method for ``self`` yields a ``ValueError`,
        then set result to the length of `self``, and append item to ``self``.

        INPUT:

        - ``self`` -- the current object.
        - ``item`` -- the item to look up, and append if necessary.

        OUTPUT:

        A non-negative integer indicating the index of ``item`` within ``self``.

        EFFECT:

        The item ``item`` may be appended to ``self``.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.containers import List
            sage: L = List([1,2,4])
            sage: L.index_append(2)
            1
            sage: L
            [1, 2, 4]
            sage: L.index_append(3)
            3
            sage: L
            [1, 2, 4, 3]
            sage: del L
        )�index�
ValueError�len�append��self�item�result�r�D/home/user/Boolean-Cayley-graphs/boolean_cayley_graphs/containers.py�index_append:s$��zList.index_appendN)�__name__�
__module__�__qualname__�__doc__rrrrrr&src@sreZdZdZddd�Zdd�Zdd�Zd	d
�Zdd�Zd
d�Z	dd�Z
dd�Zdd�Zdd�Z
dd�Zdd�ZdS)�
BijectiveLista�
    Replacement for the ``list`` class with only a few methods,
    such as ``__getitem__``, ``index``, and ``index_append``.

    List lookup for ``__getitem__`` uses a list named ``_item``.
    Index lookup for ``index`` and ``index_append`` uses a dict named ``_index`.
    This class is used for 1-1 relationships where index lookup via ``dict`` makes sense.

    .. WARNING::

        Initialization from a non-empty list can easily break
        the 1-1 relationship between index and item in a ``BijectiveList``.

    EXAMPLES:

    Initialize from a list.

    ::

        sage: from boolean_cayley_graphs.containers import BijectiveList
        sage: BL = BijectiveList(["1","2","3"])
        sage: BL.get_list()
        ['1', '2', '3']
        sage: dict(sorted(BL.get_dict().items()))
        {'1': 0, '2': 1, '3': 2}
        sage: del BL

    TESTS:

    ::

        sage: from boolean_cayley_graphs.containers import BijectiveList
        sage: L = BijectiveList([1,2,4])
        sage: print(L)
        BijectiveList(1,2,4)

        sage: from boolean_cayley_graphs.containers import BijectiveList
        sage: L = BijectiveList([1,2,4])
        sage: latex(L)
        \text{\texttt{BijectiveList(1,2,4)}}
    NcsB�dkrg|_i|_dS�|_t�fdd�tt���D��|_dS)a�
        Constructor.

        EXAMPLES:

        Default initialization.

        ::

            sage: from boolean_cayley_graphs.containers import BijectiveList
            sage: BL = BijectiveList()
            sage: BL.get_list()
            []
            sage: BL.get_dict()
            {}
            sage: del BL

        TESTS:

        Initialize from a list.

        ::

            sage: from boolean_cayley_graphs.containers import BijectiveList
            sage: BL = BijectiveList(["1","2","6"])
            sage: BL.get_list()
            ['1', '2', '6']
            sage: dict(sorted(BL.get_dict().items()))
            {'1': 0, '2': 1, '6': 2}
            sage: del BL
        Nc3s�|]	}�||fVqdS�Nr)�.0r��
other_listrr�	<genexpr>�s��z)BijectiveList.__init__.<locals>.<genexpr>)�_item�_index�dict�ranger)rrrrr�__init__�s 

�zBijectiveList.__init__cCs(t|�jdd�dd�|jD��dS)a>
        Sage string representation.

        INPUT:

        - ``self`` -- the current object.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.containers import BijectiveList
            sage: L = BijectiveList([1,2,4])
            sage: print(L)
            BijectiveList(1,2,4)
        �(�,cSsg|]}t|��qSr)�repr)rrrrr�
<listcomp>�sz(BijectiveList._repr_.<locals>.<listcomp>�))�typer�joinr�rrrr�_repr_�s����zBijectiveList._repr_cCs
|j|S)ai
        List lookup by index.

        INPUT:

        - ``self`` -- the current object.
        - ``index`` -- the index to look up.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.containers import BijectiveList
            sage: BL = BijectiveList([1,2,3])
            sage: BL[2]
            3
            sage: del BL
        �r)rrrrr�__getitem__�s
zBijectiveList.__getitem__cCs
t|j�S)aD
        Get the length of the list.

        INPUT:

        - ``self`` -- the current object.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.containers import BijectiveList
            sage: BL = BijectiveList([1,2,3])
            sage: len(BL)
            3
            sage: del BL
        )rrr'rrr�__len__�s
zBijectiveList.__len__cC�|jS)a�
        Get the ``dict`` part of the ``BijectiveList``.

        INPUT:

        - ``self`` -- the current object.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.containers import BijectiveList
            sage: BL = BijectiveList([1,2,5])
            sage: dict(sorted(BL.get_dict().items()))
            {1: 0, 2: 1, 5: 2}
            sage: del BL
        )rr'rrr�get_dict�szBijectiveList.get_dictcCr,)ag
        Get the ``list`` part of the ``BijectiveList``.

        INPUT:

        - ``self`` -- the current object.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.containers import BijectiveList
            sage: BL = BijectiveList([1,2,5])
            sage: BL.get_list()
            [1, 2, 5]
            sage: del BL

        r)r'rrr�get_listszBijectiveList.get_listcCs.z|j|}W|Stytd�|���w)a�
        Return the index of a given item.

        Use a ``dict`` lookup using ``_index`` instead of calling ``index`` on the list.
        If the ``dict`` lookup yields a ``KeyError`` then raise a ``ValueError``.

        INPUT:

        - ``self`` -- the current object.
        - ``item`` -- the item to look up.

        OUTPUT:

        A non-negative integer indicating the index of ``item`` within ``self``.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.containers import BijectiveList
            sage: BL = BijectiveList([1,2,4])
            sage: BL.index(2)
            1
            sage: BL.get_list()
            [1, 2, 4]
            sage: dict(sorted(BL.get_dict().items()))
            {1: 0, 2: 1, 4: 2}
            sage: del BL

        TESTS:

        ::

            sage: from boolean_cayley_graphs.containers import BijectiveList
            sage: BL = BijectiveList([1,2,4])
            sage: try:
            ....:     BL.index(3)
            ....: except ValueError as e:
            ....:     print("ValueError: {0}".format(e.args[0]))
            ....: finally:
            ....:     del BL
            ValueError: 3 is not in list
        z{} is not in list)r�KeyErrorr�formatr
rrrr's,��zBijectiveList.indexcCsFz|j|}W|Sty"t|j�}|j�|�||j|<Y|Sw)aQ
        Return the index of a given item, appending it if necessary.

        Use a ``dict`` lookup using ``_index`` instead of calling ``index`` on the list.
        If the dict lookup yields a `KeyError`` then set result to the length of ``self``,
        append item to ``self``, and add result to ``_index``.

        INPUT:

        - ``self`` -- the current object.
        - ``item`` -- the item to look up, and append if necessary.

        OUTPUT:

        A non-negative integer indicating the index of ``item`` within ``self``.

        EFFECT:

        The item ``item`` may be appended to ``self``.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.containers import BijectiveList
            sage: BL = BijectiveList([1,2,4])
            sage: BL.index_append(2)
            1
            sage: BL.get_list()
            [1, 2, 4]
            sage: BL.index_append(3)
            3
            sage: BL.get_list()
            [1, 2, 4, 3]
            sage: dict(sorted(BL.get_dict().items()))
            {1: 0, 2: 1, 3: 3, 4: 2}
            sage: del BL
        )rr/rrr	r
rrrrZs'�
�zBijectiveList.index_appendcC�dS)a$
        Dummy method to match the interface of ``ShelveBijectiveList``.

        TESTS:

        ::

            sage: from boolean_cayley_graphs.containers import BijectiveList
            sage: BL = BijectiveList(["1","2","6"])
            sage: BL.sync()
            sage: del BL
        Nrr'rrr�sync��
zBijectiveList.synccCr1)a4
        Dummy method to match the interface of ``ShelveBijectiveList``.

        TESTS:

        ::

            sage: from boolean_cayley_graphs.containers import BijectiveList
            sage: BL = BijectiveList(["1","2","6"])
            sage: BL.close_dict()
            sage: BL.remove_dict()
        Nrr'rrr�
close_dict�r3zBijectiveList.close_dictcCs z|`WdStyYdSw)a�
        Remove the dictionary.

        TESTS:

        ::

            sage: from boolean_cayley_graphs.containers import BijectiveList
            sage: BL = BijectiveList(["1","2","6"])
            sage: BL.close_dict()
            sage: BL.remove_dict()
            sage: try:
            ....:     BL._index
            ....: except AttributeError:
            ....:     pass
        N)r�AttributeErrorr'rrr�remove_dict�s

�zBijectiveList.remove_dictcC�|��|��dS)a�
        Clean up by closing and removing the dictionary,
        before deleting the current object.

        TESTS:

        ::

            sage: from boolean_cayley_graphs.containers import BijectiveList
            sage: BL = BijectiveList(["1","2","6"])
            sage: del BL
            sage: try:
            ....:     BL
            ....: except NameError:
            ....:     pass
        N�r4r6r'rrr�__del__�szBijectiveList.__del__r)rrrrrr(r*r+r-r.rrr2r4r6r9rrrrrfs
))30rc@s:eZdZdZd
dd�Zdd�Zdd�Zd	d
�Zdd�ZdS)�ShelveBijectiveLista
    Replacement for the ``list`` class with only a few methods,
    such as ``__getitem__``, ``index``, and ``index_append``.

    List lookup for ``__getitem__`` uses a list named ``_item``.
    Index lookup for ``index`` and ``index_append`` uses a ``shelve`` named ``_index``.
    This class is used for 1-1 relationships where index lookup via ``shelve`` makes sense.

    .. NOTE::

        This class uses ``shelve`` to cope with situations
        where a ``dict`` would be too large to fit into memory.

    .. WARNING::

        Initialization from a non-empty list works only for lists of strings.

    .. WARNING::

        Initialization from a non-empty list can easily break
        the 1-1 relationship between index and item in a ``ShelveBijectiveList``.

    EXAMPLES:

    Initialize from a list.

    ::

        sage: from boolean_cayley_graphs.containers import ShelveBijectiveList
        sage: SBL = ShelveBijectiveList(["1","2","4"])
        sage: SBL.get_list()
        ['1', '2', '4']
        sage: dict(sorted(SBL.get_dict().items()))
        {'1': 0, '2': 1, '4': 2}
        sage: del SBL

    TESTS:

    ::

        sage: from boolean_cayley_graphs.containers import ShelveBijectiveList
        sage: L = ShelveBijectiveList(["1","2","4"])
        sage: print(L)
        ShelveBijectiveList('1','2','4')

        sage: from boolean_cayley_graphs.containers import ShelveBijectiveList
        sage: L = ShelveBijectiveList(["1","2","4"])
        sage: latex(L)
        \text{\texttt{ShelveBijectiveList('1','2','4')}}
    NcCsftdd�|_|��tj|jdd�|_|dkrg|_dS||_tt|��D]}||}||j|<q%dS)a�
        Constructor.

        EXAMPLES:

        Default initialization.

        ::

            sage: from boolean_cayley_graphs.containers import ShelveBijectiveList
            sage: SBL = ShelveBijectiveList()
            sage: SBL.get_list()
            []
            sage: dict(SBL.get_dict())
            {}
            sage: del SBL

        TESTS:

        Initialize from a list.

        ::

            sage: from boolean_cayley_graphs.containers import ShelveBijectiveList
            sage: SBL = ShelveBijectiveList(["1","2","6"])
            sage: SBL.get_list()
            ['1', '2', '6']
            sage: dict(sorted(SBL.get_dict().items()))
            {'1': 0, '2': 1, '6': 2}
            sage: del SBL
        z.index)�ext�n)�flagN)	r�shelve_file_namer6�shelve�openrrrr)rrrrrrrr	s 
�zShelveBijectiveList.__init__cC�|j��dS)a0
        Synchronize the persistent dictionary on disk, if feasible.

        TESTS:

        ::

            sage: from boolean_cayley_graphs.containers import ShelveBijectiveList
            sage: SBL = ShelveBijectiveList(["1","2","6"])
            sage: SBL.sync()
            sage: del SBL
         N)rr2r'rrrr26�
zShelveBijectiveList.synccCrA)a<
        Synchronize and close the persistent dictionary on disk.

        TESTS:

        ::

            sage: from boolean_cayley_graphs.containers import ShelveBijectiveList
            sage: SBL = ShelveBijectiveList(["1","2","6"])
            sage: SBL.close_dict()
            sage: SBL.remove_dict()
        N)r�closer'rrrr4FrBzShelveBijectiveList.close_dictcCs0t�|jd�D]
}tj�|�rt�|�qdS)a�
        Remove the files used for the persistent dictionary on disk.

        .. WARNING::

            Use ``close_dict`` first.

        TESTS:

        ::

            sage: import glob
            sage: from boolean_cayley_graphs.containers import ShelveBijectiveList
            sage: SBL = ShelveBijectiveList(["1","2","6"])
            sage: SBL.close_dict()
            sage: SBL.remove_dict()
            sage: glob.glob(SBL.shelve_file_name + "*")
            []
        �*N)�globr>�os�path�isfile�remove)r�	file_namerrrr6Vs

��zShelveBijectiveList.remove_dictcCr7)ah
        Clean up by closing the persistent dictionary on disk, and
        removing the files used for it, before deleting the current object.

        TESTS:

        ::

            sage: import glob
            sage: from boolean_cayley_graphs.containers import ShelveBijectiveList
            sage: SBL = ShelveBijectiveList(["1","2","6"])
            sage: shelve_file_name = SBL.shelve_file_name
            sage: del SBL
            sage: glob.glob(shelve_file_name + "*")
            []
            sage: try:
            ....:     SBL
            ....: except NameError:
            ....:     pass
        Nr8r'rrrr9oszShelveBijectiveList.__del__r)	rrrrrr2r4r6r9rrrrr:�s
2-r:)rrErFr?�sage.misc.temporary_filer�sage.structure.sage_objectr�boolean_cayley_graphs.saveabler�listrrr:rrrr�<module>s@r