def reqrep(wrapped: t.Callable,
           meth: t.Callable,
           channel: str = "shell") -> t.Callable:
    wrapped = wrapped(meth, channel)
    if not meth.__doc__:
        # python -OO removes docstrings,
        # so don't bother building the wrapped docstring
        return wrapped

    basedoc, _ = meth.__doc__.split("Returns\n", 1)
    parts = [basedoc.strip()]
    if "Parameters" not in basedoc:
        parts.append("""
        Parameters
        ----------
        """)
    parts.append("""
        reply: bool (default: False)
            Whether to wait for and return reply
        timeout: float or None (default: None)
            Timeout to use when waiting for a reply

        Returns
        -------
        msg_id: str
            The msg_id of the request sent, if reply=False (default)
        reply: dict
            The reply message for this request, if reply=True
    """)
    wrapped.__doc__ = "\n".join(parts)
    return wrapped
Exemple #2
0
 def __call__(self, func:typing.Callable):
   string = func.__doc__
   pos = string.index(cn.EXPAND)
   if pos < 0:
       return func
   # Find the indentation for the line
   indent = pos
   for idx in range(1, pos):
     if string[pos - idx] != " ":
       indent = idx - 1
       break
   indent_str = self._getIndentStr(indent)
   # Construct the expansion
   if len(self.header) > 0:
     expansion = self._indentText(self.header, indent_str)
   else:
     expansion = ""
   keywords = list(self.keywords)
   keywords.sort()
   for idx, keyword in enumerate(keywords):
     self.kwarg_dct[keyword].setIndent(self._indent)
     expansion += str(self.kwarg_dct[keyword])
   expansion += self._indentText(self.trailer, indent_str)
   # Replace the docstring
   replace_str = "%s%s"  % (indent_str, cn.EXPAND)
   func.__doc__ = string.replace(replace_str, expansion)
   return func
Exemple #3
0
 def func(f: t.Callable):
     name = f.__name__
     #args = f.__arguments__
     annotations = f.__annotations__
     module = f.__module__
     doc = f.__doc__
     qname = f.__qualname__
     for opt in sorted(option.options):
         f = cmd_option(opt, name_prefix)(f)
     f.__name__ = name[0:-2] if name.endswith("_") else name
     f.__qualname__ = qname[0:-2] if qname.endswith("_") else qname
     #f.__args__ = args
     f.__annotations__ = annotations
     f.__module__ = module
     f.__doc__ = doc
     return f
Exemple #4
0
 def func(f: t.Callable):
     name = f.__name__
     #args = f.__arguments__
     annotations = f.__annotations__
     module = f.__module__
     doc = f.__doc__
     qname = f.__qualname__
     for i, opt in enumerate(sorted(option.options)):
         validate = None
         if isinstance(opt, CmdOption) and i == 0:
             validate = True
         f = cmd_option(opt, name_prefix, validate=validate)(f)
     f.__name__ = name[0:-2] if name.endswith("_") else name
     f.__qualname__ = qname[0:-2] if qname.endswith("_") else qname
     #f.__args__ = args
     f.__annotations__ = annotations
     f.__module__ = module
     f.__doc__ = doc
     return f
Exemple #5
0
def update_wrapper(
    wrapper: T.Callable,
    wrapped: T.Callable,
    signature: T.Union[_FullerSig, None, bool] = True,  # not in functools
    docstring: T.Union[str, bool] = True,  # not in functools
    assigned: T.Sequence[str] = WRAPPER_ASSIGNMENTS,
    updated: T.Sequence[str] = WRAPPER_UPDATES,
    # docstring options
    _doc_fmt: T.Optional[dict] = None,  # not in functools
    _doc_style: T.Union[str, T.Callable, None] = None,
):
    """Update a wrapper function to look like the wrapped function.

    Parameters
    ----------
    wrapper : Callable
        the function to be updated
    wrapped : Callable
       the original function
    signature : Signature or None or bool, optional
        signature to impose on `wrapper`.
        None and False default to `wrapped`'s signature.
        True merges `wrapper` and `wrapped` kwdefaults & annotations
    docstring : str or bool, optional
        docstring to impose on `wrapper`.
        False ignores `wrapper`'s docstring, using only `wrapped`'s docstring.
        None (defualt) merges the `wrapper` and `wrapped` docstring
    assigned : tuple, optional
       tuple naming the attributes assigned directly
       from the wrapped function to the wrapper function (defaults to
       ``functools.WRAPPER_ASSIGNMENTS``)
    updated : tuple, optional
       is a tuple naming the attributes of the wrapper that
       are updated with the corresponding attribute from the wrapped
       function (defaults to ``functools.WRAPPER_UPDATES``)
    _doc_fmt : dict, optional
        dictionary to format wrapper docstring
    _doc_style: str or Callable, optional
        the style of the docstring
        if None (default), appends `wrapper` docstring
        if str or Callable, merges the docstring

    Returns
    -------
    wrapper : Callable
        `wrapper` function updated by the `wrapped` function's attributes and
        also the provided `signature` and `docstring`.

    Raises
    ------
    ValueError
        if docstring is True

    """
    # ---------------------------------------
    # preamble

    signature, _update_sig = __parse_sig_for_update_wrapper(signature, wrapped)

    # need to get wrapper properties now
    wrapper_sig = _FullerSig.from_callable(wrapper)

    wrapper_doc = _nspct.getdoc(wrapper) or ""
    wrapper_doc = "\n".join(wrapper_doc.split("\n")[1:])  # drop title

    if _doc_fmt is None:
        _doc_fmt = {}

    # ---------------------------------------
    # update wrapper (same as functools.update_wrapper)

    for attr in assigned:
        try:
            value = getattr(wrapped, attr)
        except AttributeError:
            pass
        else:
            setattr(wrapper, attr, value)

    for attr in updated:  # update whole dictionary
        getattr(wrapper, attr).update(getattr(wrapped, attr, {}))

    # ---------------------------------------

    # deal with signature
    if signature in (None, False):
        pass

    elif _update_sig:  # merge wrapped and wrapper signature

        signature = __update_wrapper_update_sig(
            signature, wrapper_sig, _doc_fmt
        )

        for attr in SIGNATURE_ASSIGNMENTS:
            value = getattr(signature, attr)
            setattr(wrapper, attr, value)

        wrapper.__signature__ = signature.signature

    else:  # a signature object
        for attr in SIGNATURE_ASSIGNMENTS:
            _value = getattr(signature, attr)
            setattr(wrapper, attr, _value)

        # for docstring
        for param in wrapper_sig.parameters.values():
            # can only merge keyword-only
            if param.kind == _nspct.KEYWORD_ONLY:
                _doc_fmt[param.name] = param.default

        wrapper.__signature__ = signature.signature

    # ---------------------------------------
    # docstring

    if _doc_fmt:  # (not empty dict)
        wrapper_doc = _FormatTemplate(wrapper_doc).safe_substitute(**_doc_fmt)

    wrapper.__doc__ = __update_wrapper_docstring(
        wrapped,
        docstring=docstring,
        wrapper_doc=wrapper_doc,
        _doc_style=_doc_style,
    )

    # Issue #17482: set __wrapped__ last so we don't inadvertently copy it
    # from the wrapped function when updating __dict__
    wrapper.__wrapped__ = wrapped
    # Return the wrapper so this can be used as a decorator via partial()
    return wrapper