1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
68
69
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
83
84 _expander = None
85
86
87
88
91
92
93
94
97
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
109 self._expander.expand(sequence)
110
112
113 _command = None
114
117
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
131
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
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
154 for object in sequence:
155 yield object
156
158
161
163 for object in self.contents(sequence):
164 self._command.send(object)
165
167
168
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
177
178 _position = None
179
183
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
196
197 if isinstance(sequence, str):
198 return self._expand_file(sequence)
199 else:
200 return None
201
203
204 _object = None
205
207 self._object = object
208
210 return 'Object of type %s cannot be expanded: %s' % (type(self._object), self._object)
211