6.3.2. Sink Drivers

Sink drivers support the standard Python file protocol for output of text. They supply the standard python file methods:
write
Write text to output device. Repeatedly raw_write characters upto either the end of the string, or a newline character. If a newline character is found, increment the line count amd call raw_eol. Precondition: no control characters other than newline in the input.
writelines
Accepts a list of strings which are concatenated and passed to the write method. No newline characters are added. Precondition: no control characters other than newline in the input.
close
If the sink is not flagged as closed, flag the sink as closed for access to the device and call raw_close. Note this need not close the underlying device.
flush
May flush data to the device.
isatty
May return 1 if the underlying device is a tty type device.

The methods read, readline and readlines are note provided because a sink need not support read operations. The methods seek and tell are not provided because sinks need not support positioning. The method truncate is not provided because a sink need not be storage device. There is no mode attribute, sinks support writing, but need not be files.

The following methods augment the standard python methods.

writeline
Append a newline character to the argument and pass to write method.
raw_writelines
Accepts a list of strings which are written in turn using writeline. Use with a list of printable strings; that is, without trailing newlines.
The following methods should be provided by subclass derivers, if the default implementation (if it exists) is inappropriate. They are intended as private implementation details, not to be called by the user.
raw_write
Write raw text to the device. Precondition: only printable characters in the input (space is allowed). [All characters are written verbatim to the underlying device without incrementing the line count.]
raw_close
May close the underlying device. Called by the close method if the closed flag is false.
raw_flush
May flush the underlying device device.
raw_eol
Ends a line on the underlying device.
In addition, the following attributes are available:
lines_written
The total number of calls to writeline.
last_source_file
Provided for the client to store the name of the original source of the last line written.
last_source_line
Provided for the client to store the line number of the last line written in the original source file.
last_inhibit_sref
Provided for the client to store whether source referencing was disabled on the last write.
closed
Indicates if close was called.
Start python section to interscript/drivers/sinks/__init__.py[1 /1 ]
     1: #line 96 "sink_drivers.ipk"
     2: #--- sink package ---
     3: class sink_open_error(Exception): pass
     4: 
     5: 
End python section to interscript/drivers/sinks/__init__.py[1]
Start python section to interscript/drivers/sinks/util.py[1 /1 ]
     1: #line 102 "sink_drivers.ipk"
     2: import os
     3: posixpath = os.path
     4: import errno
     5: 
     6: # OS dependent routines.
     7: # Note: we use some posixpath functions, but don't trust them
     8: 
     9: # make the given directory, no error if it exists
    10: # this is posix specific, and should be moved to a platform
    11: # dependent place in the code
    12: 
    13: def create_directory(dir):
    14:   if not posixpath.isdir(dir):
    15:     try: os.mkdir(dir)
    16:     except os.error, data:
    17:       if data[0]!=errno.EEXIST: # File Exists is OK, everything else is fatal
    18:         raise os.error, (data[0],data+': directory "'+dir+'"')
    19:   if not posixpath.isdir(dir):
    20:     raise os.error, (errno.ENOENT, 'Created a directory '+dir+', but it is not there!')
    21: 
    22: # given an os specific prefix and a list of component names,
    23: # make the directory structure in which the last component is contained
    24: # and synthesise and return its full os specific pathname
    25: 
    26: def mk_dir(prefix, pathlist):
    27:   if len(pathlist)>1:
    28:     # there's more than one component in the list
    29:     # so create directories for all but the last component
    30: 
    31:     pathname = prefix+pathlist[0]
    32:     create_directory(pathname)
    33:     for component in pathlist[1:-1]:
    34:       pathname = pathname + os.sep + component
    35:       create_directory(pathname)
    36:     pathname = pathname + os.sep + pathlist[-1]
    37: 
    38:   else:
    39:     # only one component on the list
    40:     pathname = prefix+pathlist[0]
    41: 
    42:   if pathname[0]!=os.sep:
    43:     # the pathname isn't absolute, so make it so
    44:     # get current directory
    45:     curdir = os.getcwd()
    46: 
    47:     # strip trailing separator
    48:     # note this should fix cases like '/' (unix) or 'd:\' (nt)
    49:     # as well as cope with systems that return a trailing separator
    50:     if curdir[-1] == os.sep: curdir = curdir[:-1]
    51: 
    52:     # append a separator and the pathname: there will only be one
    53:     # separator at the join point unless the current directory
    54:     # ends with two separators (like the URL: http://)
    55:     pathname = curdir + os.sep + pathname
    56:   return pathname
    57: 
    58: # this routine checks is a file exists and is readable
    59: # (in the sense that it can be opened for read)
    60: # it returns 1 if the file exist and can be read, 0 if the file
    61: # doesn't exist, and throws an exception if anything else goes wrong
    62: 
    63: def file_exists(pathname):
    64:   try:
    65:     # note this leaks a file if it is opened but not closed :-))
    66:     open(pathname,'r').close()
    67:     return 1
    68:   except IOError, data:
    69:     if data[0] == errno.ENOENT:
    70:       return 0
    71:     raise IOError, data
    72: 
    73: # Note: the intention is to apply mk_dir to ensure the file has a
    74: # parent directory, creating it if necessary, then test if the file
    75: # already exists or has to be created. Even if it exists, it may have
    76: # to be replaced.
    77: 
End python section to interscript/drivers/sinks/util.py[1]


6.3.2.1. Sink Base Class
6.3.2.2. Null Sink
6.3.2.3. Tee Sink
6.3.2.4. Simple Disk File Sink
6.3.2.5. Complex Disk File Sink
6.3.2.6. Standard Output Sink
6.3.2.7. Persistent Storage Sink