Package Bio :: Module ParserSupport
[hide private]
[frames] | no frames]

Source Code for Module Bio.ParserSupport

  1  # Copyright 1999 by Jeffrey Chang.  All rights reserved. 
  2  # This code is part of the Biopython distribution and governed by its 
  3  # license.  Please see the LICENSE file that should have been included 
  4  # as part of this package. 
  5   
  6  """Code to support writing parsers (DEPRECATED). 
  7   
  8  Classes: 
  9   
 10      - AbstractParser         Base class for parsers. 
 11      - AbstractConsumer       Base class of all Consumers. 
 12      - TaggingConsumer        Consumer that tags output with its event.  For debugging 
 13   
 14  Functions: 
 15   
 16      - safe_readline          Read a line from a handle, with check for EOF. 
 17      - safe_peekline          Peek at next line, with check for EOF. 
 18      - read_and_call          Read a line from a handle and pass it to a method. 
 19      - read_and_call_while    Read many lines, as long as a condition is met. 
 20      - read_and_call_until    Read many lines, until a condition is met. 
 21      - attempt_read_and_call  Like read_and_call, but forgiving of errors. 
 22      - is_blank_line          Test whether a line is blank. 
 23   
 24  """ 
 25   
 26  import sys 
 27  from Bio._py3k import StringIO 
 28   
 29  from Bio import BiopythonDeprecationWarning 
 30  import warnings 
 31  warnings.warn("Bio.ParserSupport is now deprecated will be removed in a " 
 32                "future release of Biopython.", BiopythonDeprecationWarning) 
 33   
 34   
35 -class AbstractParser(object):
36 """Base class for other parsers. 37 38 """
39 - def parse(self, handle):
40 raise NotImplementedError("Please implement in a derived class")
41
42 - def parse_str(self, string):
43 return self.parse(StringIO(string))
44
45 - def parse_file(self, filename):
46 with open(filename) as h: 47 retval = self.parse(h) 48 return retval
49 50
51 -class AbstractConsumer(object):
52 """Base class for other Consumers. 53 54 Derive Consumers from this class and implement appropriate 55 methods for each event that you want to receive. 56 57 """
58 - def _unhandled_section(self):
59 pass
60
61 - def _unhandled(self, data):
62 pass
63
64 - def __getattr__(self, attr):
65 if attr[:6] == 'start_' or attr[:4] == 'end_': 66 method = self._unhandled_section 67 else: 68 method = self._unhandled 69 return method
70 71
72 -class TaggingConsumer(AbstractConsumer):
73 """A Consumer that tags the data stream with the event and 74 prints it to a handle. Useful for debugging. 75 76 """
77 - def __init__(self, handle=None, colwidth=15, maxwidth=80):
78 """TaggingConsumer(handle=sys.stdout, colwidth=15, maxwidth=80)""" 79 # I can't assign sys.stdout to handle in the argument list. 80 # If I do that, handle will be assigned the value of sys.stdout 81 # the first time this function is called. This will fail if 82 # the user has assigned sys.stdout to some other file, which may 83 # be closed or invalid at a later time. 84 if handle is None: 85 handle = sys.stdout 86 self._handle = handle 87 self._colwidth = colwidth 88 self._maxwidth = maxwidth
89
90 - def unhandled_section(self):
91 self._print_name('unhandled_section')
92
93 - def unhandled(self, data):
94 self._print_name('unhandled', data)
95
96 - def _print_name(self, name, data=None):
97 if data is None: 98 # Write the name of a section. 99 self._handle.write("%s %s\n" % ("*" * self._colwidth, name)) 100 else: 101 # Write the tag and line. 102 self._handle.write("%-*s: %s\n" % ( 103 self._colwidth, name[:self._colwidth], 104 data[:self._maxwidth - self._colwidth - 2].rstrip()))
105
106 - def __getattr__(self, attr):
107 if attr[:6] == 'start_' or attr[:4] == 'end_': 108 method = lambda a=attr, s=self: s._print_name(a) 109 else: 110 method = lambda x, a=attr, s=self: s._print_name(a, x) 111 return method
112 113
114 -def read_and_call(uhandle, method, **keywds):
115 """read_and_call(uhandle, method[, start][, end][, contains][, blank][, has_re]) 116 117 Read a line from uhandle, check it, and pass it to the method. 118 Raises a ValueError if the line does not pass the checks. 119 120 start, end, contains, blank, and has_re specify optional conditions 121 that the line must pass. start and end specifies what the line must 122 begin or end with (not counting EOL characters). contains 123 specifies a substring that must be found in the line. If blank 124 is a true value, then the line must be blank. has_re should be 125 a regular expression object with a pattern that the line must match 126 somewhere. 127 128 """ 129 line = safe_readline(uhandle) 130 errmsg = _fails_conditions(*(line,), **keywds) 131 if errmsg is not None: 132 raise ValueError(errmsg) 133 method(line)
134 135
136 -def read_and_call_while(uhandle, method, **keywds):
137 """read_and_call_while(uhandle, method[, start][, end][, contains][, blank][, has_re]) -> number of lines 138 139 Read a line from uhandle and pass it to the method as long as 140 some condition is true. Returns the number of lines that were read. 141 142 See the docstring for read_and_call for a description of the parameters. 143 144 """ 145 nlines = 0 146 while True: 147 line = safe_readline(uhandle) 148 # If I've failed the condition, then stop reading the line. 149 if _fails_conditions(*(line,), **keywds): 150 uhandle.saveline(line) 151 break 152 method(line) 153 nlines = nlines + 1 154 return nlines
155 156
157 -def read_and_call_until(uhandle, method, **keywds):
158 """read_and_call_until(uhandle, method, 159 start=None, end=None, contains=None, blank=None) -> number of lines 160 161 Read a line from uhandle and pass it to the method until 162 some condition is true. Returns the number of lines that were read. 163 164 See the docstring for read_and_call for a description of the parameters. 165 166 """ 167 nlines = 0 168 while True: 169 line = safe_readline(uhandle) 170 # If I've met the condition, then stop reading the line. 171 if not _fails_conditions(*(line,), **keywds): 172 uhandle.saveline(line) 173 break 174 method(line) 175 nlines = nlines + 1 176 return nlines
177 178
179 -def attempt_read_and_call(uhandle, method, **keywds):
180 """attempt_read_and_call(uhandle, method, **keywds) -> boolean 181 182 Similar to read_and_call, but returns a boolean specifying 183 whether the line has passed the checks. Does not raise 184 exceptions. 185 186 See docs for read_and_call for a description of the function 187 arguments. 188 189 """ 190 line = safe_readline(uhandle) 191 passed = not _fails_conditions(*(line,), **keywds) 192 if passed: 193 method(line) 194 else: 195 uhandle.saveline(line) 196 return passed
197 198
199 -def _fails_conditions(line, start=None, end=None, contains=None, blank=None, 200 has_re=None):
201 if start is not None: 202 if line[:len(start)] != start: 203 return "Line does not start with '%s':\n%s" % (start, line) 204 if end is not None: 205 if line.rstrip()[-len(end):] != end: 206 return "Line does not end with '%s':\n%s" % (end, line) 207 if contains is not None: 208 if contains not in line: 209 return "Line does not contain '%s':\n%s" % (contains, line) 210 if blank is not None: 211 if blank: 212 if not is_blank_line(line): 213 return "Expected blank line, but got:\n%s" % line 214 else: 215 if is_blank_line(line): 216 return "Expected non-blank line, but got a blank one" 217 if has_re is not None: 218 if has_re.search(line) is None: 219 return "Line does not match regex '%s':\n%s" % ( 220 has_re.pattern, line) 221 return None
222 223
224 -def is_blank_line(line, allow_spaces=0):
225 """is_blank_line(line, allow_spaces=0) -> boolean 226 227 Return whether a line is blank. allow_spaces specifies whether to 228 allow whitespaces in a blank line. A true value signifies that a 229 line containing whitespaces as well as end-of-line characters 230 should be considered blank. 231 232 """ 233 if not line: 234 return 1 235 if allow_spaces: 236 return line.rstrip() == '' 237 return line[0] == '\n' or line[0] == '\r'
238 239
240 -def safe_readline(handle):
241 """safe_readline(handle) -> line 242 243 Read a line from an UndoHandle and return it. If there are no more 244 lines to read, I will raise a ValueError. 245 246 """ 247 line = handle.readline() 248 if not line: 249 raise ValueError("Unexpected end of stream.") 250 return line
251 252
253 -def safe_peekline(handle):
254 """safe_peekline(handle) -> line 255 256 Peek at the next line in an UndoHandle and return it. If there are no 257 more lines to peek, I will raise a ValueError. 258 259 """ 260 line = handle.peekline() 261 if not line: 262 raise ValueError("Unexpected end of stream.") 263 return line
264