Beispiel #1
0
    def _populate(self):
        """
        Put some revisions of a blob object in our database and on the
        filesystem.
        """
        from ZODB.utils import u64 as bytes8_to_int64

        connection1 = self.database.open()
        root = connection1.root()

        tids = self.tids = []
        times = self.times = []
        blob = Blob()

        for i in range(self.BLOB_REVISION_COUNT):
            transaction.begin()
            with blob.open('w') as f:
                f.write(b'this is blob data ' + str(i).encode())
            if 'blob' not in root:
                root['blob'] = blob
            transaction.commit()

            blob._p_activate()
            tid = blob._p_serial
            tids.append(tid)
            tid_int = bytes8_to_int64(tid)

            times.append(tid_int - 1)

        blob._p_activate()

        self.oid = oid = root['blob']._p_oid
        fshelper = self.blob_storage.blobhelper.fshelper
        self.fns = [fshelper.getBlobFilename(oid, x) for x in tids]
        connection1.close()
Beispiel #2
0
class File(Persistent):

    title = _BLANK

    name = renamer()

    def __init__(self, stream=None, mimetype=None, title=_BLANK):
        """ The constructor of a File object.

        ``stream`` should be a filelike object (an object with a ``read``
        method that takes a size argument) or ``None``.  If stream is
        ``None``, the blob attached to this file object is created empty.

        ``title`` must be a string or Unicode object.

        ``mimetype`` may be any of the following:

        - ``None``, meaning set this file object's mimetype to
          ``application/octet-stream`` (the default).

        - A mimetype string (e.g. ``image/gif``)

        - The constant :attr:`substanced.file.USE_MAGIC`, which will
          derive the mimetype from the stream content (if ``stream`` is also
          supplied) using the ``python-magic`` library.

          .. warning::

             On non-Linux systems, successful use of
             :attr:`substanced.file.USE_MAGIC` requires the installation
             of additional dependencies.  See :ref:`optional_dependencies`.
        """
        self.blob = Blob()
        self.title = title or _BLANK

        # mimetype will be overridden by upload if there's a stream
        if mimetype is USE_MAGIC:
            self.mimetype = "application/octet-stream"
        else:
            self.mimetype = mimetype or "application/octet-stream"

        if stream is not None:
            if mimetype is USE_MAGIC:
                hint = USE_MAGIC
            else:
                hint = None
            self.upload(stream, mimetype_hint=hint)

    def upload(self, stream, mimetype_hint=None):
        """ Replace the current contents of this file's blob with the
        contents of ``stream``.  ``stream`` must be a filelike object (it
        must have a ``read`` method that takes a size argument).

        ``mimetype_hint`` can be any of the following:

        - ``None``, meaning don't reset the current mimetype.  This is the
          default.  If you already know the file's mimetype, and you don't
          want it divined from a filename or stream content, use ``None`` as
          the ``mimetype_hint`` value, and set the ``mimetype`` attribute of
          the file object directly before or after calling this method.

        - A string containing a filename that has an extension; the mimetype
          will be derived from the extension in the filename using the Python
          ``mimetypes`` module, and the result will be set as the mimetype
          attribute of this object.

        - The constant :attr:`pyramid.file.USE_MAGIC`, which will derive
          the mimetype using the ``python-magic`` library based on the
          stream's actual content.  The result will be set as the mimetype
          attribute of this object.

          .. warning::

             On non-Linux systems, successful use of
             :attr:`substanced.file.USE_MAGIC` requires the installation
             of additional dependencies.  See :ref:`optional_dependencies`.
          
        """
        if not stream:
            stream = io.StringIO()
        fp = self.blob.open("w")
        first = True
        use_magic = False
        if mimetype_hint is USE_MAGIC:
            use_magic = True
            if magic is None:  # pragma: no cover
                warnings.warn(
                    "The python-magic library does not have its requisite "
                    "dependencies installed properly, therefore the "
                    '"USE_MAGIC" flag passed to this method has been ignored '
                    '(it has been converted to "None").  The mimetype of '
                    "substanced.file.File objects created may be incorrect as "
                    "a result."
                )
                use_magic = False
                mimetype_hint = None

        if not use_magic:
            if mimetype_hint is not None:
                mimetype, _ = mimetypes.guess_type(mimetype_hint, strict=False)
                if mimetype is None:
                    mimetype = "application/octet-stream"
                self.mimetype = mimetype
        for chunk in chunks(stream):
            if use_magic and first:
                first = False
                m = magic.Magic(mime=True)
                mimetype = m.from_buffer(chunk)
                self.mimetype = u(mimetype)
            fp.write(chunk)
        fp.close()

    def get_response(self, **kw):
        """ Return a WebOb-compatible response object which uses the blob
        content as the stream data and the mimetype of the file as the
        content type.  The ``**kw`` arguments will be passed to the
        ``pyramid.response.FileResponse`` constructor as its keyword
        arguments."""
        if not "content_type" in kw:
            kw["content_type"] = str(self.mimetype)
        path = self.blob.committed()
        response = FileResponse(path, **kw)
        return response

    def get_size(self):
        """ Return the size in bytes of the data in the blob associated with
        the file"""
        return os.stat(self.blob.committed()).st_size

    def get_etag(self):
        """ Return a token identifying the "version" of the file.
        """
        self._p_activate()
        mine = self._p_serial
        blob = self.blob._p_serial
        if blob == z64:
            self.blob._p_activate()
            blob = self.blob._p_serial
        return oid_repr(max(mine, blob))
Beispiel #3
0
class File(Persistent):

    title = _BLANK

    name = renamer()

    def __init__(self, stream=None, mimetype=None, title=_BLANK):
        """ The constructor of a File object.

        ``stream`` should be a filelike object (an object with a ``read``
        method that takes a size argument) or ``None``.  If stream is
        ``None``, the blob attached to this file object is created empty.

        ``title`` must be a string or Unicode object.

        ``mimetype`` may be any of the following:

        - ``None``, meaning set this file object's mimetype to
          ``application/octet-stream`` (the default).

        - A mimetype string (e.g. ``image/gif``)

        - The constant :attr:`substanced.file.USE_MAGIC`, which will
          derive the mimetype from the stream content (if ``stream`` is also
          supplied) using the ``python-magic`` library.

          .. warning::

             On non-Linux systems, successful use of
             :attr:`substanced.file.USE_MAGIC` requires the installation
             of additional dependencies.  See :ref:`installing_python_magic`.
        """
        self.blob = Blob()
        self.title = title or _BLANK

        # mimetype will be overridden by upload if there's a stream
        if mimetype is USE_MAGIC:
            self.mimetype = 'application/octet-stream'
        else:
            self.mimetype = mimetype or 'application/octet-stream'

        if stream is not None:
            if mimetype is USE_MAGIC:
                hint = USE_MAGIC
            else:
                hint = None
            self.upload(stream, mimetype_hint=hint)

    def upload(self, stream, mimetype_hint=None):
        """ Replace the current contents of this file's blob with the
        contents of ``stream``.  ``stream`` must be a filelike object (it
        must have a ``read`` method that takes a size argument).

        ``mimetype_hint`` can be any of the following:

        - ``None``, meaning don't reset the current mimetype.  This is the
          default.  If you already know the file's mimetype, and you don't
          want it divined from a filename or stream content, use ``None`` as
          the ``mimetype_hint`` value, and set the ``mimetype`` attribute of
          the file object directly before or after calling this method.

        - A string containing a filename that has an extension; the mimetype
          will be derived from the extension in the filename using the Python
          ``mimetypes`` module, and the result will be set as the mimetype
          attribute of this object.

        - The constant :attr:`substanced.file.USE_MAGIC`, which will derive
          the mimetype using the ``python-magic`` library based on the
          stream's actual content.  The result will be set as the mimetype
          attribute of this object.

          .. warning::

             On non-Linux systems, successful use of
             :attr:`substanced.file.USE_MAGIC` requires the installation
             of additional dependencies.  See :ref:`installing_python_magic`.
        """
        if not stream:
            stream = io.StringIO()
        fp = self.blob.open('w')
        first = True
        use_magic = False
        if mimetype_hint is USE_MAGIC:
            use_magic = True
            if magic is None:  # pragma: no cover
                warnings.warn(
                    'The python-magic library does not have its requisite '
                    'dependencies installed properly, therefore the '
                    '"USE_MAGIC" flag passed to this method has been ignored '
                    '(it has been converted to "None").  The mimetype of '
                    'substanced.file.File objects created may be incorrect as '
                    'a result.')
                use_magic = False
                mimetype_hint = None

        if not use_magic:
            if mimetype_hint is not None:
                mimetype, _ = mimetypes.guess_type(mimetype_hint, strict=False)
                if mimetype is None:
                    mimetype = 'application/octet-stream'
                self.mimetype = mimetype
        for chunk in chunks(stream):
            if use_magic and first:
                first = False
                m = magic.Magic(mime=True)
                mimetype = m.from_buffer(chunk)
                self.mimetype = u(mimetype)
            fp.write(chunk)
        fp.close()

    def get_response(self, **kw):
        """ Return a WebOb-compatible response object which uses the blob
        content as the stream data and the mimetype of the file as the
        content type.  The ``**kw`` arguments will be passed to the
        :class:`pyramid.response.FileResponse` constructor as its keyword
        arguments."""
        if not 'content_type' in kw:
            kw['content_type'] = str(self.mimetype)
        path = self.blob.committed()
        response = FileResponse(path, **kw)
        return response

    def get_size(self):
        """ Return the size in bytes of the data in the blob associated with
        the file"""
        return os.stat(self.blob.committed()).st_size

    def get_etag(self):
        """ Return a token identifying the "version" of the file.
        """
        self._p_activate()
        mine = self._p_serial
        blob = self.blob._p_serial
        if blob == z64:
            self.blob._p_activate()
            blob = self.blob._p_serial
        return oid_repr(max(mine, blob))