mercurial/util.py
changeset 16803 107a3270a24a
parent 16769 e406b9656da3
child 16834 cafd8a8fb713
equal deleted inserted replaced
16802:7e5d94381cd1 16803:107a3270a24a
    12 This contains helper routines that are independent of the SCM core and
    12 This contains helper routines that are independent of the SCM core and
    13 hide platform-specific details from the core.
    13 hide platform-specific details from the core.
    14 """
    14 """
    15 
    15 
    16 from i18n import _
    16 from i18n import _
    17 import error, osutil, encoding
    17 import error, osutil, encoding, collections
    18 import errno, re, shutil, sys, tempfile, traceback
    18 import errno, re, shutil, sys, tempfile, traceback
    19 import os, time, datetime, calendar, textwrap, signal
    19 import os, time, datetime, calendar, textwrap, signal
    20 import imp, socket, urllib
    20 import imp, socket, urllib
    21 
    21 
    22 if os.name == 'nt':
    22 if os.name == 'nt':
   203     return f
   203     return f
   204 
   204 
   205 def lrucachefunc(func):
   205 def lrucachefunc(func):
   206     '''cache most recent results of function calls'''
   206     '''cache most recent results of function calls'''
   207     cache = {}
   207     cache = {}
   208     order = []
   208     order = collections.deque()
   209     if func.func_code.co_argcount == 1:
   209     if func.func_code.co_argcount == 1:
   210         def f(arg):
   210         def f(arg):
   211             if arg not in cache:
   211             if arg not in cache:
   212                 if len(cache) > 20:
   212                 if len(cache) > 20:
   213                     del cache[order.pop(0)]
   213                     del cache[order.popleft()]
   214                 cache[arg] = func(arg)
   214                 cache[arg] = func(arg)
   215             else:
   215             else:
   216                 order.remove(arg)
   216                 order.remove(arg)
   217             order.append(arg)
   217             order.append(arg)
   218             return cache[arg]
   218             return cache[arg]
   219     else:
   219     else:
   220         def f(*args):
   220         def f(*args):
   221             if args not in cache:
   221             if args not in cache:
   222                 if len(cache) > 20:
   222                 if len(cache) > 20:
   223                     del cache[order.pop(0)]
   223                     del cache[order.popleft()]
   224                 cache[args] = func(*args)
   224                 cache[args] = func(*args)
   225             else:
   225             else:
   226                 order.remove(args)
   226                 order.remove(args)
   227             order.append(args)
   227             order.append(args)
   228             return cache[args]
   228             return cache[args]
   863     def read(self, l):
   863     def read(self, l):
   864         """Read L bytes of data from the iterator of chunks of data.
   864         """Read L bytes of data from the iterator of chunks of data.
   865         Returns less than L bytes if the iterator runs dry."""
   865         Returns less than L bytes if the iterator runs dry."""
   866         left = l
   866         left = l
   867         buf = ''
   867         buf = ''
   868         queue = self._queue
   868         queue = collections.deque(self._queue)
   869         while left > 0:
   869         while left > 0:
   870             # refill the queue
   870             # refill the queue
   871             if not queue:
   871             if not queue:
   872                 target = 2**18
   872                 target = 2**18
   873                 for chunk in self.iter:
   873                 for chunk in self.iter:
   876                     if target <= 0:
   876                     if target <= 0:
   877                         break
   877                         break
   878                 if not queue:
   878                 if not queue:
   879                     break
   879                     break
   880 
   880 
   881             chunk = queue.pop(0)
   881             chunk = queue.popleft()
   882             left -= len(chunk)
   882             left -= len(chunk)
   883             if left < 0:
   883             if left < 0:
   884                 queue.insert(0, chunk[left:])
   884                 queue.appendleft(chunk[left:])
   885                 buf += chunk[:left]
   885                 buf += chunk[:left]
   886             else:
   886             else:
   887                 buf += chunk
   887                 buf += chunk
       
   888         self._queue = list(queue)
   888 
   889 
   889         return buf
   890         return buf
   890 
   891 
   891 def filechunkiter(f, size=65536, limit=None):
   892 def filechunkiter(f, size=65536, limit=None):
   892     """Create a generator that produces the data in the file size
   893     """Create a generator that produces the data in the file size