def enhance_frame()

in bugbot/crash/socorro_util.py [0:0]


def enhance_frame(frame, vcs_mappings):
    """Add additional info to a stack frame

    This adds signature and source links from vcs_mappings.

    """
    # If this is a truncation frame, then we don't need to enhance it in any way
    if frame.get("truncated") is not None:
        return

    if frame.get("function"):
        # Remove spaces before all stars, ampersands, and commas
        function = re.sub(r" (?=[\*&,])", "", frame["function"])
        # Ensure a space after commas
        function = re.sub(r",(?! )", ", ", function)
        frame["function"] = function
        signature = function
    elif frame.get("file") and frame.get("line"):
        signature = "%s#%d" % (frame["file"], frame["line"])
    elif frame.get("module") and frame.get("module_offset"):
        signature = "%s@%s" % (
            frame["module"],
            strip_leading_zeros(frame["module_offset"]),
        )
    elif frame.get("unloaded_modules"):
        first_module = frame["unloaded_modules"][0]
        if first_module.get("offsets"):
            signature = "(unloaded %s@%s)" % (
                first_module.get("module") or "",
                strip_leading_zeros(first_module.get("offsets")[0]),
            )
        else:
            signature = "(unloaded %s)" % first_module
    else:
        signature = "@%s" % frame["offset"]

    frame["signature"] = signature
    if signature.startswith("(unloaded"):
        # If the signature is based on an unloaded module, leave the string as is
        frame["short_signature"] = signature
    else:
        # Remove arguments which are enclosed in parens
        frame["short_signature"] = re.sub(r"\(.*\)", "", signature)

    if frame.get("file"):
        vcsinfo = frame["file"].split(":")
        if len(vcsinfo) == 4:
            vcstype, root, vcs_source_file, revision = vcsinfo
            if "/" in root:
                # The root is something like 'hg.mozilla.org/mozilla-central'
                server, repo = root.split("/", 1)
            else:
                # E.g. 'gecko-generated-sources' or something without a '/'
                repo = server = root

            if (
                vcs_source_file.count("/") > 1
                and len(vcs_source_file.split("/")[0]) == 128
            ):
                # In this case, the 'vcs_source_file' will be something like
                # '{SHA-512 hex}/ipc/ipdl/PCompositorBridgeChild.cpp'
                # So drop the sha part for the sake of the 'file' because
                # we don't want to display a 128 character hex code in the
                # hyperlink text.
                vcs_source_file_display = "/".join(vcs_source_file.split("/")[1:])
            else:
                # Leave it as is if it's not unwieldy long.
                vcs_source_file_display = vcs_source_file

            if vcstype in vcs_mappings:
                if server in vcs_mappings[vcstype]:
                    link = vcs_mappings[vcstype][server]
                    frame["file"] = vcs_source_file_display
                    frame["source_link"] = link % {
                        "repo": repo,
                        "file": vcs_source_file,
                        "revision": revision,
                        "line": frame["line"],
                    }
            else:
                path_parts = vcs_source_file.split("/")
                frame["file"] = path_parts.pop()