1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 """Module containing the user function data singleton which stores all of the data."""
25
26
27 from re import search
28 from relax_errors import RelaxError
29 from string import split
30
31
32 from relax_errors import RelaxError
33 from user_functions.objects import Class_container, Table, Uf_container
34
35
37 """The user function data singleton class."""
38
39
40 _instance = None
41
58
59
82
83
85 """Add the user function to the object.
86
87 @param name: The name of the user function.
88 @type name: str
89 @return: The user function data object.
90 @rtype: user_functions.objects.Uf_container instance
91 """
92
93
94 if name in self._uf_names:
95 raise RelaxError("The user function %s has already been set up." % name)
96
97
98 if search('\.', name):
99
100 class_name, fn_name = split(name, '.')
101
102
103 if class_name not in self._class_names:
104 raise RelaxError("The user function class '%s' has not been set up yet." % class_name)
105
106
107 self._uf_names.append(name)
108 self._uf[name] = Uf_container()
109
110
111 self._uf_names.sort()
112
113
114 return self._uf[name]
115
116
118 """Iterator method for looping over the user function classes.
119
120 @return: The class name and data container.
121 @rtype: tuple of str and Class_container instance
122 """
123
124
125 for i in range(len(self._class_names)):
126 yield self._class_names[i], self._classes[self._class_names[i]]
127
128
130 """Return the user function class data object corresponding to the given name.
131
132 @param name: The name of the user function class.
133 @type name: str
134 @return: The class data container.
135 @rtype: Class_container instance
136 """
137
138
139 return self._classes[name]
140
141
143 """Return the user function data object corresponding to the given name.
144
145 @param name: The name of the user function.
146 @type name: str
147 @return: The user function data container.
148 @rtype: Uf_container instance
149 """
150
151
152 return self._uf[name]
153
154
156 """Iterator method for looping over the user functions.
157
158 @keyword uf_class: If given, restrict the iterator to a user function class.
159 @type uf_class: str or None
160 @return: The user function name and data container.
161 @rtype: tuple of str and Uf_container instance
162 """
163
164
165 for i in range(len(self._uf_names)):
166
167 if uf_class and not search("^%s\." % uf_class, self._uf_names[i]):
168 continue
169
170 yield self._uf_names[i], self._uf[self._uf_names[i]]
171
172
174 """Validate that all of the user functions have been correctly set up."""
175
176
177 for name, uf in self.uf_loop():
178
179 if uf.title == None:
180 raise RelaxError("The title of the %s user function has not been specified." % name)
181
182
183 if uf.backend == None:
184 raise RelaxError("The back end of the %s user function has not been specified." % name)
185
186
187
189 """The data singleton holding all of the description tables."""
190
191
192 _instance = None
193
194 - def __new__(self, *args, **kargs):
195 """Replacement method for implementing the singleton design pattern."""
196
197
198 if self._instance is None:
199
200 self._instance = object.__new__(self, *args, **kargs)
201
202
203 self._tables = {}
204 self._labels = []
205
206
207 return self._instance
208
209
210 - def add_table(self, label=None, caption=None, caption_short=None, spacing=True, longtable=False):
211 """Add a new table to the object.
212
213 @keyword label: The unique label of the table. This is used to identify tables, and is also used in the table referencing in the LaTeX compilation of the user manual.
214 @type label: str
215 @keyword caption: The caption for the table.
216 @type caption: str
217 @keyword caption_short: The optional short caption for the table, used in the LaTeX user manual list of tables section for example.
218 @type caption_short: str
219 @keyword spacing: A flag which if True will cause empty rows to be placed between elements.
220 @type spacing: bool
221 @keyword longtable: A special LaTeX flag which if True will cause the longtables package to be used to spread a table across multiple pages. This should only be used for tables that do not fit on a single page.
222 @type longtable: bool
223 @return: The table object.
224 @rtype: user_functions.objects.Table instance
225 """
226
227
228 if label == None:
229 raise RelaxError("The table label must be supplied.")
230
231
232 if label in self._labels:
233 raise RelaxError("The table with label '%s' has already been set up." % label)
234
235
236 self._labels.append(label)
237 self._tables[label] = Table(label=label, caption=caption, caption_short=caption_short, spacing=spacing, longtable=longtable)
238
239
240 return self._tables[label]
241
242
244 """Return the table matching the given label.
245
246 @param label: The unique label of the table.
247 @type label: str
248 @return: The table data container.
249 @rtype: user_functions.objects.Table instance
250 """
251
252
253 if label not in self._tables.keys():
254 raise RelaxError("The table with label '%s' does not exist." % label)
255
256
257 return self._tables[label]
258