Package osh :: Package command :: Module expand
[frames] | no frames]

Source Code for Module osh.command.expand

  1  # osh 
  2  # Copyright (C) 2005 Jack Orenstein <jao@geophile.com> 
  3  # 
  4  # This program is free software; you can redistribute it and/or modify 
  5  # it under the terms of the GNU General Public License as published by 
  6  # the Free Software Foundation; either version 2 of the License, or 
  7  # (at your option) any later version. 
  8  # 
  9  # This program is distributed in the hope that it will be useful, 
 10  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 11  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 12  # GNU General Public License for more details. 
 13  # 
 14  # You should have received a copy of the GNU General Public License 
 15  # along with this program; if not, write to the Free Software 
 16  # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 17   
 18  """C{expand [POSITION]} 
 19   
 20  Receives a stream of sequences as input. If C{POSITION} is omitted, then 
 21  each item of the sequence is generated as a separate 1-tuple in the 
 22  output stream. 
 23   
 24  B{Example}: If the input contains these sequences:: 
 25   
 26      ('a', 'b') 
 27      ('c', 'd') 
 28   
 29  then C{expand} generates this output:: 
 30      ('a',) 
 31      ('b',) 
 32      ('c',) 
 33      ('d',) 
 34   
 35  If C{POSITION} is specified, then each input sequence is used to generate 
 36  zero or more output sequences. In each output sequence, the item at the 
 37  selected position is replaced by one component of the selected object. 
 38   
 39  The types that can be expanded are C{list}, C{tuple}, C{generator} and 
 40  C{string}. When a string is expanded, the string is interpreted as a 
 41  filename, and expansion yields each line of the named file. 
 42   
 43  B{Example}: If the input contains these sequences:: 
 44   
 45      ('a', [1, 2, 3], 'x') 
 46      ('b', [4, 5], 'y') 
 47      ('c', [], 'z') 
 48   
 49  then C{expand 1} generates this output:: 
 50   
 51      ('a', 1, 'x') 
 52      ('a', 2, 'x') 
 53      ('a', 3, 'x') 
 54      ('b', 4, 'y') 
 55      ('b', 5, 'y') 
 56   
 57  Note that an empty nested sequence results in no output, (as for 
 58  C{('c', [], 'z')}.) 
 59  """ 
 60   
 61  import types 
 62   
 63  import osh.core 
 64   
 65  # CLI 
66 -def _expand():
67 return _Expand()
68 69 # API
70 -def expand(position = None):
71 """Flattens an input sequence by generating output sequences in which an interior element 72 is expanded. If C{position} is omitted, then each element of the input sequence is generated 73 as a separate 1-tuples. If C{position} is specified, then the item at the given position 74 is expanded. If the element being expanded is a string, then the string is interpreted 75 as a filename, and the expansion yields each line of the file in turn. 76 """ 77 args = [] 78 if position is not None: 79 args.append(position) 80 return _Expand().process_args(*args)
81
82 -class _Expand(osh.core.Op):
83 84 _expander = None 85 86 87 # object interface 88
89 - def __init__(self):
90 osh.core.Op.__init__(self, None, (0, 1))
91 92 93 # BaseOp interface 94
95 - def doc(self):
96 return __doc__
97
98 - def setup(self):
99 args = self.args() 100 position = args.next_int() 101 if position is not None and args.has_next(): 102 self.usage() 103 if position is None: 104 self._expander = _SequenceExpander(self) 105 else: 106 self._expander = _ComponentExpander(self, position)
107
108 - def receive(self, sequence):
109 self._expander.expand(sequence)
110
111 -class _Expander(object):
112 113 _command = None 114
115 - def __init__(self, command):
116 self._command = command
117
118 - def expand(self, sequence):
119 assert False
120
121 - def contents(self, object):
122 contents_generator = self._expand_as_file(object) 123 if not contents_generator: 124 contents_generator = self._expand_as_sequence(object) 125 if not contents_generator: 126 raise _NotExpandableException(object) 127 return contents_generator
128
129 - def _expand_as_file(self, object):
130 assert False
131
132 - def _expand_as_sequence(self, object):
133 if (isinstance(object, tuple) or 134 isinstance(object, list) or 135 isinstance(object, types.GeneratorType)): 136 return self._expand_sequence(object) 137 else: 138 return None
139
140 - def _expand_file(self, filename):
141 file = open(filename, 'r') 142 eof = False 143 while not eof: 144 line = file.readline() 145 if line: 146 if line.endswith('\n'): 147 line = line[:-1] 148 yield line 149 else: 150 eof = True 151 file.close()
152
153 - def _expand_sequence(self, sequence):
154 for object in sequence: 155 yield object
156
157 -class _SequenceExpander(_Expander):
158
159 - def __init__(self, command):
160 _Expander.__init__(self, command)
161
162 - def expand(self, sequence):
163 for object in self.contents(sequence): 164 self._command.send(object)
165
166 - def _expand_as_file(self, object):
167 # Expand as file if object is a sequence of len 1, 168 # containing a string (which is interpreted as a filename). 169 if ((isinstance(object, tuple) or isinstance(object, list)) and len(object) == 1): 170 object = object[0] 171 if isinstance(object, str): 172 return self._expand_file(object) 173 else: 174 return None
175
176 -class _ComponentExpander(_Expander):
177 178 _position = None 179
180 - def __init__(self, command, position):
181 _Expander.__init__(self, command) 182 self._position = position
183
184 - def expand(self, sequence):
185 pre = sequence[:self._position] 186 if self._position == -1: 187 post = tuple() 188 else: 189 post = sequence[(self._position + 1):] 190 contents = self.contents(sequence[self._position]) 191 for object in contents: 192 output = pre + (object,) + post 193 self._command.send(output)
194
195 - def _expand_as_file(self, sequence):
196 # Expand as file if item at position is a string. 197 if isinstance(sequence, str): 198 return self._expand_file(sequence) 199 else: 200 return None
201
202 -class _NotExpandableException(Exception):
203 204 _object = None 205
206 - def __init__(self, object):
207 self._object = object
208
209 - def __str__(self):
210 return 'Object of type %s cannot be expanded: %s' % (type(self._object), self._object)
211