Gradually iterating towards the obvious -- of course I didn't need to

involve Python files.

--HG--
extra : convert_revision : svn%3Aeff31bef-be4a-0410-a8fe-e47997df2690/trunk%4040
issue20
tibs 2008-08-24 18:48:40 +00:00
rodzic 02f72c180d
commit cabde235d0
2 zmienionych plików z 83 dodań i 42 usunięć

Wyświetl plik

@ -9,16 +9,16 @@ will have to manage without. This is still better than no testing...
First, check we've got the basics working:
>>> from tstools import ESStream
>>> from tstools import ESFile
>>> try:
... stream = ESStream(test_es_file)
... stream = ESFile(test_es_file)
... except:
... test_es_file = '/home/tibs/Videos/aladdin.es'
... stream = ESStream(test_es_file)
... stream = ESFile(test_es_file)
The filename is available as a "readonly" value:
>>> stream.filename == test_es_file
>>> stream.name == test_es_file
True
We've opened it for read:
@ -78,8 +78,8 @@ And write another file...
>>> import os
>>> directory = tempfile.mkdtemp()
>>> filename = os.path.join(directory,'tstools_test_1.es')
>>> out = ESStream(filename,'w')
>>> out.filename == filename
>>> out = ESFile(filename,'w')
>>> out.name == filename
True
>>> out.is_readable() == False
True
@ -88,9 +88,25 @@ And write another file...
>>> out.mode
'w'
>>> for unit in es_unit_list:
... pass # well, this bit isn't done yet
... out.write(unit)
>>> out.close()
Did that do the right thing? Check that we can read the units back (one by
one, to test the ``read`` method), and that the units we read back are
identical to those we wrote.
>>> infile = ESFile(filename,'r')
>>> other_units = []
>>> for ii in range(0,6):
... other_units.append(infile.read())
>>>
>>> for ii in range(0,6):
... if es_unit_list[ii] != other_units[ii]:
... print 'Error: unit %d does not match'%ii
... break
// Local Variables:
// tab-width: 8

Wyświetl plik

@ -40,6 +40,16 @@ cdef extern from "stdio.h":
# as well.
cdef FILE *fdopen(int fildes, char *mode)
cdef FILE *fopen(char *path, char *mode)
cdef int fclose(FILE *stream)
cdef int fileno(FILE *stream)
cdef extern from "errno.h":
cdef int errno
cdef extern from "string.h":
cdef char *strerror(int errnum)
cdef FILE *convert_python_file(object file):
"""Given a Python file object, return an equivalent stream.
There are *so many things* dodgy about doing this...
@ -162,12 +172,6 @@ cdef class ESUnit:
"""
report_ES_unit(stdout, self.unit)
#def _set_unit(self, ES_unit_p unit):
# if self.unit:
# raise TSToolsException,'ESUnit already has an ES unit associated'
# else:
# self.unit = unit
def __dealloc__(self):
free_ES_unit(&self.unit)
@ -205,61 +209,59 @@ cdef _next_ESUnit(ES_p stream, filename):
cdef ESUnit u
u = ESUnit()
u.unit = unit
#u._set_unit(unit)
return u
cdef class ESStream:
cdef class ESFile:
"""A Python class representing an ES stream.
Initially, always a file (so maybe this should be ESFile?)
We support opening for read, or opening (creating) a new file
for write. For the moment, we don't support appending.
for write. For the moment, we don't support appending, and
support for trying to read and write the same file is undefined.
So, create a new ESStream as either:
So, create a new ESFile as either:
* ESStream(filename,'r') or
* ESStream(filename,'w')
* ESFile(filename,'r') or
* ESFile(filename,'w')
Note that there is always an implicit 'b' attached to the mode (i.e., the
file is accessed in binary mode).
"""
cdef object python_file # File as opened by Python
cdef FILE *file_stream # The corresponding C file stream
cdef int fileno # and file number
cdef ES_p stream # For reading an existing ES stream
cdef readonly object filename
cdef readonly object name
cdef readonly object mode
cdef object actual_mode
# It appears to be recommended to make __cinit__ expand to take more
# arguments (if __init__ ever gains them), since both get the same
# things passed to them. Hmm, normally I'd trust myself, but let's
# try the recommended route
def __cinit__(self,filename,mode='r',*args,**kwargs):
actual_mode = mode+'b'
self.file_stream = fopen(filename,mode)
if self.file_stream == NULL:
raise TSToolsException,"Error opening file '%s'"\
" with (actual) mode '%s': %s"%(filename,mode,strerror(errno))
self.fileno = fileno(self.file_stream)
if mode == 'r':
actual_mode = 'rb'
self.python_file = open(filename,actual_mode)
fileno = self.python_file.fileno()
self.file_stream = fdopen(fileno,actual_mode)
retval = build_elementary_stream_file(fileno,&self.stream)
retval = build_elementary_stream_file(self.fileno,&self.stream)
if retval != 0:
raise TSToolsException,'Error starting to read ES file %s'%filename
elif mode == 'w':
actual_mode = 'wb'
self.python_file = open(filename,actual_mode)
fileno = self.python_file.fileno()
self.file_stream = fdopen(fileno,actual_mode)
else:
raise ValueError,"Only modes 'r' and 'w' supported for ESStream"
raise TSToolsException,'Error attaching elementary stream to file %s'%filename
def __init__(self,filename,mode='r'):
# What should go in __init__ and what in __cinit__ ???
self.filename = filename
self.name = filename
self.mode = mode
self.actual_mode = mode + 'b'
def __dealloc__(self):
if self.file_stream != NULL:
retval = fclose(self.file_stream)
if retval != 0:
raise TSToolsException,"Error closing file '%s':"\
" %s"%(filename,strerror(errno))
if self.stream != NULL:
free_elementary_stream(&self.stream)
@ -281,15 +283,38 @@ cdef class ESStream:
def __next__(self):
"""Our iterator interface retrieves the ES units from the stream.
"""
return _next_ESUnit(self.stream,self.filename)
return _next_ESUnit(self.stream,self.name)
def read(self):
"""Read the next ES unit from this stream.
"""
try:
return _next_ESUnit(self.stream,self.name)
except StopIteration:
raise EOFError
def write(self, ESUnit unit):
"""Write an ES unit to this stream.
"""
if self.file_stream == NULL:
raise TSToolsException,'ESFile does not seem to have been opened for write'
retval = write_ES_unit(self.file_stream,unit.unit)
if retval != 0:
raise TSToolsException,'Error writing ES unit to file %s'%self.name
def close(self):
if self.python_file:
self.python_file.close()
self.python_file = None
self.mode = None
# Apparently we can't call the __dealloc__ method itself,
# but I think this is sensible to do here...
if self.file_stream != NULL:
retval = fclose(self.file_stream)
if retval != 0:
raise TSToolsException,"Error closing file '%s':"\
" %s"%(filename,strerror(errno))
if self.stream != NULL:
free_elementary_stream(&self.stream)
# And obviously we're not available any more
self.file_stream = NULL
self.fileno = -1
self.name = None
self.mode = None