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 from .CommonTemplateBehaviour import CommonTemplateBehaviour
18
19 from PyFoam.ThirdParty.six import print_,iteritems
20
21 from os import path
22
23 -class FromTemplate(PyFoamApplication,
24 CommonPickledDataInput,
25 CommonTemplateBehaviour,
26 CommonTemplateFormat):
27 - def __init__(self,
28 args=None,
29 parameters={},
30 **kwargs):
31 description="""\
32 Generates a file from a template file. Usually the name of the
33 template file is the name of the file with the extension '.template'
34 (unless specified otherwise). The file is generated by replacing
35 everything in the template file that is enclosed by $ $ with
36 calculated expression. values are given in a Python-dictionary. Lines
37 in the template file that start with $$ are used as definitons for
38 intermediate expressions.
39
40 This format is used if the two arguments are used. If the template
41 file and the data is specified via options then a more advanced
42 template format that allows branches and loops is used via the
43 template-engine pyratemp (see
44 http://www.simple-is-better.org/template/pyratemp.html). If data is
45 read from a pickled-input then it looks for the keys "template" and "values" and
46 uses these.
47
48 In the new format expressions are delimited by |- at the start and -|
49 at the end. These defaults can be changed
50
51 @param parameters: Dictionary with parameters (only usable
52 when called from a script)
53 """
54
55 self.parameters=parameters.copy()
56
57 PyFoamApplication.__init__(self,
58 args=args,
59 description=description,
60 usage="%prog [options] (<file> <vals>|)",
61 nr=0,
62 changeVersion=False,
63 interspersed=True,
64 exactNr=False,
65 **kwargs)
66
68 CommonPickledDataInput.addOptions(self)
69
70 inputs=OptionGroup(self.parser,
71 "Inputs",
72 "Inputs for the templating process")
73 self.parser.add_option_group(inputs)
74
75 inputs.add_option("--template-file",
76 action="store",
77 default=None,
78 dest="template",
79 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.")
80 inputs.add_option("--values-string",
81 action="store",
82 default=None,
83 dest="values",
84 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")
85 inputs.add_option("--values-dictionary",
86 action="store",
87 default=None,
88 dest="valuesDict",
89 help="Name of a dictionary-file in OpenFOAM-format. If this is unspecified too then values are taken from the pickled-input")
90 inputs.add_option("--no-defaults-file",
91 action="store_false",
92 default=True,
93 dest="useDefaults",
94 help="If a file with the same name as the template file but the extension '.defaults' is found then it is loaded before the other values are read. This option switches this off")
95
96 outputs=OptionGroup(self.parser,
97 "Outputs",
98 "Outputs of the templating process")
99 self.parser.add_option_group(outputs)
100 outputs.add_option("--stdout",
101 action="store_true",
102 dest="stdout",
103 default=False,
104 help="Doesn't write to the file, but outputs the result on stdout")
105 outputs.add_option("--dump-used-values",
106 action="store_true",
107 dest="dumpUsed",
108 default=False,
109 help="Print the used parameters")
110 outputs.add_option("--output-file",
111 action="store",
112 default=None,
113 dest="outputFile",
114 help="File to which the output will be written. Only for the new format")
115
116 CommonTemplateFormat.addOptions(self)
117
118 CommonTemplateBehaviour.addOptions(self)
119
121 if self.opts.template=="stdin" and self.opts.pickledFileRead=="stdin":
122 self.error("Can't simultanously read pickled data and the tempalte from the standard input")
123
124 content=None
125 if self.opts.template=="stdin":
126 content=sys.stdin.read()
127 data=None
128 if self.opts.pickledFileRead:
129 data=self.readPickledData()
130 fName=None
131
132 if len(self.parser.getArgs())==2:
133 if self.opts.pickledFileRead:
134 self.error("old-format mode does not work with pickled input")
135 if self.opts.outputFile:
136 self.error("--output-file is not valid for the old format")
137
138 fName=self.parser.getArgs()[0]
139 vals=eval(self.parser.getArgs()[1])
140 if type(vals)==str:
141
142 vals=eval(vals)
143
144 if self.opts.template==None:
145 template=fName+".template"
146 else:
147 template=self.opts.template
148
149 if content:
150 t=TemplateFileOldFormat(content=content)
151 else:
152 t=TemplateFileOldFormat(name=template)
153 elif len(self.parser.getArgs())==0:
154 if self.opts.template==None and self.opts.outputFile!=None and self.opts.outputFile!="stdin":
155 self.opts.template=self.opts.outputFile+".template"
156 self.warning("Automatically setting template to",self.opts.template)
157 vals={}
158 if self.opts.useDefaults and self.opts.template!=None and self.opts.template!="stdin":
159 name,ext=path.splitext(self.opts.template)
160 defaultName=name+".defaults"
161 if path.exists(defaultName):
162 self.warning("Reading default values from",defaultName)
163 vals=ParsedParameterFile(defaultName,
164 noHeader=True,
165 doMacroExpansion=True).getValueDict()
166
167 vals.update(self.parameters)
168
169 if self.opts.values:
170 vals.update(eval(self.opts.values))
171 elif self.opts.valuesDict:
172 vals.update(ParsedParameterFile(self.opts.valuesDict,
173 noHeader=True,
174 doMacroExpansion=True).getValueDict())
175 elif data:
176 vals.update(data["values"])
177 elif len(self.parameters)==0:
178 self.error("Either specify the values with --values-string or --values-dictionary or in the pickled input data")
179
180 if self.opts.dumpUsed:
181 maxLen=max([len(k) for k in vals.keys()])
182 formatString=" %%%ds | %%s" % maxLen
183 print_("Used values")
184 print_(formatString % ("Name","Value"))
185 print_("-"*(maxLen+30))
186 for k,v in iteritems(vals):
187 print_(formatString % (k,v))
188
189 if self.opts.outputFile:
190 assignmentDebug=self.pickAssignmentDebug(self.opts.outputFile)
191 else:
192 assignmentDebug=None
193
194 if content:
195 t=TemplateFile(content=content,
196 tolerantRender=self.opts.tolerantRender,
197 allowExec=self.opts.allowExec,
198 expressionDelimiter=self.opts.expressionDelimiter,
199 assignmentDebug=assignmentDebug,
200 assignmentLineStart=self.opts.assignmentLineStart)
201 elif data:
202 t=TemplateFile(content=data["template"],
203 tolerantRender=self.opts.tolerantRender,
204 allowExec=self.opts.allowExec,
205 expressionDelimiter=self.opts.expressionDelimiter,
206 assignmentDebug=assignmentDebug,
207 assignmentLineStart=self.opts.assignmentLineStart)
208 elif self.opts.template:
209 t=TemplateFile(name=self.opts.template,
210 tolerantRender=self.opts.tolerantRender,
211 allowExec=self.opts.allowExec,
212 expressionDelimiter=self.opts.expressionDelimiter,
213 assignmentDebug=assignmentDebug,
214 assignmentLineStart=self.opts.assignmentLineStart)
215 else:
216 self.error("Template unspecified")
217
218 if self.opts.outputFile:
219 fName=self.opts.outputFile
220 else:
221 self.error("Either specify 2 arguments (file and values) for old format or no arguments for the new format")
222
223 if self.opts.stdout:
224 print_(t.getString(vals))
225 elif fName:
226 try:
227 t.writeToFile(fName,vals)
228 except (NameError,SyntaxError):
229 e = sys.exc_info()[1]
230 print_("While processing file",fName)
231 raise e
232 else:
233 self.error("No destination for the output specified")
234
235
236