Subclassing file and getting around the file.__init__ rigidity

J

Jan Burgy

Hi all y'all,

Consider the class down below. I've implemented it just because I
needed the pushback method. Now of course the third line in __init__
doesn't work and I even understand why. My question is: is there any
way to make it work? Somebody proposed a patch for fileobject.c to
allow stuff like fp = file(fp1.fileno()) but it looks like it's been
rejected. I won't so bold as to request a change in Python. Should I
try to re-write this class in C? Although I know C I'm much to lazy to
take on the entire python API, not that it doesn't look nice.

Thanks for your help

Jan Burgy

class BufferedFile(file):

def __init__(self, name):
if type(name) == file:
self = name # DOESN'T WORK!
else:
file.__init__(self, name)
self.buffer = None

def readline(self):
if self.buffer:
i = self.buffer.find("\n")
line, self.buffer = self.buffer[:i], self.buffer[:i+1]
else:
line = file.readline(self)
return line

def pushback(self, line):
self.buffer = line + self.buffer
 
?

=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=

Jan said:
Consider the class down below. I've implemented it just because I
needed the pushback method. Now of course the third line in __init__
doesn't work and I even understand why. My question is: is there any
way to make it work?

What do you mean, it doesn't work? It does precisely what it says it
does:
class BufferedFile(file):

def __init__(self, name):
if type(name) == file:
self = name # DOESN'T WORK!

This assigns the local variable self to be the value of the local
variable name. As a result of that assignment, self does not refer
anymore to the object being created, but instead, it refers to
the first parameter. The object just being created is then not
accessible anymore.

If you thought this assignment might modify the object being created
in some way: Why would you think so?

Regards,
Martin
 
F

F. GEIGER

# Untested code

class BufferedFile(file):

def __init__(self, name):
if type(name) == file:
self.__dict__.update(file.__dict__) # Kinda cctor
else:
file.__init__(self, name)
self.buffer = None

Cheers
Franz
 
J

Jan Burgy

Hi Franz,

your idea is exactly the type of stuff I was thinking of.
Unfortunately it doesn't work... Does anybody see what we're doing
wrong?

Thanks to all

Jan Burgy

F. GEIGER said:
# Untested code

class BufferedFile(file):

def __init__(self, name):
if type(name) == file:
self.__dict__.update(file.__dict__) # Kinda cctor
else:
file.__init__(self, name)
self.buffer = None

Cheers
Franz

Jan Burgy said:
Hi all y'all,

Consider the class down below. I've implemented it just because I
needed the pushback method. Now of course the third line in __init__
doesn't work and I even understand why. My question is: is there any
way to make it work? Somebody proposed a patch for fileobject.c to
allow stuff like fp = file(fp1.fileno()) but it looks like it's been
rejected. I won't so bold as to request a change in Python. Should I
try to re-write this class in C? Although I know C I'm much to lazy to
take on the entire python API, not that it doesn't look nice.

Thanks for your help

Jan Burgy

class BufferedFile(file):

def __init__(self, name):
if type(name) == file:
self = name # DOESN'T WORK!
else:
file.__init__(self, name)
self.buffer = None

def readline(self):
if self.buffer:
i = self.buffer.find("\n")
line, self.buffer = self.buffer[:i], self.buffer[:i+1]
else:
line = file.readline(self)
return line

def pushback(self, line):
self.buffer = line + self.buffer
 
P

Peter Otten

Jan said:
Hi all y'all,

Consider the class down below. I've implemented it just because I
needed the pushback method. Now of course the third line in __init__
doesn't work and I even understand why. My question is: is there any
way to make it work? Somebody proposed a patch for fileobject.c to
allow stuff like fp = file(fp1.fileno()) but it looks like it's been
rejected. I won't so bold as to request a change in Python. Should I
try to re-write this class in C? Although I know C I'm much to lazy to
take on the entire python API, not that it doesn't look nice.

Thanks for your help

Jan Burgy

class BufferedFile(file):

def __init__(self, name):
if type(name) == file:
self = name # DOESN'T WORK!
else:
file.__init__(self, name)
self.buffer = None

def readline(self):
if self.buffer:
i = self.buffer.find("\n")
line, self.buffer = self.buffer[:i], self.buffer[:i+1]
else:
line = file.readline(self)
return line

def pushback(self, line):
self.buffer = line + self.buffer

Here's a way to force it by using a wrapper instead of a subclass:

class BufferedFile(object):
def __init__(self, name, *more):
if isinstance(name, basestring):
self.fo = file(name, *more)
else:
self.fo = name
assert len(more) == 0
self.buffer = []

def readline(self):
if self.buffer:
return self.buffer.pop()
return self.fo.readline()

def __iter__(self):
return self

def next(self):
result = self.readline()
if not result:
raise StopIteration
return result

def pushback(self, line):
self.buffer.append(line)

def __getattr__(self, name):
return getattr(self.fo, name)

Unfortunately it grew clumsier than I originaly expected because of the
duplicated interface (next() and readline() for essentially the same
thing). Personally, I would recommend using the subclass approach and drop
the requirement of accepting a file object as an __init__() parameter.
Still the above has the advantage of working with "real files" and StringIO
objects alike (not tested, so don't blame me).


Peter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top