New submission from Christian Heimes:

I always missed a getsize() method on file objects. The patch adds a
method getsize() to all io instances. The method returns a SizeInfo
object which can print a human readable name or the bare size in bytes.
The method is using os.fstat and falls back to the seek(0,2), tell()
pattern.

>>> f = open("/etc/passwd")
>>> f.getsize()
<SizeInfo 1.7 KiB>
>>> int(f.getsize())
1721
>>> str(f.getsize())
'1.7 KiB'
>>> (f.getsize().sizeinfo())
(1.681, 1)

I'm going to provide unit tests and documentation if you like the feature.

----------
components: Library (Lib)
files: py3k_sizeinfo.patch
messages: 56877
nosy: tiran
severity: normal
status: open
title: Add getsize() to io instances
type: rfe
versions: Python 3.0
Added file: http://bugs.python.org/file8642/py3k_sizeinfo.patch

__________________________________
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1351>
__________________________________
Index: Lib/io.py
===================================================================
--- Lib/io.py	(Revision 58695)
+++ Lib/io.py	(Arbeitskopie)
@@ -190,6 +190,42 @@
         return open(*args, **kwargs)
 
 
+class SizeInfo:
+    """Wrapper for size information
+    """
+    size_names = ('B', 'KiB', 'MiB', 'GiB')
+
+    def __init__(self, size:int):
+        if not isinstance(size, int) and not size >=0:
+            raise ValueError("Invalid size %r" % size)
+        self._size = size
+
+    def __int__(self) -> int:
+        """int(sizeinfo) -> int
+        """
+        return self._size
+
+    def sizeinfo(self) -> tuple:
+        """sizeinfo() -> (rounded size:float, size name:int)
+        """
+        if self._size == 0:
+            return 0, 0
+        if self._size < 1024:
+            return self._size, 0
+        if self._size < 1048576:
+            return round(self._size / 1024, 3), 1
+        if self._size < 1073741824:
+            return round(self._size / 1048576, 3), 2
+        return round(self._size / 1073741824, 3), 3
+
+    def __str__(self) -> str:
+        size, name = self.sizeinfo()
+        return "%1.1f %s" % (size, self.size_names[name])
+
+    def __repr__(self) -> str:
+        return "<%s %s>" % (self.__class__.__name__, self)
+
+
 class UnsupportedOperation(ValueError, IOError):
     pass
 
@@ -339,6 +375,27 @@
             raise ValueError("I/O operation on closed file."
                              if msg is None else msg)
 
+    def getsize(self) -> SizeInfo:
+        """getsize() -> SizeInfo object
+        """
+        size = None
+        self.flush()
+
+        try:
+            size = os.fstat(self.fileno()).st_size
+        except (IOError, OSError):
+            pass
+
+        if size is None:
+            oldpos = self.tell()
+            try:
+                self.seek(0, 2)
+                size = self.tell()
+            finally:
+                self.seek(oldpos)
+
+        return SizeInfo(size)
+
     ### Context manager ###
 
     def __enter__(self) -> "IOBase":  # That's a forward reference
@@ -621,6 +678,10 @@
 
     ### Inquiries ###
 
+    def getsize(self):
+        self.flush()
+        return self.raw.getsize()
+
     def seekable(self):
         return self.raw.seekable()
 
_______________________________________________
Python-bugs-list mailing list 
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to