Yet Another PEP: Query Protocol Interface or __query__
Clark C. Evans
cce at clarkevans.com
Tue Mar 27 16:40:27 CEST 2001
I've started to write an example usage of this PEP. It is
far from perfect, however it should give you an idea of
the usage. I could use some help with examples and tightening
Example Usage (written but not checked)
Suppose a user has a function that requires a file-like
object. Here is how adapt can be used to ensure that
an argument does indeed follow the file protocol:
from adapt import adapt
file = adapt(file,types.FileType)
TypeError: test cannot be adapted to <type 'file'>
Let us assume that the code above becomes the norm, and
now the user needs to re-use this code with a BLOB
stored in a database. Here is how that would be done.
def readline(self): # read line from BLOB
return "This is a new line" # real code goes here
# (other file functions go here)
if protocol is types.FileType: return self
This is a new line
Let us say that this works for a while, but sooner or later
the concept of a forward-access read-only file is needed.
So, perhaps the following "standard interface" emerges:
def readline(self): pass
def read(self,size=-1): pass
def readline(self): # implement using read
def read(self,size=-1): # implement using readline
def __call__(self, obj):
# objects adaptable to FileType is are compliant
retval = adapt(obj,types.FileType)
if retval: return retval
# objects that have both readline and read are ok
if getattr(obj,'readline',None) and \
getattr(obj,'read',None): return obj
# wrap objects exposing a readline
retval = AdaptReadline()
retval.readline = obj.readline
# wrap objects exposing a read
retval = AdaptRead()
retval.read = obj.read
This would allow our first-line program to be re-written to
use the new interface:
file = adapt(file,ForwardFile)
Note that anything which inherits from ForwardFile is a
adaptable as well as anything which considers itself a FileType
More so, do to the __adapt__ class method above, anything
that has read or readline can be adapted to work!
Let's say that time passes on, and a record-set class is
created. And after the above interface is well in use
(and now immutable due to wide distribution), the creator
of the record-set class wishes to make this new class
substitutable for any ForwardFile.
def readline(): pass # some intelligent impl
def read(): pass # more intelligent impl
# other record set specific stuff
There are a few choices. First, the RecordSet class
could inherit from ForwardFile. Or, the following
__adapt__ method could be added!
if protocol is ForwardFile: return self
This has a slight problem in that a dependency is now
created (ForwardFile must be on the user's system). This
can be mitigated with something like the following:
if protocol.__name__ = 'ForwardFile': return self
Note that readline and read could be put in a wrapper class
instead (so that they don't clutter the RecordSet class!
Regardless, in every case where a ForwardFile is accepted,
the adapter mechanism will also pass off for objects of
1. Is there a way to get a fully-qualified name
(including the package?)
2. What kind of "wrapper helpers" could be made?
(I like Carlos's examples!)
3. Perhaps a __conform__ function would also
like to know who the caller is... I wonder
if this would be useful. Can this be
3. Would a __protocol__ item also help?
__protocol__ = "com.zoober.protocols.ForwardFile"
This would allow the __conform__ above to be re-written:
if protocol.__protocol__ =
In this way, support for multiple protocols could
be put in place without requiring said classes/interface
declarations on the user's box.
4. Is a protcol registry needed, or does the
above suffice? (I think it's good enough)
A proposal would be like:
And then, after exhausting the object and the
protcol, it could check in the registry...
Thank you all for your help!
More information about the Python-list