Make a new function from a given template and update the signature
(self, src_templ, evaldict=None, addsource=False, **attrs)
| 170 | func.__dict__.update(kw) |
| 171 | |
| 172 | def make(self, src_templ, evaldict=None, addsource=False, **attrs): |
| 173 | "Make a new function from a given template and update the signature" |
| 174 | src = src_templ % vars(self) # expand name and signature |
| 175 | evaldict = evaldict or {} |
| 176 | mo = DEF.match(src) |
| 177 | if mo is None: |
| 178 | raise SyntaxError('not a valid function template\n%s' % src) |
| 179 | name = mo.group(1) # extract the function name |
| 180 | names = set([name] + [arg.strip(' *') for arg in |
| 181 | self.shortsignature.split(',')]) |
| 182 | for n in names: |
| 183 | if n in ('_func_', '_call_'): |
| 184 | raise NameError('%s is overridden in\n%s' % (n, src)) |
| 185 | |
| 186 | if not src.endswith('\n'): # add a newline for old Pythons |
| 187 | src += '\n' |
| 188 | |
| 189 | # Ensure each generated function has a unique filename for profilers |
| 190 | # (such as cProfile) that depend on the tuple of (<filename>, |
| 191 | # <definition line>, <function name>) being unique. |
| 192 | filename = '<decorator-gen-%d>' % (next(self._compile_count),) |
| 193 | try: |
| 194 | code = compile(src, filename, 'single') |
| 195 | exec(code, evaldict) |
| 196 | except: |
| 197 | print('Error in generated code:', file=sys.stderr) |
| 198 | print(src, file=sys.stderr) |
| 199 | raise |
| 200 | func = evaldict[name] |
| 201 | if addsource: |
| 202 | attrs['__source__'] = src |
| 203 | self.update(func, **attrs) |
| 204 | return func |
| 205 | |
| 206 | @classmethod |
| 207 | def create(cls, obj, body, evaldict, defaults=None, |