Package Camelot :: Package camelot :: Package core :: Package files :: Module storage |
[frames] | no frames]

# Source Code for Module Camelot.camelot.core.files.storage

      1  # -*- coding: utf8 -*-
      2
      3  import logging
      4
      5  logger = logging.getLogger( 'camelot.core.files.storage' )
      6
      7  from camelot.view.model_thread import model_function
      8
      9 -class StoredFile( object ):
     10      """Helper class for the File field type.
     11      Stored file objects can be used within the GUI thread, as none of
     12      its methods should block.
     13      """
     14
     15 -    def __init__( self, storage, name ):
     16          """
     17      :param storage: the storage in which the file is stored
     18      :param name: the key by which the file is known in the storage"""
     19          self.storage = storage
     20          self.name = name
     21
     22      @property
     23 -    def verbose_name( self ):
     24          """The name of the file, as it is to be displayed in the GUI"""
     25          return self.name
     26
     27 -    def __unicode__( self ):
     28          return self.verbose_name
     29
     30 -class StoredImage( StoredFile ):
     31      """Helper class for the Image field type Class linking an image and the
     32      location and filename where the image is stored"""
     33
     34      @model_function
     35 -    def checkout_image( self ):
     36          """Checkout the image from the storage, and return a QImage"""
     37          from PyQt4.QtGui import QImage
     38          p = self.storage.checkout( self )
     39          return QImage( p )
     40
     41      @model_function
     42 -    def checkout_thumbnail( self, width, height ):
     43          """Checkout a thumbnail for this image form the storage
     44          :return: a QImage"""
     45          from PyQt4.QtCore import Qt
     46          original_image = self.checkout_image()
     47          return original_image.scaled( width, height, Qt.KeepAspectRatio )
     48
     49 -class Storage( object ):
     50      """Helper class that opens and saves StoredFile objects
     51    The default implementation stores files in the settings.CAMELOT_MEDIA_ROOT
     52    directory.  The storage object should only be used within the model thread,
     53    as all of it's methods might block.
     54
     55    The methods of this class don't verify if they are called on the model
     56    thread, because these classes can be used on the server as well.
     57      """
     58
     59 -    def __init__( self, upload_to = '', stored_file_implementation = StoredFile ):
     60          """
     61      :param upload_to: the sub directory in which to put files
     62      :param stored_file_implementation: the subclass of StoredFile to be used when
     63      checking out files from the storage
     64      """
     65          import settings
     66          import os
     67          self.upload_to = os.path.join( settings.CAMELOT_MEDIA_ROOT, upload_to )
     68          self.stored_file_implementation = stored_file_implementation
     69          #
     70          # don't do anything here that might reduce the startup time, like verifying the
     71          # availability of the storage, sinde the path might be on a slow network share
     72          #
     73
     74 -    def available(self):
     75          """Verify if the storage is available
     76          """
     77          import os
     78          try:
     79              if not os.path.exists( self.upload_to ):
     80                  os.makedirs( self.upload_to )
     81              return True
     82          except Exception, e:
     83              logger.warn( 'Could not access or create path %s, files will be unreachable' % self.upload_to, exc_info = e )
     84          return False
     85
     86 -    def exists( self, name ):
     87          """True if a file exists given some name"""
     88          if self.available():
     89              import os
     90              os.path.exists( self.path( name ) )
     91          return False
     92
     93 -    def list(self, prefix='*', suffix='*'):
     94          """Lists all files with a given prefix and or suffix available in this storage
     95          :return: a iterator of StoredFile objects
     96          """
     97          import glob
     98          import os
     99          return (StoredFile(self, name) for name in glob.glob( os.path.join( self.upload_to, u'%s*%s'%(prefix, suffix) ) ) )
    100
    101 -    def path( self, name ):
    102          """The local filesystem path where the file can be opened using Python’s standard open"""
    103          import os
    104          return os.path.join( self.upload_to, name )
    105
    106 -    def checkin( self, local_path ):
    107          """Check the file pointed to by local_path into the storage, and
    108          return a StoredFile"""
    109          self.available()
    110          import tempfile
    111          import shutil
    112          import os
    113          root, extension = os.path.splitext( os.path.basename( local_path ) )
    114          ( handle, to_path ) = tempfile.mkstemp( suffix = extension, prefix = root, dir = self.upload_to, text = 'b' )
    115          os.close( handle )
    116          logger.debug( 'copy file from %s to %s', local_path, to_path )
    117          shutil.copy( local_path, to_path )
    118          return self.stored_file_implementation( self, os.path.basename( to_path ) )
    119
    120 -    def checkin_stream( self, prefix, suffix, stream ):
    121          """Check the datastream in as a file into the storage
    122          :param prefix: the prefix to use for generating a file name
    123          :param suffix: the suffix to use for generating a filen name, eg '.png'
    124          :return: a StoredFile"""
    125          self.available()
    126          import tempfile
    127          import os
    128          ( handle, to_path ) = tempfile.mkstemp( suffix = suffix, prefix = prefix, dir = self.upload_to, text = 'b' )
    129          file = os.fdopen( handle, 'wb' )
    130          file.write( stream.read() )
    131          file.flush()
    132          file.close()
    133          return self.stored_file_implementation( self, os.path.basename( to_path ) )
    134
    135 -    def checkout( self, stored_file ):
    136          """Check the file pointed to by the local_path out of the storage and return
    137      a local filesystem path where the file can be opened"""
    138          self.available()
    139          import os
    140          return os.path.join( self.upload_to, stored_file.name )
    141
    142 -    def checkout_stream( self, stored_file ):
    143          """Check the file stored_file out of the storage as a datastream
    144          :return: a file object
    145          """
    146          self.available()
    147          import os
    148          return open( os.path.join( self.upload_to, stored_file.name ), 'rb' )
    149
    150 -    def delete( self, name ):
    151          pass
    152
    153 -class S3Storage( object ):
    154      """Helper class that opens and saves StoredFile objects into Amazon S3.
    155
    156      these attibutes need to be set in your settings for S3Storage to work :
    157       * AWS_ACCESS_KEY_ID = '<INSERT YOUR AWS ACCESS KEY ID HERE>'
    158       * AWS_SECRET_ACCESS_KEY = '<INSERT YOUR AWS SECRET ACCESS KEY HERE>'
    159       * AWS_BUCKET_NAME = 'camelot'
    160       * AWS_LOCATION = S3.Location.DEFAULT
    161
    162      Using this Storage requires the availability of S3.py on your PYTHONPATH.
    163      S3.py can be found on the amazon.com website
    164      """
    165
    166 -    def __init__( self, upload_to = '', stored_file_implementation = StoredFile ):
    167          # try to work around bug S3 code which uses bad names of days
    168          # http://code.google.com/p/boto/issues/detail?id=140
    169          # but workaround doesn't work :(
    170          #import locale
    171  #    locale.setlocale(locale.LC_TIME, 'en_US.utf8')
    172  #    print 'create S3 storage'
    173          import settings
    174          import S3
    175          self.upload_to = upload_to
    176          conn = S3.AWSAuthConnection( settings.AWS_ACCESS_KEY_ID, settings.AWS_SECRET_ACCESS_KEY )
    177  #        _generator = S3.QueryStringAuthGenerator( settings.AWS_ACCESS_KEY_ID, settings.AWS_SECRET_ACCESS_KEY )
    178          if ( conn.check_bucket_exists( settings.AWS_BUCKET_NAME ).status == 200 ):
    179              pass
    180          else:
    181              conn.create_located_bucket( settings.AWS_BUCKET_NAME, settings.AWS_LOCATION ).message
    182