Show More
@@ -1,278 +1,284 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 | """String interpolation for Python (by Ka-Ping Yee, 14 Feb 2000). |
|
2 | """String interpolation for Python (by Ka-Ping Yee, 14 Feb 2000). | |
3 |
|
3 | |||
4 | This module lets you quickly and conveniently interpolate values into |
|
4 | This module lets you quickly and conveniently interpolate values into | |
5 | strings (in the flavour of Perl or Tcl, but with less extraneous |
|
5 | strings (in the flavour of Perl or Tcl, but with less extraneous | |
6 | punctuation). You get a bit more power than in the other languages, |
|
6 | punctuation). You get a bit more power than in the other languages, | |
7 | because this module allows subscripting, slicing, function calls, |
|
7 | because this module allows subscripting, slicing, function calls, | |
8 | attribute lookup, or arbitrary expressions. Variables and expressions |
|
8 | attribute lookup, or arbitrary expressions. Variables and expressions | |
9 | are evaluated in the namespace of the caller. |
|
9 | are evaluated in the namespace of the caller. | |
10 |
|
10 | |||
11 | The itpl() function returns the result of interpolating a string, and |
|
11 | The itpl() function returns the result of interpolating a string, and | |
12 | printpl() prints out an interpolated string. Here are some examples: |
|
12 | printpl() prints out an interpolated string. Here are some examples: | |
13 |
|
13 | |||
14 | from Itpl import printpl |
|
14 | from Itpl import printpl | |
15 | printpl("Here is a $string.") |
|
15 | printpl("Here is a $string.") | |
16 | printpl("Here is a $module.member.") |
|
16 | printpl("Here is a $module.member.") | |
17 | printpl("Here is an $object.member.") |
|
17 | printpl("Here is an $object.member.") | |
18 | printpl("Here is a $functioncall(with, arguments).") |
|
18 | printpl("Here is a $functioncall(with, arguments).") | |
19 | printpl("Here is an ${arbitrary + expression}.") |
|
19 | printpl("Here is an ${arbitrary + expression}.") | |
20 | printpl("Here is an $array[3] member.") |
|
20 | printpl("Here is an $array[3] member.") | |
21 | printpl("Here is a $dictionary['member'].") |
|
21 | printpl("Here is a $dictionary['member'].") | |
22 |
|
22 | |||
23 | The filter() function filters a file object so that output through it |
|
23 | The filter() function filters a file object so that output through it | |
24 | is interpolated. This lets you produce the illusion that Python knows |
|
24 | is interpolated. This lets you produce the illusion that Python knows | |
25 | how to do interpolation: |
|
25 | how to do interpolation: | |
26 |
|
26 | |||
27 | import Itpl |
|
27 | import Itpl | |
28 | sys.stdout = Itpl.filter() |
|
28 | sys.stdout = Itpl.filter() | |
29 | f = "fancy" |
|
29 | f = "fancy" | |
30 | print "Isn't this $f?" |
|
30 | print "Isn't this $f?" | |
31 | print "Standard output has been replaced with a $sys.stdout object." |
|
31 | print "Standard output has been replaced with a $sys.stdout object." | |
32 | sys.stdout = Itpl.unfilter() |
|
32 | sys.stdout = Itpl.unfilter() | |
33 | print "Okay, back $to $normal." |
|
33 | print "Okay, back $to $normal." | |
34 |
|
34 | |||
35 | Under the hood, the Itpl class represents a string that knows how to |
|
35 | Under the hood, the Itpl class represents a string that knows how to | |
36 | interpolate values. An instance of the class parses the string once |
|
36 | interpolate values. An instance of the class parses the string once | |
37 | upon initialization; the evaluation and substitution can then be done |
|
37 | upon initialization; the evaluation and substitution can then be done | |
38 | each time the instance is evaluated with str(instance). For example: |
|
38 | each time the instance is evaluated with str(instance). For example: | |
39 |
|
39 | |||
40 | from Itpl import Itpl |
|
40 | from Itpl import Itpl | |
41 | s = Itpl("Here is $foo.") |
|
41 | s = Itpl("Here is $foo.") | |
42 | foo = 5 |
|
42 | foo = 5 | |
43 | print str(s) |
|
43 | print str(s) | |
44 | foo = "bar" |
|
44 | foo = "bar" | |
45 | print str(s) |
|
45 | print str(s) | |
46 |
|
46 | |||
47 | $Id: Itpl.py 958 2005-12-27 23:17:51Z fperez $ |
|
47 | $Id: Itpl.py 2918 2007-12-31 14:34:47Z vivainio $ | |
48 | """ # ' -> close an open quote for stupid emacs |
|
48 | """ # ' -> close an open quote for stupid emacs | |
49 |
|
49 | |||
50 | #***************************************************************************** |
|
50 | #***************************************************************************** | |
51 | # |
|
51 | # | |
52 | # Copyright (c) 2001 Ka-Ping Yee <ping@lfw.org> |
|
52 | # Copyright (c) 2001 Ka-Ping Yee <ping@lfw.org> | |
53 | # |
|
53 | # | |
54 | # |
|
54 | # | |
55 | # Published under the terms of the MIT license, hereby reproduced: |
|
55 | # Published under the terms of the MIT license, hereby reproduced: | |
56 | # |
|
56 | # | |
57 | # Permission is hereby granted, free of charge, to any person obtaining a copy |
|
57 | # Permission is hereby granted, free of charge, to any person obtaining a copy | |
58 | # of this software and associated documentation files (the "Software"), to |
|
58 | # of this software and associated documentation files (the "Software"), to | |
59 | # deal in the Software without restriction, including without limitation the |
|
59 | # deal in the Software without restriction, including without limitation the | |
60 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
|
60 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | |
61 | # sell copies of the Software, and to permit persons to whom the Software is |
|
61 | # sell copies of the Software, and to permit persons to whom the Software is | |
62 | # furnished to do so, subject to the following conditions: |
|
62 | # furnished to do so, subject to the following conditions: | |
63 | # |
|
63 | # | |
64 | # The above copyright notice and this permission notice shall be included in |
|
64 | # The above copyright notice and this permission notice shall be included in | |
65 | # all copies or substantial portions of the Software. |
|
65 | # all copies or substantial portions of the Software. | |
66 | # |
|
66 | # | |
67 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
67 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
68 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
68 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
69 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
69 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
70 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
70 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
71 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|
71 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
72 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
|
72 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
73 | # IN THE SOFTWARE. |
|
73 | # IN THE SOFTWARE. | |
74 | # |
|
74 | # | |
75 | #***************************************************************************** |
|
75 | #***************************************************************************** | |
76 |
|
76 | |||
77 | __author__ = 'Ka-Ping Yee <ping@lfw.org>' |
|
77 | __author__ = 'Ka-Ping Yee <ping@lfw.org>' | |
78 | __license__ = 'MIT' |
|
78 | __license__ = 'MIT' | |
79 |
|
79 | |||
80 | import string |
|
80 | import string | |
81 | import sys |
|
81 | import sys | |
82 | from tokenize import tokenprog |
|
82 | from tokenize import tokenprog | |
83 | from types import StringType |
|
83 | from types import StringType | |
84 |
|
84 | |||
85 | class ItplError(ValueError): |
|
85 | class ItplError(ValueError): | |
86 | def __init__(self, text, pos): |
|
86 | def __init__(self, text, pos): | |
87 | self.text = text |
|
87 | self.text = text | |
88 | self.pos = pos |
|
88 | self.pos = pos | |
89 | def __str__(self): |
|
89 | def __str__(self): | |
90 | return "unfinished expression in %s at char %d" % ( |
|
90 | return "unfinished expression in %s at char %d" % ( | |
91 | repr(self.text), self.pos) |
|
91 | repr(self.text), self.pos) | |
92 |
|
92 | |||
93 | def matchorfail(text, pos): |
|
93 | def matchorfail(text, pos): | |
94 | match = tokenprog.match(text, pos) |
|
94 | match = tokenprog.match(text, pos) | |
95 | if match is None: |
|
95 | if match is None: | |
96 | raise ItplError(text, pos) |
|
96 | raise ItplError(text, pos) | |
97 | return match, match.end() |
|
97 | return match, match.end() | |
98 |
|
98 | |||
99 | class Itpl: |
|
99 | class Itpl: | |
100 | """Class representing a string with interpolation abilities. |
|
100 | """Class representing a string with interpolation abilities. | |
101 |
|
101 | |||
102 | Upon creation, an instance works out what parts of the format |
|
102 | Upon creation, an instance works out what parts of the format | |
103 | string are literal and what parts need to be evaluated. The |
|
103 | string are literal and what parts need to be evaluated. The | |
104 | evaluation and substitution happens in the namespace of the |
|
104 | evaluation and substitution happens in the namespace of the | |
105 | caller when str(instance) is called.""" |
|
105 | caller when str(instance) is called.""" | |
106 |
|
106 | |||
107 |
def __init__(self, format,codec= |
|
107 | def __init__(self, format,codec=sys.stdin.encoding,encoding_errors='backslashreplace'): | |
108 | """The single mandatory argument to this constructor is a format |
|
108 | """The single mandatory argument to this constructor is a format | |
109 | string. |
|
109 | string. | |
110 |
|
110 | |||
111 | The format string is parsed according to the following rules: |
|
111 | The format string is parsed according to the following rules: | |
112 |
|
112 | |||
113 | 1. A dollar sign and a name, possibly followed by any of: |
|
113 | 1. A dollar sign and a name, possibly followed by any of: | |
114 | - an open-paren, and anything up to the matching paren |
|
114 | - an open-paren, and anything up to the matching paren | |
115 | - an open-bracket, and anything up to the matching bracket |
|
115 | - an open-bracket, and anything up to the matching bracket | |
116 | - a period and a name |
|
116 | - a period and a name | |
117 | any number of times, is evaluated as a Python expression. |
|
117 | any number of times, is evaluated as a Python expression. | |
118 |
|
118 | |||
119 | 2. A dollar sign immediately followed by an open-brace, and |
|
119 | 2. A dollar sign immediately followed by an open-brace, and | |
120 | anything up to the matching close-brace, is evaluated as |
|
120 | anything up to the matching close-brace, is evaluated as | |
121 | a Python expression. |
|
121 | a Python expression. | |
122 |
|
122 | |||
123 | 3. Outside of the expressions described in the above two rules, |
|
123 | 3. Outside of the expressions described in the above two rules, | |
124 | two dollar signs in a row give you one literal dollar sign. |
|
124 | two dollar signs in a row give you one literal dollar sign. | |
125 |
|
125 | |||
126 | Optional arguments: |
|
126 | Optional arguments: | |
127 |
|
127 | |||
128 | - codec('utf_8'): a string containing the name of a valid Python |
|
128 | - codec('utf_8'): a string containing the name of a valid Python | |
129 | codec. |
|
129 | codec. | |
130 |
|
130 | |||
131 | - encoding_errors('backslashreplace'): a string with a valid error handling |
|
131 | - encoding_errors('backslashreplace'): a string with a valid error handling | |
132 | policy. See the codecs module documentation for details. |
|
132 | policy. See the codecs module documentation for details. | |
133 |
|
133 | |||
134 | These are used to encode the format string if a call to str() fails on |
|
134 | These are used to encode the format string if a call to str() fails on | |
135 | the expanded result.""" |
|
135 | the expanded result.""" | |
136 |
|
136 | |||
137 | if not isinstance(format,basestring): |
|
137 | if not isinstance(format,basestring): | |
138 | raise TypeError, "needs string initializer" |
|
138 | raise TypeError, "needs string initializer" | |
139 | self.format = format |
|
139 | self.format = format | |
140 | self.codec = codec |
|
140 | self.codec = codec | |
141 | self.encoding_errors = encoding_errors |
|
141 | self.encoding_errors = encoding_errors | |
142 |
|
142 | |||
143 | namechars = "abcdefghijklmnopqrstuvwxyz" \ |
|
143 | namechars = "abcdefghijklmnopqrstuvwxyz" \ | |
144 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; |
|
144 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; | |
145 | chunks = [] |
|
145 | chunks = [] | |
146 | pos = 0 |
|
146 | pos = 0 | |
147 |
|
147 | |||
148 | while 1: |
|
148 | while 1: | |
149 | dollar = string.find(format, "$", pos) |
|
149 | dollar = string.find(format, "$", pos) | |
150 | if dollar < 0: break |
|
150 | if dollar < 0: break | |
151 | nextchar = format[dollar+1] |
|
151 | nextchar = format[dollar+1] | |
152 |
|
152 | |||
153 | if nextchar == "{": |
|
153 | if nextchar == "{": | |
154 | chunks.append((0, format[pos:dollar])) |
|
154 | chunks.append((0, format[pos:dollar])) | |
155 | pos, level = dollar+2, 1 |
|
155 | pos, level = dollar+2, 1 | |
156 | while level: |
|
156 | while level: | |
157 | match, pos = matchorfail(format, pos) |
|
157 | match, pos = matchorfail(format, pos) | |
158 | tstart, tend = match.regs[3] |
|
158 | tstart, tend = match.regs[3] | |
159 | token = format[tstart:tend] |
|
159 | token = format[tstart:tend] | |
160 | if token == "{": level = level+1 |
|
160 | if token == "{": level = level+1 | |
161 | elif token == "}": level = level-1 |
|
161 | elif token == "}": level = level-1 | |
162 | chunks.append((1, format[dollar+2:pos-1])) |
|
162 | chunks.append((1, format[dollar+2:pos-1])) | |
163 |
|
163 | |||
164 | elif nextchar in namechars: |
|
164 | elif nextchar in namechars: | |
165 | chunks.append((0, format[pos:dollar])) |
|
165 | chunks.append((0, format[pos:dollar])) | |
166 | match, pos = matchorfail(format, dollar+1) |
|
166 | match, pos = matchorfail(format, dollar+1) | |
167 | while pos < len(format): |
|
167 | while pos < len(format): | |
168 | if format[pos] == "." and \ |
|
168 | if format[pos] == "." and \ | |
169 | pos+1 < len(format) and format[pos+1] in namechars: |
|
169 | pos+1 < len(format) and format[pos+1] in namechars: | |
170 | match, pos = matchorfail(format, pos+1) |
|
170 | match, pos = matchorfail(format, pos+1) | |
171 | elif format[pos] in "([": |
|
171 | elif format[pos] in "([": | |
172 | pos, level = pos+1, 1 |
|
172 | pos, level = pos+1, 1 | |
173 | while level: |
|
173 | while level: | |
174 | match, pos = matchorfail(format, pos) |
|
174 | match, pos = matchorfail(format, pos) | |
175 | tstart, tend = match.regs[3] |
|
175 | tstart, tend = match.regs[3] | |
176 | token = format[tstart:tend] |
|
176 | token = format[tstart:tend] | |
177 | if token[0] in "([": level = level+1 |
|
177 | if token[0] in "([": level = level+1 | |
178 | elif token[0] in ")]": level = level-1 |
|
178 | elif token[0] in ")]": level = level-1 | |
179 | else: break |
|
179 | else: break | |
180 | chunks.append((1, format[dollar+1:pos])) |
|
180 | chunks.append((1, format[dollar+1:pos])) | |
181 |
|
181 | |||
182 | else: |
|
182 | else: | |
183 | chunks.append((0, format[pos:dollar+1])) |
|
183 | chunks.append((0, format[pos:dollar+1])) | |
184 | pos = dollar + 1 + (nextchar == "$") |
|
184 | pos = dollar + 1 + (nextchar == "$") | |
185 |
|
185 | |||
186 | if pos < len(format): chunks.append((0, format[pos:])) |
|
186 | if pos < len(format): chunks.append((0, format[pos:])) | |
187 | self.chunks = chunks |
|
187 | self.chunks = chunks | |
188 |
|
188 | |||
189 | def __repr__(self): |
|
189 | def __repr__(self): | |
190 | return "<Itpl %s >" % repr(self.format) |
|
190 | return "<Itpl %s >" % repr(self.format) | |
191 |
|
191 | |||
192 | def _str(self,glob,loc): |
|
192 | def _str(self,glob,loc): | |
193 | """Evaluate to a string in the given globals/locals. |
|
193 | """Evaluate to a string in the given globals/locals. | |
194 |
|
194 | |||
195 | The final output is built by calling str(), but if this fails, the |
|
195 | The final output is built by calling str(), but if this fails, the | |
196 | result is encoded with the instance's codec and error handling policy, |
|
196 | result is encoded with the instance's codec and error handling policy, | |
197 | via a call to out.encode(self.codec,self.encoding_errors)""" |
|
197 | via a call to out.encode(self.codec,self.encoding_errors)""" | |
198 | result = [] |
|
198 | result = [] | |
199 | app = result.append |
|
199 | app = result.append | |
200 | for live, chunk in self.chunks: |
|
200 | for live, chunk in self.chunks: | |
201 | if live: app(str(eval(chunk,glob,loc))) |
|
201 | if live: | |
|
202 | val = eval(chunk,glob,loc) | |||
|
203 | try: | |||
|
204 | app(str(val)) | |||
|
205 | except UnicodeEncodeError: | |||
|
206 | app(unicode(val)) | |||
|
207 | ||||
202 | else: app(chunk) |
|
208 | else: app(chunk) | |
203 | out = ''.join(result) |
|
209 | out = ''.join(result) | |
204 | try: |
|
210 | try: | |
205 | return str(out) |
|
211 | return str(out) | |
206 | except UnicodeError: |
|
212 | except UnicodeError: | |
207 | return out.encode(self.codec,self.encoding_errors) |
|
213 | return out.encode(self.codec,self.encoding_errors) | |
208 |
|
214 | |||
209 | def __str__(self): |
|
215 | def __str__(self): | |
210 | """Evaluate and substitute the appropriate parts of the string.""" |
|
216 | """Evaluate and substitute the appropriate parts of the string.""" | |
211 |
|
217 | |||
212 | # We need to skip enough frames to get to the actual caller outside of |
|
218 | # We need to skip enough frames to get to the actual caller outside of | |
213 | # Itpl. |
|
219 | # Itpl. | |
214 | frame = sys._getframe(1) |
|
220 | frame = sys._getframe(1) | |
215 | while frame.f_globals["__name__"] == __name__: frame = frame.f_back |
|
221 | while frame.f_globals["__name__"] == __name__: frame = frame.f_back | |
216 | loc, glob = frame.f_locals, frame.f_globals |
|
222 | loc, glob = frame.f_locals, frame.f_globals | |
217 |
|
223 | |||
218 | return self._str(glob,loc) |
|
224 | return self._str(glob,loc) | |
219 |
|
225 | |||
220 | class ItplNS(Itpl): |
|
226 | class ItplNS(Itpl): | |
221 | """Class representing a string with interpolation abilities. |
|
227 | """Class representing a string with interpolation abilities. | |
222 |
|
228 | |||
223 | This inherits from Itpl, but at creation time a namespace is provided |
|
229 | This inherits from Itpl, but at creation time a namespace is provided | |
224 | where the evaluation will occur. The interpolation becomes a bit more |
|
230 | where the evaluation will occur. The interpolation becomes a bit more | |
225 | efficient, as no traceback needs to be extracte. It also allows the |
|
231 | efficient, as no traceback needs to be extracte. It also allows the | |
226 | caller to supply a different namespace for the interpolation to occur than |
|
232 | caller to supply a different namespace for the interpolation to occur than | |
227 | its own.""" |
|
233 | its own.""" | |
228 |
|
234 | |||
229 | def __init__(self, format,globals,locals=None, |
|
235 | def __init__(self, format,globals,locals=None, | |
230 | codec='utf_8',encoding_errors='backslashreplace'): |
|
236 | codec='utf_8',encoding_errors='backslashreplace'): | |
231 | """ItplNS(format,globals[,locals]) -> interpolating string instance. |
|
237 | """ItplNS(format,globals[,locals]) -> interpolating string instance. | |
232 |
|
238 | |||
233 | This constructor, besides a format string, takes a globals dictionary |
|
239 | This constructor, besides a format string, takes a globals dictionary | |
234 | and optionally a locals (which defaults to globals if not provided). |
|
240 | and optionally a locals (which defaults to globals if not provided). | |
235 |
|
241 | |||
236 | For further details, see the Itpl constructor.""" |
|
242 | For further details, see the Itpl constructor.""" | |
237 |
|
243 | |||
238 | if locals is None: |
|
244 | if locals is None: | |
239 | locals = globals |
|
245 | locals = globals | |
240 | self.globals = globals |
|
246 | self.globals = globals | |
241 | self.locals = locals |
|
247 | self.locals = locals | |
242 | Itpl.__init__(self,format,codec,encoding_errors) |
|
248 | Itpl.__init__(self,format,codec,encoding_errors) | |
243 |
|
249 | |||
244 | def __str__(self): |
|
250 | def __str__(self): | |
245 | """Evaluate and substitute the appropriate parts of the string.""" |
|
251 | """Evaluate and substitute the appropriate parts of the string.""" | |
246 | return self._str(self.globals,self.locals) |
|
252 | return self._str(self.globals,self.locals) | |
247 |
|
253 | |||
248 | def __repr__(self): |
|
254 | def __repr__(self): | |
249 | return "<ItplNS %s >" % repr(self.format) |
|
255 | return "<ItplNS %s >" % repr(self.format) | |
250 |
|
256 | |||
251 | # utilities for fast printing |
|
257 | # utilities for fast printing | |
252 | def itpl(text): return str(Itpl(text)) |
|
258 | def itpl(text): return str(Itpl(text)) | |
253 | def printpl(text): print itpl(text) |
|
259 | def printpl(text): print itpl(text) | |
254 | # versions with namespace |
|
260 | # versions with namespace | |
255 | def itplns(text,globals,locals=None): return str(ItplNS(text,globals,locals)) |
|
261 | def itplns(text,globals,locals=None): return str(ItplNS(text,globals,locals)) | |
256 | def printplns(text,globals,locals=None): print itplns(text,globals,locals) |
|
262 | def printplns(text,globals,locals=None): print itplns(text,globals,locals) | |
257 |
|
263 | |||
258 | class ItplFile: |
|
264 | class ItplFile: | |
259 | """A file object that filters each write() through an interpolator.""" |
|
265 | """A file object that filters each write() through an interpolator.""" | |
260 | def __init__(self, file): self.file = file |
|
266 | def __init__(self, file): self.file = file | |
261 | def __repr__(self): return "<interpolated " + repr(self.file) + ">" |
|
267 | def __repr__(self): return "<interpolated " + repr(self.file) + ">" | |
262 | def __getattr__(self, attr): return getattr(self.file, attr) |
|
268 | def __getattr__(self, attr): return getattr(self.file, attr) | |
263 | def write(self, text): self.file.write(str(Itpl(text))) |
|
269 | def write(self, text): self.file.write(str(Itpl(text))) | |
264 |
|
270 | |||
265 | def filter(file=sys.stdout): |
|
271 | def filter(file=sys.stdout): | |
266 | """Return an ItplFile that filters writes to the given file object. |
|
272 | """Return an ItplFile that filters writes to the given file object. | |
267 |
|
273 | |||
268 | 'file = filter(file)' replaces 'file' with a filtered object that |
|
274 | 'file = filter(file)' replaces 'file' with a filtered object that | |
269 | has a write() method. When called with no argument, this creates |
|
275 | has a write() method. When called with no argument, this creates | |
270 | a filter to sys.stdout.""" |
|
276 | a filter to sys.stdout.""" | |
271 | return ItplFile(file) |
|
277 | return ItplFile(file) | |
272 |
|
278 | |||
273 | def unfilter(ifile=None): |
|
279 | def unfilter(ifile=None): | |
274 | """Return the original file that corresponds to the given ItplFile. |
|
280 | """Return the original file that corresponds to the given ItplFile. | |
275 |
|
281 | |||
276 | 'file = unfilter(file)' undoes the effect of 'file = filter(file)'. |
|
282 | 'file = unfilter(file)' undoes the effect of 'file = filter(file)'. | |
277 | 'sys.stdout = unfilter()' undoes the effect of 'sys.stdout = filter()'.""" |
|
283 | 'sys.stdout = unfilter()' undoes the effect of 'sys.stdout = filter()'.""" | |
278 | return ifile and ifile.file or sys.stdout.file |
|
284 | return ifile and ifile.file or sys.stdout.file |
General Comments 0
You need to be logged in to leave comments.
Login now