Parse docstring into a dict

    :rtype: data.FDocstring
4019
def _doc_parse(doc, module=None, qualname=None):
    

    # Build the rex
    known_tags = {
        'param': 'arg',
        'type': 'arg-type',
        'return': 'ret',
        'returns': 'ret',
        'rtype': 'ret-type',
        'exception': 'exc',
        'except': 'exc',
        'raise': 'exc',
        'raises': 'exc',
    }
    tag_rex = re.compile(r'^\s*:(' + '|'.join(map(re.escape, known_tags)) + r')\s*(\S+)?\s*:', re.MULTILINE)

    # Match tags
    collect_args = {}
    collect_ret = {}
    doc_args = []
    doc_exc = []
    for m in reversed(list(tag_rex.finditer(doc))):
        # Fetch data
        tag, arg = m.groups()
        tag = known_tags[tag]  # Normalized tag name

        # Fetch docstring part
        value = doc[m.end():].strip()  # Copy text after the tag
        doc = doc[:m.start()].strip()  # truncate the string

        # Handle tag: collect data
        if tag == 'exc':
            doc_exc.append(data.ExceptionDoc(arg, value))
        elif tag in ('ret', 'ret-type'):
            # Collect fields 1 by 1
            collect_ret[{'ret': 'doc', 'ret-type': 'type'}[tag]] = value
        elif tag in ('arg', 'arg-type'):
            # Init new collection
            if arg not in collect_args:
                doc_args.append(arg)  # add name for now, then map() replace with classes
                collect_args[arg] = {}
            # Collect fields 1 by 1
            collect_args[arg][{'arg': 'doc', 'arg-type': 'type'}[tag]] = value
        else:
            raise AssertionError('Unknown tag type: {}'.format(tag))

    # Merge collected data
    doc_ret = data.ValueDoc(**collect_ret) if collect_ret else None
    doc_args = map(lambda name: data.ArgumentDoc(name=name, **collect_args[name]), collect_args)

    # Finish
    return data.FDocstring(module=module, qualname=qualname, doc=doc, args=doc_args, exc=doc_exc, ret=doc_ret)
442773
def load_operations_from_docstring(docstring):
    
    doc_data = load_yaml_from_docstring(docstring)
    return {
        key: val
        for key, val in iteritems(doc_data)
        if key in PATH_KEYS or key.startswith("x-")
    }
737830
function makeDocString(obj) {
        var docStr = obj
        if (Array.isArray(docStr)) {
            docStr = docStr.join('\n');
        }
        return docStr;
    }
30321
def extract_docstring_summary(docstring):
    
    summary_lines = []
    for line in docstring:
        if line == '':
            break
        else:
            summary_lines.append(line)
    return ' '.join(summary_lines)
1037562
def _parse_docstring(fh):
    """"""
    find_fades = re.compile(r'\b(fades)\b:').search

    for line in fh:
        if line.startswith("'"):
            quote = "'"
            break
        if line.startswith('"'):
            quote = '"'
            break
    else:
        return {}

    if line[1] == quote:
        # comment start with triple quotes
        endquote = quote * 3
    else:
        endquote = quote

    if endquote in line[len(endquote):]:
        docstring_lines = [line[:line.index(endquote)]]
    else:
        docstring_lines = [line]
        for line in fh:
            if endquote in line:
                docstring_lines.append(line[:line.index(endquote)])
                break
            docstring_lines.append(line)

    docstring_lines = iter(docstring_lines)
    for doc_line in docstring_lines:
        if find_fades(doc_line):
            break
    else:
        return {}

    return _parse_requirement(list(docstring_lines))
438186
def parse(fname):
    

    blocks = list()
    with io.open(fname, "r", encoding="utf-8") as f:
        in_block = False
        current_block = None
        current_header = ""

        for line in f:

            # Doctests are within a quadruple hashtag header.
            if line.startswith("#### "):
                current_header = line.rstrip()

            # The actuat test is within a fenced block.
            if line.startswith("```"):
                in_block = False

            if in_block:
                current_block.append(line)

            if line.startswith("```python"):
                in_block = True
                current_block = list()
                current_block.append(current_header)
                blocks.append(current_block)

    tests = list()
    for block in blocks:
        header = (
            block[0].strip("# ")  # Remove Markdown
                    .rstrip()     # Remove newline
                    .lower()      # PEP08
        )

        # Remove unsupported characters
        header = re.sub(r"\W", "_", header)

        # Adding "untested" anywhere in the first line of
        # the doctest excludes it from the test.
        if "untested" in block[1].lower():
            continue

        data = re.sub(" ", "", block[1])  # Remove spaces
        data = (
            data.strip("#")
                .rstrip()     # Remove newline
                .split(",")
        )

        binding, doctest_version = (data + [None])[:2]

        # Run tests on both Python 2 and 3, unless explicitly stated
        if doctest_version is not None:
            if doctest_version not in ("Python2", "Python3"):
                raise SyntaxError(
                    "Invalid Python version:\n%s\n"
                    "Python version must follow binding, e.g.\n"
                    "# PyQt5, Python3" % doctest_version)

            active_version = "Python%i" % sys.version_info[0]
            if doctest_version != active_version:
                continue

        tests.append({
            "header": header,
            "binding": binding,
            "body": block[2:]
        })

    return tests
642623
def parse_docstring(entity):
    
    doc = inspect.getdoc(entity)
    if not doc:
        return None, None
    doc = doc.splitlines(keepends=True)
    if not doc[0].strip():
        doc.pop(0)
    title = (doc and doc.pop(0).strip()) or None
    if doc and not doc[0].strip():
        doc.pop(0)
    desc = ''.join(doc).rstrip() or None
    return title, desc
3937
def parse_docstring(obj, process_doc, endpoint=None, verb=None):
    
    first_line, other_lines, swag = None, None, None

    full_doc = None
    swag_path = getattr(obj, 'swag_path', None)
    swag_type = getattr(obj, 'swag_type', 'yml')
    swag_paths = getattr(obj, 'swag_paths', None)
    root_path = get_root_path(obj)
    from_file = False

    if swag_path is not None:
        full_doc = load_from_file(swag_path, swag_type)
        from_file = True
    elif swag_paths is not None:
        for key in ("{}_{}".format(endpoint, verb), endpoint, verb.lower()):
            if key in swag_paths:
                full_doc = load_from_file(swag_paths[key], swag_type)
                break
        from_file = True
        # TODO: handle multiple root_paths
        # to support `import: ` from multiple places
    else:
        full_doc = inspect.getdoc(obj)

    if full_doc:

        if full_doc.startswith('file:'):
            if not hasattr(obj, 'root_path'):
                obj.root_path = root_path
            swag_path, swag_type = get_path_from_doc(full_doc)
            doc_filepath = os.path.join(obj.root_path, swag_path)
            full_doc = load_from_file(doc_filepath, swag_type)
            from_file = True

        full_doc = parse_imports(full_doc, root_path)

        yaml_sep = full_doc.find('---')

        if yaml_sep != -1:
            line_feed = full_doc.find('\n')
            if line_feed != -1:
                first_line = process_doc(full_doc[:line_feed])
                other_lines = process_doc(
                    full_doc[line_feed + 1: yaml_sep]
                )
                swag = yaml.load(full_doc[yaml_sep + 4:])
        else:
            if from_file:
                swag = yaml.load(full_doc)
            else:
                first_line = full_doc

    return first_line, other_lines, swag
489662
def parse_docstring(thing):
    
    assert not isinstance(thing, bytes)
    doc = cleandoc(thing) if isinstance(thing, str) else getdoc(thing)
    doc = empty if doc is None else doc
    assert not isinstance(doc, bytes)
    # Break the docstring into two parts: title and body.
    parts = docstring_split(doc)
    if len(parts) == 2:
        title, body = parts[0], parts[1]
    else:
        title, body = parts[0], empty
    # Remove line breaks from the title line.
    title = remove_line_breaks(title)
    # Normalise line-breaks on newline.
    body = body.replace("\r\n", newline).replace("\r", newline)
    return docstring(title, body)
218654
def get_docstr(func_or_class):
    
    import utool as ut
    try:
        docstr_ = func_or_class.func_doc
    except AttributeError:
        docstr_ = func_or_class.__doc__
    if docstr_ is None:
        docstr_ = ''
    docstr = ut.unindent(docstr_)
    return docstr
358259
def stringify_dict_contents(dct):
    """"""
    return {
        str_if_nested_or_str(k): str_if_nested_or_str(v)
        for k, v in dct.items()
    }
1135553
def _read_dict(self, f):
        
        d = {}
        for k, item in f.items():
            if type(item) == h5py._hl.dataset.Dataset:
                v = item.value
                if type(v) == np.string_:
                    v = str(v)
                if type(v) == str and v == "NONE":
                    d[k] = None
                elif type(v) == str and v == "EMPTYARR":
                    d[k] = np.array([])
                elif isinstance(v, bytes):
                    d[k] = v.decode('utf-8')
                else:
                    d[k] = v

            elif k[:5] == "DICT_":
                d[k[5:]] = self._read_dict(item)
            elif k[:5] == "LIST_":
                tmpD = self._read_dict(item)
                d[k[5:]] = [tmpD[str(i)] for i in range(len(tmpD))]
        return d
618408
def get_module_docstring(filepath):
    ""
    co = compile(open(filepath).read(), filepath, 'exec')
    if co.co_consts and isinstance(co.co_consts[0], six.string_types):
        docstring = co.co_consts[0]
    else:
        docstring = None
    return docstring
249019
def _parse_docstrings(self, filepath):
        """"""        
        xmlpath = self.get_xmldoc_path(filepath)
        if self.tramp.exists(xmlpath):
            xmlstring = self.tramp.read(xmlpath)
            self.modulep.docparser.parsexml(xmlstring, self.modules, xmlpath)
706380
def parse_docstring(docstring):
    '''
    
    '''
    if docstring is None:
        return '', ''

    parts = _DOCSTRING_SPLIT.split(docstring)

    if len(parts) == 1:
        return docstring, ''
    elif len(parts) == 2:
        return parts[0], parts[1]
    else:
        raise TooManySplitsError()
1066387
def parse_docopt_string(docopt_string):
    """"""
    from re import match, DOTALL
    only_usage_pattern = r"""\s+Usage:\s+(?P<usage>.*)\s+"""
    usage_and_options_pattern = r"""\s+Usage:\s+(?P<usage>.*)\s+Options:\s+(?P<options>.*)\s+"""
    usage, options = '', ''
    if match(usage_and_options_pattern, docopt_string, DOTALL):
        usage = match(usage_and_options_pattern, docopt_string, DOTALL).groupdict()['usage']
        options = match(usage_and_options_pattern, docopt_string, DOTALL).groupdict()['options']
    elif match(only_usage_pattern, docopt_string, DOTALL):
        usage = match(only_usage_pattern, docopt_string, DOTALL).groupdict()['usage']
    return usage, options
1172144
def parse_doc(s):
    
    if not s:
        return
    doc = DocObject()
    tag = None
    s = s[3:-2]  # remove '/**' and '*/'
    for line in s.splitlines():
        line = line.lstrip(' *')  # strip a ' ' and '*' from start
        if not line:
            tag = None  # on empty line reset the tag information
        elif line[0] == '@':
            line = line[1:]
            res = line.split(maxsplit=1)
            if len(res) == 0:
                continue
            tag = res[0]
            if len(res) == 1:
                doc.add_tag(tag, True)
            elif len(res) == 2:
                value = res[1]
                doc.add_tag(tag, value)
        elif tag:  # append to previous matched tag
            doc.add_tag(tag, line)
        else: # append any loose lines to description
            doc.add_tag('description', line)
    return doc