Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/util.py @ 36395:01e29e885600
util: add a file object proxy that can read at most N bytes
Sometimes we have data of a known size within a stream. For
performance reasons, we don't want to pre-read this data (we want
to allow consumers to read on demand). For simplicitly reasons,
we don't want callers to necessarily know their data is coming
from within an outer stream and there is a limit to how much
they should read.
The class introduced by this commit provides a very simple proxy
around an underlying file object that allows the consumer to
.read() up to N bytes from the file object. Attempts to read
past this many bytes results in a simulated EOF.
Differential Revision: https://phab.mercurial-scm.org/D2377
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Wed, 21 Feb 2018 13:41:20 -0800 |
parents | 1fa33bd848ee |
children | 0cb09c322647 |
comparison
equal
deleted
inserted
replaced
36394:a2d11d23bb25 | 36395:01e29e885600 |
---|---|
1977 if not s: | 1977 if not s: |
1978 break | 1978 break |
1979 if limit: | 1979 if limit: |
1980 limit -= len(s) | 1980 limit -= len(s) |
1981 yield s | 1981 yield s |
1982 | |
1983 class cappedreader(object): | |
1984 """A file object proxy that allows reading up to N bytes. | |
1985 | |
1986 Given a source file object, instances of this type allow reading up to | |
1987 N bytes from that source file object. Attempts to read past the allowed | |
1988 limit are treated as EOF. | |
1989 | |
1990 It is assumed that I/O is not performed on the original file object | |
1991 in addition to I/O that is performed by this instance. If there is, | |
1992 state tracking will get out of sync and unexpected results will ensue. | |
1993 """ | |
1994 def __init__(self, fh, limit): | |
1995 """Allow reading up to <limit> bytes from <fh>.""" | |
1996 self._fh = fh | |
1997 self._left = limit | |
1998 | |
1999 def read(self, n=-1): | |
2000 if not self._left: | |
2001 return b'' | |
2002 | |
2003 if n < 0: | |
2004 n = self._left | |
2005 | |
2006 data = self._fh.read(min(n, self._left)) | |
2007 self._left -= len(data) | |
2008 assert self._left >= 0 | |
2009 | |
2010 return data | |
1982 | 2011 |
1983 def makedate(timestamp=None): | 2012 def makedate(timestamp=None): |
1984 '''Return a unix timestamp (or the current time) as a (unixtime, | 2013 '''Return a unix timestamp (or the current time) as a (unixtime, |
1985 offset) tuple based off the local timezone.''' | 2014 offset) tuple based off the local timezone.''' |
1986 if timestamp is None: | 2015 if timestamp is None: |