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