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 _______________________________________________ Zope-Dev maillist - Zope-Dev@zope.org https://mail.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - https://mail.zope.org/mailman/listinfo/zope-announce https://mail.zope.org/mailman/listinfo/zope )