[Python-3000] enhanced descriptors, part 2

tomer filiba tomerfiliba at gmail.com
Mon Jun 12 21:06:38 CEST 2006


there really is a need for "enhanced descriptors", or something like
that. i'm having serious trouble implementing the position property,
as python is currently limited in this area.

the rules were:
* when you assign a positive integer, it's an absolute position to
seek to
* when you assign a negative integer, it's relative to the end, as
is the case with slices
* when you assign None, it's the ultimate last position --
seek(0, "end"), although you would use f.END instead of None
* when you use the +=/-= operators, it's relative to the current
position (if optimized via __iadd__, can reduce one unnecessary
system call)

but descriptors don't support augmented __set__()ing. one solution
would be to return an int-like object, where __iadd__ would seek
relative to the current position.

aside of being slower than expected, complicating __set__, and
implementing position caching, this has a major drawback:
f.position += 4 # this assignment seeks
p = f.position
p += 4 # and this assignment seeks as well!

so that's out of the question, and we'll have to suffer two system
calls, at least in the experimental branch. maybe the C-branch
could utilize under-the-hood tricks to avoid that.

the current code of the descriptor looks like this:

class PositionDesc(object):
    def __get__(self, obj, cls):
        if obj is None:
            return self
        return obj.tell()

    def __set__(self, obj, value):
        if value is None:
            obj.seek(0, "end")
        elif value < 0:
            obj.seek(value, "end")
            obj.seek(value, "start")

but now we come to another problem... files became cyclic!
or sorta... if f.position < x, then f.position -= x would assign a
negative value to f.position. this, in turn, seeks relative to the
end of the file, thus making the file behave like a semi-cyclic
entity with a not-so-intuitive behavior... for example, assuming
a file size of 100, and a current position of 70:

pos = 70
pos -= 71 ==> pos = -1 ==> pos = (100 - 1) ==> pos = 99


in the original design, i wanted to raise an exception if seeking
relative to the current position got negative... but due to the
aforementioned technical limitations, it's not possible.

the whole issue could be solved if the descriptor protocol
supported augmented assignment -- but it requires, of course,
a drastic change to the language, something like the suggested
STORE_INPLACE_ATTR or the __iattr__ suggested by Greg.

will Guido pronounce on his choice (or dischard it altogether)?

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.python.org/pipermail/python-3000/attachments/20060612/c36705e9/attachment.htm 

More information about the Python-3000 mailing list