MCPcopy
hub / github.com/sqlalchemy/sqlalchemy / decorate

Function decorate

lib/sqlalchemy/util/langhelpers.py:266–344  ·  view source on GitHub ↗
(fn: _Fn)

Source from the content-addressed store, hash-verified

264 """A signature-matching decorator factory."""
265
266 def decorate(fn: _Fn) -> _Fn:
267 if not inspect.isfunction(fn) and not inspect.ismethod(fn):
268 raise Exception("not a decoratable function")
269
270 # Python 3.14 defer creating __annotations__ until its used.
271 # We do not want to create __annotations__ now.
272 annofunc = getattr(fn, "__annotate__", None)
273 if annofunc is not None:
274 fn.__annotate__ = None # type: ignore[union-attr]
275 try:
276 spec = compat.inspect_getfullargspec(fn)
277 finally:
278 fn.__annotate__ = annofunc # type: ignore[union-attr]
279 else:
280 spec = compat.inspect_getfullargspec(fn)
281
282 # Do not generate code for annotations.
283 # update_wrapper() copies the annotation from fn to decorated.
284 # We use dummy defaults for code generation to avoid having
285 # copy of large globals for compiling.
286 # We copy __defaults__ and __kwdefaults__ from fn to decorated.
287 empty_defaults = (None,) * len(spec.defaults or ())
288 empty_kwdefaults = dict.fromkeys(spec.kwonlydefaults or ())
289 spec = spec._replace(
290 annotations={},
291 defaults=empty_defaults,
292 kwonlydefaults=empty_kwdefaults,
293 )
294
295 names = (
296 tuple(cast("Tuple[str, ...]", spec[0]))
297 + cast("Tuple[str, ...]", spec[1:3])
298 + (fn.__name__,)
299 )
300 targ_name, fn_name = _unique_symbols(names, "target", "fn")
301
302 metadata: Dict[str, Optional[str]] = dict(target=targ_name, fn=fn_name)
303 metadata.update(format_argspec_plus(spec, grouped=False))
304 metadata["name"] = fn.__name__
305
306 if inspect.iscoroutinefunction(fn):
307 metadata["prefix"] = "async "
308 metadata["target_prefix"] = "await "
309 else:
310 metadata["prefix"] = ""
311 metadata["target_prefix"] = ""
312
313 # look for __ positional arguments. This is a convention in
314 # SQLAlchemy that arguments should be passed positionally
315 # rather than as keyword
316 # arguments. note that apply_pos doesn't currently work in all cases
317 # such as when a kw-only indicator "*" is present, which is why
318 # we limit the use of this to just that case we can detect. As we add
319 # more kinds of methods that use @decorator, things may have to
320 # be further improved in this area
321 if "__" in repr(spec[0]):
322 code = """\
323%(prefix)sdef %(name)s%(grouped_args)s:

Callers

nothing calls this directly

Calls 7

_unique_symbolsFunction · 0.85
format_argspec_plusFunction · 0.85
inject_param_textFunction · 0.85
_replaceMethod · 0.80
castFunction · 0.70
_exec_code_in_envFunction · 0.70
updateMethod · 0.45

Tested by

no test coverage detected