Package osh :: Module function
[frames] | no frames]

Source Code for Module osh.function

 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  """Encapsulates functions used in osh commands such as C{f} and C{select}. 
19   
20  osh function syntax:: 
21   
22      [[lambda] ARGS:] EXPRESSION 
23   
24  C{ARGS}: Comma-separated list of function arguments, optionally preceded by keyword 
25  C{lambda}. C{ARGS} may be omitted only for a function with no arguments. 
26   
27  C{EXPRESSION}: A Python expression written in terms of the function arguments. 
28   
29  Example:: 
30   
31      x: max(x, 10) 
32  """ 
33   
34  import copy 
35  import sys 
36  import types 
37   
38  import core 
39   
40  _LAMBDA = 'lambda ' 
41  _LAMBDA_COLON = 'lambda:' 
42   
43  # "Private" name (with leading underscore) so that epydoc doesn't document the class 
44 -class _Function(object):
45 """Represents a function for use by osh commands with function arguments, 46 e.g., select. 47 """ 48 49 _function = None 50 _function_id = None 51
52 - def __init__(self, function_spec, namespace = core.__dict__):
53 """Creates a Function. 54 - function_spec: String specification of a function. Uses lambda notation, 55 but the 'lambda' keyword is optional. 56 - namespace: The default is reasonable; there's been no need to 57 override it so far. 58 """ 59 if type(function_spec) in (types.FunctionType, types.BuiltinFunctionType): 60 self._function = function_spec 61 else: 62 lambda_expression = self.parse(function_spec.strip()) 63 # Create a namespace including symbols defined by the current osh invocation. 64 namespace = copy.copy(namespace) 65 namespace.update(core.namespace()) 66 self._function = eval(lambda_expression, namespace)
67
68 - def __call__(self, *args): # args = None):
69 return self._function(*args)
70
71 - def parse(self, function_spec):
72 # If the function spec starts with a lambda, then just use it as is. 73 # Otherwise, it could be: 74 # - function with arg list, e.g. "x, y: x + y" 75 # - zero-arg list with colon, e.g. ": processes()" 76 # - zero-arg list without colon, e.g. "processes()" 77 # Try prepending "lambda:" and "lambda" until there's 78 # no syntax error. Crude but effective. 79 if function_spec.startswith(_LAMBDA) or function_spec.startswith(_LAMBDA_COLON): 80 # ok as is 81 pass 82 else: 83 fixed_function_spec = '%s: %s' % (_LAMBDA, function_spec) 84 try: 85 eval(fixed_function_spec) 86 function_spec = fixed_function_spec 87 except: 88 fixed_function_spec = '%s %s' % (_LAMBDA, function_spec) 89 try: 90 eval(fixed_function_spec) 91 function_spec = fixed_function_spec 92 except: 93 raise Exception('Illegal function spec: %s' % function_spec) 94 return function_spec
95