--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/django/core/files/base.py Tue Oct 14 16:00:59 2008 +0000
@@ -0,0 +1,169 @@
+import os
+
+from django.utils.encoding import smart_str, smart_unicode
+
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
+
+class File(object):
+ DEFAULT_CHUNK_SIZE = 64 * 2**10
+
+ def __init__(self, file):
+ self.file = file
+ self._name = file.name
+ self._mode = file.mode
+ self._closed = False
+
+ def __str__(self):
+ return smart_str(self.name or '')
+
+ def __unicode__(self):
+ return smart_unicode(self.name or u'')
+
+ def __repr__(self):
+ return "<%s: %s>" % (self.__class__.__name__, self or "None")
+
+ def __nonzero__(self):
+ return not not self.name
+
+ def __len__(self):
+ return self.size
+
+ def _get_name(self):
+ return self._name
+ name = property(_get_name)
+
+ def _get_mode(self):
+ return self._mode
+ mode = property(_get_mode)
+
+ def _get_closed(self):
+ return self._closed
+ closed = property(_get_closed)
+
+ def _get_size(self):
+ if not hasattr(self, '_size'):
+ if hasattr(self.file, 'size'):
+ self._size = self.file.size
+ elif os.path.exists(self.file.name):
+ self._size = os.path.getsize(self.file.name)
+ else:
+ raise AttributeError("Unable to determine the file's size.")
+ return self._size
+
+ def _set_size(self, size):
+ self._size = size
+
+ size = property(_get_size, _set_size)
+
+ def chunks(self, chunk_size=None):
+ """
+ Read the file and yield chucks of ``chunk_size`` bytes (defaults to
+ ``UploadedFile.DEFAULT_CHUNK_SIZE``).
+ """
+ if not chunk_size:
+ chunk_size = self.__class__.DEFAULT_CHUNK_SIZE
+
+ if hasattr(self, 'seek'):
+ self.seek(0)
+ # Assume the pointer is at zero...
+ counter = self.size
+
+ while counter > 0:
+ yield self.read(chunk_size)
+ counter -= chunk_size
+
+ def multiple_chunks(self, chunk_size=None):
+ """
+ Returns ``True`` if you can expect multiple chunks.
+
+ NB: If a particular file representation is in memory, subclasses should
+ always return ``False`` -- there's no good reason to read from memory in
+ chunks.
+ """
+ if not chunk_size:
+ chunk_size = self.DEFAULT_CHUNK_SIZE
+ return self.size > chunk_size
+
+ def xreadlines(self):
+ return iter(self)
+
+ def readlines(self):
+ return list(self.xreadlines())
+
+ def __iter__(self):
+ # Iterate over this file-like object by newlines
+ buffer_ = None
+ for chunk in self.chunks():
+ chunk_buffer = StringIO(chunk)
+
+ for line in chunk_buffer:
+ if buffer_:
+ line = buffer_ + line
+ buffer_ = None
+
+ # If this is the end of a line, yield
+ # otherwise, wait for the next round
+ if line[-1] in ('\n', '\r'):
+ yield line
+ else:
+ buffer_ = line
+
+ if buffer_ is not None:
+ yield buffer_
+
+ def open(self, mode=None):
+ if not self.closed:
+ self.seek(0)
+ elif os.path.exists(self.file.name):
+ self.file = open(self.file.name, mode or self.file.mode)
+ else:
+ raise ValueError("The file cannot be reopened.")
+
+ def seek(self, position):
+ self.file.seek(position)
+
+ def tell(self):
+ return self.file.tell()
+
+ def read(self, num_bytes=None):
+ if num_bytes is None:
+ return self.file.read()
+ return self.file.read(num_bytes)
+
+ def write(self, content):
+ if not self.mode.startswith('w'):
+ raise IOError("File was not opened with write access.")
+ self.file.write(content)
+
+ def flush(self):
+ if not self.mode.startswith('w'):
+ raise IOError("File was not opened with write access.")
+ self.file.flush()
+
+ def close(self):
+ self.file.close()
+ self._closed = True
+
+class ContentFile(File):
+ """
+ A File-like object that takes just raw content, rather than an actual file.
+ """
+ def __init__(self, content):
+ self.file = StringIO(content or '')
+ self.size = len(content or '')
+ self.file.seek(0)
+ self._closed = False
+
+ def __str__(self):
+ return 'Raw content'
+
+ def __nonzero__(self):
+ return True
+
+ def open(self, mode=None):
+ if self._closed:
+ self._closed = False
+ self.seek(0)