[Zope-dev] zope.filerepresentation
Martin Aspeli
optilude+lists at gmail.com
Wed Sep 30 20:13:11 EDT 2009
Hanno Schlichting wrote:
> Is there any reason to invent a new API and not just use Python's file API?
I don't know. IReadFile and IWriteFile have been around for ever and are
used by a number of things in Zope. They have read(), write() and
size(). The first two are on file, the last one isn't. I'd like to be
able to use this API as a base, since it's used for things like
z3c.blobfile already, and is documented as the way to do this kind of
thing in Philipp's book.
> So .name instead of getFilename, iterator per __iter__ and next?
Yeah, that's a better idea.
> I'm not sure about the different read/write methods on file-objects,
> but I think the standard ones do cover all the same use-cases.
>
> The standard file implementation has no knowledge of its size, as this
> is sometimes impossible to get, when dealing with stream based
> file-like objects. Do we really need to have files to know their size?
Well, for the writeFile() stuff maybe we don't. Thinking through my use
cases again, I can't see a need for passing the content type in, and
encoding can be set if we support setting the '.encoding' property.
It's kind of important to be able to indicate the size and MIME type for
a read operation, though. In this case, I want to be able to put that
information into the Content-Type and Content-Length headers. The
IStreamData stuff in Zope 2 also wants to know the length before it
starts streaming.
In some cases, it may not be possible to know, in which case we can fall
back on len(data), but in other cases, the length is known
(plone.namedfile and z3c.blobfile keep track of it, for example), in
which case having a way to ask the adapter means it can be done much
more efficiently.
So, how about this:
class IReadFile(Interface):
"""Provide read access to file data
"""
def read():
"""Return the file data as a str
"""
def size():
"""Return the data length
"""
class ILargeReadFile(IReadFile):
"""Provide efficient read access to file data
"""
def getContentType():
"""Get the content/MIME type of the file as a string in the form
'major/minor'. Return None if this is not known or undefined.
"""
name = schema.TextLine(title=u"Filename", readonly=True)
encoding = schema.ASCIILine(title=u"Encoding", readonly=True)
def __iter__():
"""Get an iterator"""
def next():
"""See file"""
def seek():
"""See file"""
def tell():
"""See file"""
class IWriteFile(Interface):
def write(data):
"""Update the file data
"""
class ILargeWriteFile(IWriteFile):
def write(data):
"""Write a chunk of data
"""
name = schema.TextLine(title=u"Filename", readonly=False)
encoding = schema.ASCIILine(title=u"Encoding", readonly=False)
def tell():
"""See file"""
def close():
"""See file""
It may be worth supporting the rest of the functions (readlines,
writelines, truncate, readline, isatty, fileno, flush) so that
ILargeReadFile + ILargeWriteFile are equivalent to file.
I've also allowed here for the name and encoding to be set on an
ILargeWriteFile, with the caveat that this has to be done before the
writing.
In this approach, the caller is responsible for writing large streams in
chunks and then calling close, i.e. the iterator isn't passed to the
ILargeWriteFile. I think that's OK, though.
I've still got the content type as a method (maybe make it a read-only
property?) that may return None. That could be in a separate adapter,
but that feels like overkill to me. :)
Martin
--
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book
More information about the Zope-Dev
mailing list