Lichen

lib/__builtins__/sequence.py

227:3a4ba5788f0f
2016-11-23 Paul Boddie Fixed list and tuple initialisation via their initialisers. Introduced generic string representation support for sequences. Removed superfluous tuple native functions. Added element-setting and size-setting native functions for fragments. Added __setitem__ support for sequences. Added initialisation and serialisation tests for lists and tuples.
     1 #!/usr/bin/env python     2      3 """     4 Sequence operations.     5      6 Copyright (C) 2015, 2016 Paul Boddie <paul@boddie.org.uk>     7      8 This program is free software; you can redistribute it and/or modify it under     9 the terms of the GNU General Public License as published by the Free Software    10 Foundation; either version 3 of the License, or (at your option) any later    11 version.    12     13 This program is distributed in the hope that it will be useful, but WITHOUT    14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS    15 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more    16 details.    17     18 You should have received a copy of the GNU General Public License along with    19 this program.  If not, see <http://www.gnu.org/licenses/>.    20 """    21     22 from native import _isinstance    23     24 class sequence:    25     26     "A common base class for sequence types."    27     28     def _str(self, opening, closing):    29     30         "Serialise this object with the given 'opening' and 'closing' strings."    31     32         b = buffer()    33         i = 0    34         l = self.__len__()    35         first = True    36     37         b.append(opening)    38         while i < l:    39             if first:    40                 first = False    41             else:    42                 b.append(", ")    43             b.append(repr(self.__get_single_item__(i)))    44             i += 1    45         b.append(closing)    46     47         return str(b)    48     49     def __getitem__(self, index):    50     51         "Return the item or slice specified by 'index'."    52     53         # Normalise any integer indexes, converting negative indexes to positive    54         # ones.    55     56         if _isinstance(index, int):    57             index = _normalise_index(index, self.__len__())    58             return self.__get_single_item__(index)    59     60         # Handle slices separately.    61     62         elif _isinstance(index, slice):    63             return self.__getslice__(index.start, index.end)    64     65         # No other kinds of objects are supported as indexes.    66     67         else:    68             raise TypeError    69     70     def __setitem__(self, index, value):    71     72         "Set at 'index' the given 'value'."    73     74         # Normalise any integer indexes, converting negative indexes to positive    75         # ones.    76     77         if _isinstance(index, int):    78             index = _normalise_index(index, self.__len__())    79             return self.__set_single_item__(index, value)    80     81         # Handle slices separately.    82     83         elif _isinstance(index, slice):    84             return self.__setslice__(index.start, index.end, value)    85     86         # No other kinds of objects are supported as indexes.    87     88         else:    89             raise TypeError    90     91     def __getslice__(self, start, end=None):    92     93         "Return a slice starting from 'start', with the optional 'end'."    94     95         length = self.__len__()    96     97         # Handle a null start as the first position, otherwise normalising any    98         # start index.    99    100         if start is None:   101             start = 0   102         else:   103             start = _normalise_index(start, length)   104    105         # Handle a null end as the first position after the end of the sequence,   106         # otherwise normalising any end index.   107    108         if end is None:   109             end = length   110         else:   111             end = _normalise_index(end, length)   112    113         result = []   114    115         while start < end:   116             result.append(self.__get_single_item__(start))   117             start += 1   118    119         return result   120    121 def _get_absolute_index(index, length):   122    123     """   124     Return the absolute index for 'index' given a collection having the   125     specified 'length'.   126     """   127    128     if index < 0:   129         return length + index   130     else:   131         return index   132    133 def _normalise_index(index, length):   134    135     "Normalise 'index' for a collection having the specified 'length'."   136    137     return _min(length, _max(0, _get_absolute_index(index, length)))   138    139 def _max(x, y):   140    141     "Return the maximum of 'x' and 'y'."   142    143     if x >= y:   144         return x   145     else:   146         return y   147    148 def _min(x, y):   149    150     "Return the minimum of 'x' and 'y'."   151    152     if x <= y:   153         return x   154     else:   155         return y   156    157 def _tuple(l): pass   158    159 # vim: tabstop=4 expandtab shiftwidth=4