web/lib/django/core/files/base.py
changeset 0 0d40e90630ef
equal deleted inserted replaced
-1:000000000000 0:0d40e90630ef
       
     1 import os
       
     2 try:
       
     3     from cStringIO import StringIO
       
     4 except ImportError:
       
     5     from StringIO import StringIO
       
     6 
       
     7 from django.utils.encoding import smart_str, smart_unicode
       
     8 from django.core.files.utils import FileProxyMixin
       
     9 
       
    10 class File(FileProxyMixin):
       
    11     DEFAULT_CHUNK_SIZE = 64 * 2**10
       
    12 
       
    13     def __init__(self, file, name=None):
       
    14         self.file = file
       
    15         if name is None:
       
    16             name = getattr(file, 'name', None)
       
    17         self.name = name
       
    18         self.mode = getattr(file, 'mode', None)
       
    19 
       
    20     def __str__(self):
       
    21         return smart_str(self.name or '')
       
    22 
       
    23     def __unicode__(self):
       
    24         return smart_unicode(self.name or u'')
       
    25 
       
    26     def __repr__(self):
       
    27         return "<%s: %s>" % (self.__class__.__name__, self or "None")
       
    28 
       
    29     def __nonzero__(self):
       
    30         return bool(self.name)
       
    31 
       
    32     def __len__(self):
       
    33         return self.size
       
    34 
       
    35     def _get_size(self):
       
    36         if not hasattr(self, '_size'):
       
    37             if hasattr(self.file, 'size'):
       
    38                 self._size = self.file.size
       
    39             elif os.path.exists(self.file.name):
       
    40                 self._size = os.path.getsize(self.file.name)
       
    41             else:
       
    42                 raise AttributeError("Unable to determine the file's size.")
       
    43         return self._size
       
    44 
       
    45     def _set_size(self, size):
       
    46         self._size = size
       
    47 
       
    48     size = property(_get_size, _set_size)
       
    49 
       
    50     def _get_closed(self):
       
    51         return not self.file or self.file.closed
       
    52     closed = property(_get_closed)
       
    53 
       
    54     def chunks(self, chunk_size=None):
       
    55         """
       
    56         Read the file and yield chucks of ``chunk_size`` bytes (defaults to
       
    57         ``UploadedFile.DEFAULT_CHUNK_SIZE``).
       
    58         """
       
    59         if not chunk_size:
       
    60             chunk_size = self.DEFAULT_CHUNK_SIZE
       
    61 
       
    62         if hasattr(self, 'seek'):
       
    63             self.seek(0)
       
    64         # Assume the pointer is at zero...
       
    65         counter = self.size
       
    66 
       
    67         while counter > 0:
       
    68             yield self.read(chunk_size)
       
    69             counter -= chunk_size
       
    70 
       
    71     def multiple_chunks(self, chunk_size=None):
       
    72         """
       
    73         Returns ``True`` if you can expect multiple chunks.
       
    74 
       
    75         NB: If a particular file representation is in memory, subclasses should
       
    76         always return ``False`` -- there's no good reason to read from memory in
       
    77         chunks.
       
    78         """
       
    79         if not chunk_size:
       
    80             chunk_size = self.DEFAULT_CHUNK_SIZE
       
    81         return self.size > chunk_size
       
    82 
       
    83     def __iter__(self):
       
    84         # Iterate over this file-like object by newlines
       
    85         buffer_ = None
       
    86         for chunk in self.chunks():
       
    87             chunk_buffer = StringIO(chunk)
       
    88 
       
    89             for line in chunk_buffer:
       
    90                 if buffer_:
       
    91                     line = buffer_ + line
       
    92                     buffer_ = None
       
    93 
       
    94                 # If this is the end of a line, yield
       
    95                 # otherwise, wait for the next round
       
    96                 if line[-1] in ('\n', '\r'):
       
    97                     yield line
       
    98                 else:
       
    99                     buffer_ = line
       
   100 
       
   101         if buffer_ is not None:
       
   102             yield buffer_
       
   103 
       
   104     def open(self, mode=None):
       
   105         if not self.closed:
       
   106             self.seek(0)
       
   107         elif self.name and os.path.exists(self.name):
       
   108             self.file = open(self.name, mode or self.mode)
       
   109         else:
       
   110             raise ValueError("The file cannot be reopened.")
       
   111 
       
   112     def close(self):
       
   113         self.file.close()
       
   114 
       
   115 class ContentFile(File):
       
   116     """
       
   117     A File-like object that takes just raw content, rather than an actual file.
       
   118     """
       
   119     def __init__(self, content):
       
   120         content = content or ''
       
   121         super(ContentFile, self).__init__(StringIO(content))
       
   122         self.size = len(content)
       
   123 
       
   124     def __str__(self):
       
   125         return 'Raw content'
       
   126 
       
   127     def __nonzero__(self):
       
   128         return True
       
   129 
       
   130     def open(self, mode=None):
       
   131         self.seek(0)
       
   132 
       
   133     def close(self):
       
   134         pass