github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-runtime-src/third_party/pypy/_collections.py (about)

     1  """High performance data structures
     2  """
     3  #
     4  # Copied and completed from the sandbox of CPython
     5  #   (nondist/sandbox/collections/pydeque.py rev 1.1, Raymond Hettinger)
     6  #
     7  
     8  # Note that PyPy also contains a built-in module '_collections' which will hide
     9  # this one if compiled in.
    10  
    11  # try:
    12  #     from threading import _get_ident as _thread_ident
    13  # except ImportError:
    14  #     def _thread_ident():
    15  #         return -1
    16  
    17  import thread
    18  _thread_ident = thread.get_ident
    19  
    20  n = 30
    21  LFTLNK = n
    22  RGTLNK = n+1
    23  BLOCKSIZ = n+2
    24  
    25  # The deque's size limit is d.maxlen.  The limit can be zero or positive, or
    26  # None.  After an item is added to a deque, we check to see if the size has
    27  # grown past the limit. If it has, we get the size back down to the limit by
    28  # popping an item off of the opposite end.  The methods that can trigger this
    29  # are append(), appendleft(), extend(), and extendleft().
    30  
    31  class deque(object):
    32  
    33      def __new__(cls, iterable=(), *args, **kw):
    34          self = super(deque, cls).__new__(cls)
    35          self.clear()
    36          return self
    37  
    38      def __init__(self, iterable=(), maxlen=None):
    39          self.clear()
    40          if maxlen is not None:
    41              if maxlen < 0:
    42                  raise ValueError("maxlen must be non-negative")
    43          self._maxlen = maxlen
    44          add = self.append
    45          for elem in iterable:
    46              add(elem)
    47  
    48      # @property
    49      def maxlen(self):
    50          return self._maxlen
    51      # TODO: Make this a decorator once they're implemented.
    52      maxlen = property(maxlen)
    53      def clear(self):
    54          self.right = self.left = [None] * BLOCKSIZ
    55          self.rightndx = n//2   # points to last written element
    56          self.leftndx = n//2+1
    57          self.length = 0
    58          self.state = 0
    59  
    60      def append(self, x):
    61          self.state += 1
    62          self.rightndx += 1
    63          if self.rightndx == n:
    64              newblock = [None] * BLOCKSIZ
    65              self.right[RGTLNK] = newblock
    66              newblock[LFTLNK] = self.right
    67              self.right = newblock
    68              self.rightndx = 0
    69          self.length += 1
    70          self.right[self.rightndx] = x
    71          if self.maxlen is not None and self.length > self.maxlen:
    72              self.popleft()
    73  
    74      def appendleft(self, x):
    75          self.state += 1
    76          self.leftndx -= 1
    77          if self.leftndx == -1:
    78              newblock = [None] * BLOCKSIZ
    79              self.left[LFTLNK] = newblock
    80              newblock[RGTLNK] = self.left
    81              self.left = newblock
    82              self.leftndx = n-1
    83          self.length += 1
    84          self.left[self.leftndx] = x
    85          if self.maxlen is not None and self.length > self.maxlen:
    86              self.pop()
    87  
    88      def extend(self, iterable):
    89          if iterable is self:
    90              iterable = list(iterable)
    91          for elem in iterable:
    92              self.append(elem)
    93  
    94      def extendleft(self, iterable):
    95          if iterable is self:
    96              iterable = list(iterable)
    97          for elem in iterable:
    98              self.appendleft(elem)
    99  
   100      def pop(self):
   101          if self.left is self.right and self.leftndx > self.rightndx:
   102              raise IndexError("pop from an empty deque")
   103          x = self.right[self.rightndx]
   104          self.right[self.rightndx] = None
   105          self.length -= 1
   106          self.rightndx -= 1
   107          self.state += 1
   108          if self.rightndx == -1:
   109              prevblock = self.right[LFTLNK]
   110              if prevblock is None:
   111                  # the deque has become empty; recenter instead of freeing block
   112                  self.rightndx = n//2
   113                  self.leftndx = n//2+1
   114              else:
   115                  prevblock[RGTLNK] = None
   116                  self.right[LFTLNK] = None
   117                  self.right = prevblock
   118                  self.rightndx = n-1
   119          return x
   120  
   121      def popleft(self):
   122          if self.left is self.right and self.leftndx > self.rightndx:
   123              raise IndexError("pop from an empty deque")
   124          x = self.left[self.leftndx]
   125          self.left[self.leftndx] = None
   126          self.length -= 1
   127          self.leftndx += 1
   128          self.state += 1
   129          if self.leftndx == n:
   130              prevblock = self.left[RGTLNK]
   131              if prevblock is None:
   132                  # the deque has become empty; recenter instead of freeing block
   133                  self.rightndx = n//2
   134                  self.leftndx = n//2+1
   135              else:
   136                  prevblock[LFTLNK] = None
   137                  self.left[RGTLNK] = None
   138                  self.left = prevblock
   139                  self.leftndx = 0
   140          return x
   141  
   142      def count(self, value):
   143          c = 0
   144          for item in self:
   145              if item == value:
   146                  c += 1
   147          return c
   148  
   149      def remove(self, value):
   150          # Need to defend mutating or failing comparisons
   151          i = 0
   152          try:
   153              for i in range(len(self)):
   154                  if self[0] == value:
   155                      self.popleft()
   156                      return
   157                  self.append(self.popleft())
   158              i += 1
   159              raise ValueError("deque.remove(x): x not in deque")
   160          finally:
   161              self.rotate(i)
   162  
   163      def rotate(self, n=1):
   164          length = len(self)
   165          if length <= 1:
   166              return
   167          halflen = length >> 1
   168          if n > halflen or n < -halflen:
   169              n %= length
   170              if n > halflen:
   171                  n -= length
   172              elif n < -halflen:
   173                  n += length
   174          while n > 0:
   175              self.appendleft(self.pop())
   176              n -= 1
   177          while n < 0:
   178              self.append(self.popleft())
   179              n += 1
   180  
   181      def reverse(self):
   182          "reverse *IN PLACE*"
   183          leftblock = self.left
   184          rightblock = self.right
   185          leftindex = self.leftndx
   186          rightindex = self.rightndx
   187          for i in range(self.length // 2):
   188              # Validate that pointers haven't met in the middle
   189              assert leftblock != rightblock or leftindex < rightindex
   190  
   191              # Swap
   192              (rightblock[rightindex], leftblock[leftindex]) = (
   193                  leftblock[leftindex], rightblock[rightindex])
   194  
   195              # Advance left block/index pair
   196              leftindex += 1
   197              if leftindex == n:
   198                  leftblock = leftblock[RGTLNK]
   199                  assert leftblock is not None
   200                  leftindex = 0
   201  
   202              # Step backwards with the right block/index pair
   203              rightindex -= 1
   204              if rightindex == -1:
   205                  rightblock = rightblock[LFTLNK]
   206                  assert rightblock is not None
   207                  rightindex = n - 1
   208  
   209      def __repr__(self):
   210          threadlocalattr = '__repr' + str(_thread_ident())
   211          if threadlocalattr in self.__dict__:
   212              return 'deque([...])'
   213          else:
   214              self.__dict__[threadlocalattr] = True
   215              try:
   216                  if self.maxlen is not None:
   217                      return 'deque(%r, maxlen=%s)' % (list(self), self.maxlen)
   218                  else:
   219                      return 'deque(%r)' % (list(self),)
   220              finally:
   221                  del self.__dict__[threadlocalattr]
   222  
   223      def __iter__(self):
   224          return deque_iterator(self, self._iter_impl)
   225  
   226      def _iter_impl(self, original_state, giveup):
   227          if self.state != original_state:
   228              giveup()
   229          block = self.left
   230          while block:
   231              l, r = 0, n
   232              if block is self.left:
   233                  l = self.leftndx
   234              if block is self.right:
   235                  r = self.rightndx + 1
   236              for elem in block[l:r]:
   237                  yield elem
   238                  if self.state != original_state:
   239                      giveup()
   240              block = block[RGTLNK]
   241  
   242      def __reversed__(self):
   243          return deque_iterator(self, self._reversed_impl)
   244  
   245      def _reversed_impl(self, original_state, giveup):
   246          if self.state != original_state:
   247              giveup()
   248          block = self.right
   249          while block:
   250              l, r = 0, n
   251              if block is self.left:
   252                  l = self.leftndx
   253              if block is self.right:
   254                  r = self.rightndx + 1
   255              for elem in reversed(block[l:r]):
   256                  yield elem
   257                  if self.state != original_state:
   258                      giveup()
   259              block = block[LFTLNK]
   260  
   261      def __len__(self):
   262          #sum = 0
   263          #block = self.left
   264          #while block:
   265          #    sum += n
   266          #    block = block[RGTLNK]
   267          #return sum + self.rightndx - self.leftndx + 1 - n
   268          return self.length
   269  
   270      def __getref(self, index):
   271          if index >= 0:
   272              block = self.left
   273              while block:
   274                  l, r = 0, n
   275                  if block is self.left:
   276                      l = self.leftndx
   277                  if block is self.right:
   278                      r = self.rightndx + 1
   279                  span = r-l
   280                  if index < span:
   281                      return block, l+index
   282                  index -= span
   283                  block = block[RGTLNK]
   284          else:
   285              block = self.right
   286              while block:
   287                  l, r = 0, n
   288                  if block is self.left:
   289                      l = self.leftndx
   290                  if block is self.right:
   291                      r = self.rightndx + 1
   292                  negative_span = l-r
   293                  if index >= negative_span:
   294                      return block, r+index
   295                  index -= negative_span
   296                  block = block[LFTLNK]
   297          raise IndexError("deque index out of range")
   298  
   299      def __getitem__(self, index):
   300          block, index = self.__getref(index)
   301          return block[index]
   302  
   303      def __setitem__(self, index, value):
   304          block, index = self.__getref(index)
   305          block[index] = value
   306  
   307      def __delitem__(self, index):
   308          length = len(self)
   309          if index >= 0:
   310              if index >= length:
   311                  raise IndexError("deque index out of range")
   312              self.rotate(-index)
   313              self.popleft()
   314              self.rotate(index)
   315          else:
   316              index = ~index
   317              if index >= length:
   318                  raise IndexError("deque index out of range")
   319              self.rotate(index)
   320              self.pop()
   321              self.rotate(-index)
   322  
   323      def __reduce_ex__(self, proto):
   324          return type(self), (list(self), self.maxlen)
   325  
   326      __hash__ = None
   327  
   328      def __copy__(self):
   329          return self.__class__(self, self.maxlen)
   330  
   331      # XXX make comparison more efficient
   332      def __eq__(self, other):
   333          if isinstance(other, deque):
   334              return list(self) == list(other)
   335          else:
   336              return NotImplemented
   337  
   338      def __ne__(self, other):
   339          if isinstance(other, deque):
   340              return list(self) != list(other)
   341          else:
   342              return NotImplemented
   343  
   344      def __lt__(self, other):
   345          if isinstance(other, deque):
   346              return list(self) < list(other)
   347          else:
   348              return NotImplemented
   349  
   350      def __le__(self, other):
   351          if isinstance(other, deque):
   352              return list(self) <= list(other)
   353          else:
   354              return NotImplemented
   355  
   356      def __gt__(self, other):
   357          if isinstance(other, deque):
   358              return list(self) > list(other)
   359          else:
   360              return NotImplemented
   361  
   362      def __ge__(self, other):
   363          if isinstance(other, deque):
   364              return list(self) >= list(other)
   365          else:
   366              return NotImplemented
   367  
   368      def __iadd__(self, other):
   369          self.extend(other)
   370          return self
   371  
   372  class deque_iterator(object):
   373  
   374      def __init__(self, deq, itergen):
   375          self.counter = len(deq)
   376          def giveup():
   377              self.counter = 0
   378              raise RuntimeError("deque mutated during iteration")
   379          self._gen = itergen(deq.state, giveup)
   380  
   381      def next(self):
   382          res = next(self._gen)
   383          self.counter -= 1
   384          return res
   385  
   386      def __iter__(self):
   387          return self
   388  
   389  class defaultdict(dict):
   390  
   391      def __init__(self, *args, **kwds):
   392          if len(args) > 0:
   393              default_factory = args[0]
   394              args = args[1:]
   395              if not callable(default_factory) and default_factory is not None:
   396                  raise TypeError("first argument must be callable")
   397          else:
   398              default_factory = None
   399          self.default_factory = default_factory
   400          super(defaultdict, self).__init__(*args, **kwds)
   401  
   402      def __missing__(self, key):
   403          # from defaultdict docs
   404          if self.default_factory is None:
   405              raise KeyError(key)
   406          self[key] = value = self.default_factory()
   407          return value
   408  
   409      def __repr__(self, recurse=set()):
   410          if id(self) in recurse:
   411              return "defaultdict(...)"
   412          try:
   413              recurse.add(id(self))
   414              return "defaultdict(%s, %s)" % (repr(self.default_factory), super(defaultdict, self).__repr__())
   415          finally:
   416              recurse.remove(id(self))
   417  
   418      def copy(self):
   419          return type(self)(self.default_factory, self)
   420  
   421      def __copy__(self):
   422          return self.copy()
   423  
   424      def __reduce__(self):
   425          """
   426          __reduce__ must return a 5-tuple as follows:
   427  
   428             - factory function
   429             - tuple of args for the factory function
   430             - additional state (here None)
   431             - sequence iterator (here None)
   432             - dictionary iterator (yielding successive (key, value) pairs
   433  
   434             This API is used by pickle.py and copy.py.
   435          """
   436          return (type(self), (self.default_factory,), None, None, self.iteritems())
   437