1
2 """
3 Application class that implements pyFoamFromTemplate
4 """
5
6 import sys
7
8 from optparse import OptionGroup
9
10 from .PyFoamApplication import PyFoamApplication
11
12 from PyFoam.Basics.TemplateFile import TemplateFile,TemplateFileOldFormat
13 from PyFoam.RunDictionary.ParsedParameterFile import ParsedParameterFile
14
15 from .CommonPickledDataInput import CommonPickledDataInput
16 from .CommonTemplateFormat import CommonTemplateFormat
17
18 from PyFoam.ThirdParty.six import print_
19
20 -class FromTemplate(PyFoamApplication,
21 CommonPickledDataInput,
22 CommonTemplateFormat):
24 description="""\
25 Generates a file from a template file. Usually the name of the
26 template file is the name of the file with the extension '.template'
27 (unless specified otherwise). The file is generated by replacing
28 everything in the template file that is enclosed by $ $ with
29 calculated expression. values are given in a Python-dictionary. Lines
30 in the template file that start with $$ are used as definitons for
31 intermediate expressions.
32
33 This format is used if the two arguments are used. If the template
34 file and the data is specified via options then a more advanced
35 template format that allows branches and loops is used via the
36 template-engine pyratemp (see
37 http://www.simple-is-better.org/template/pyratemp.html). If data is
38 read from a pickled-input then it looks for the keys "template" and "values" and
39 uses these.
40
41 In the new format expressions are delimited by |- at the start and -|
42 at the end. These defaults can be changed
43 """
44
45 PyFoamApplication.__init__(self,
46 args=args,
47 description=description,
48 usage="%prog [options] (<file> <vals>|)",
49 nr=0,
50 changeVersion=False,
51 interspersed=True,
52 exactNr=False)
53
55 CommonPickledDataInput.addOptions(self)
56
57 inputs=OptionGroup(self.parser,
58 "Inputs",
59 "Inputs for the templating process")
60 self.parser.add_option_group(inputs)
61
62 inputs.add_option("--template-file",
63 action="store",
64 default=None,
65 dest="template",
66 help="Name of the template file. Also overwrites the standard for the old format (<filename>.template). If this is set to 'stdin' then the template is read from the standard-input to allow using the pipe into it.")
67 inputs.add_option("--values-string",
68 action="store",
69 default=None,
70 dest="values",
71 help="String with the values that are to be inserted into the template as a dictionaty in Python-format. If specified this is the first choice")
72 inputs.add_option("--values-dictionary",
73 action="store",
74 default=None,
75 dest="valuesDict",
76 help="Name of a dictionary-file in OpenFOAM-format. If this is unspecified too then values are taken from the pickled-input")
77
78 outputs=OptionGroup(self.parser,
79 "Outputs",
80 "Outputs of the templating process")
81 self.parser.add_option_group(outputs)
82 outputs.add_option("--stdout",
83 action="store_true",
84 dest="stdout",
85 default=False,
86 help="Doesn't write to the file, but outputs the result on stdout")
87 outputs.add_option("--output-file",
88 action="store",
89 default=None,
90 dest="outputFile",
91 help="File to which the output will be written. Only for the new format")
92
93 CommonTemplateFormat.addOptions(self)
94
95 behaviour=OptionGroup(self.parser,
96 "Behaviour",
97 "The behaviour of the parser")
98 self.parser.add_option_group(behaviour)
99 behaviour.add_option("--tolerant-expression-evaluation",
100 action="store_true",
101 default=False,
102 dest="tolerantRender",
103 help="Instead of failing when encountering a problem during an evaluation a string with the error message is inserted into the output")
104 behaviour.add_option("--allow-exec-instead-of-assignment",
105 action="store_true",
106 default=False,
107 dest="allowExec",
108 help="Allows exectution of non-assignments in $$-lines. This is potentially unsafe as it allows 'import' and calling of external programs")
109
111 if self.opts.template=="stdin" and self.opts.pickledFileRead=="stdin":
112 self.error("Can't simultanously read pickled data and the tempalte from the standard input")
113
114 content=None
115 if self.opts.template=="stdin":
116 content=sys.stdin.read()
117 data=None
118 if self.opts.pickledFileRead:
119 data=self.readPickledData()
120 fName=None
121
122 if len(self.parser.getArgs())==2:
123 if self.opts.pickledFileRead:
124 self.error("old-format mode does not work with pickled input")
125 if self.opts.outputFile:
126 self.error("--output-file is not valid for the old format")
127
128 fName=self.parser.getArgs()[0]
129 vals=eval(self.parser.getArgs()[1])
130 if type(vals)==str:
131
132 vals=eval(vals)
133
134 if self.opts.template==None:
135 template=fName+".template"
136 else:
137 template=self.opts.template
138
139 if content:
140 t=TemplateFileOldFormat(content=content)
141 else:
142 t=TemplateFileOldFormat(name=template)
143 elif len(self.parser.getArgs())==0:
144 if self.opts.values:
145 vals=eval(self.opts.values)
146 elif self.opts.valuesDict:
147 vals=ParsedParameterFile(self.opts.valuesDict,
148 noHeader=True,
149 doMacroExpansion=True).getValueDict()
150 elif data:
151 vals=data["values"]
152 else:
153 self.error("Either specify the values with --values-string or --values-dictionary or in the pickled input data")
154
155 if content:
156 t=TemplateFile(content=content,
157 tolerantRender=self.opts.tolerantRender,
158 allowExec=self.opts.allowExec,
159 expressionDelimiter=self.opts.expressionDelimiter,
160 assignmentLineStart=self.opts.assignmentLineStart)
161 elif data:
162 t=TemplateFile(content=data["template"],
163 tolerantRender=self.opts.tolerantRender,
164 allowExec=self.opts.allowExec,
165 expressionDelimiter=self.opts.expressionDelimiter,
166 assignmentLineStart=self.opts.assignmentLineStart)
167 elif self.opts.template:
168 t=TemplateFile(name=self.opts.template,
169 tolerantRender=self.opts.tolerantRender,
170 allowExec=self.opts.allowExec,
171 expressionDelimiter=self.opts.expressionDelimiter,
172 assignmentLineStart=self.opts.assignmentLineStart)
173 else:
174 self.error("Template unspecified")
175
176 if self.opts.outputFile:
177 fName=self.opts.outputFile
178 else:
179 self.error("Either specify 2 arguments (file and values) for old format or no arguments for the new format")
180
181 if self.opts.stdout:
182 print_(t.getString(vals))
183 elif fName:
184 try:
185 t.writeToFile(fName,vals)
186 except (NameError,SyntaxError):
187 e = sys.exc_info()[1]
188 print_("While processing file",fName)
189 raise e
190 else:
191 self.error("No destination for the output specified")
192
193
194