Example #1
0
async def docStormTypes():
    registry = s_stormtypes.registry

    libsinfo = registry.getLibDocs()

    libspage = s_autodoc.RstHelp()

    libspage.addHead('Storm Libraries',
                     lvl=0,
                     link='.. _stormtypes-libs-header:')

    lines = (
        '',
        'Storm Libraries represent powerful tools available inside of the Storm query language.',
        '')
    libspage.addLines(*lines)

    s_autodoc.docStormTypes(libspage,
                            libsinfo,
                            linkprefix='stormlibs',
                            islib=True)

    priminfo = registry.getTypeDocs()
    typespage = s_autodoc.RstHelp()

    typespage.addHead('Storm Types', lvl=0, link='.. _stormtypes-prim-header:')

    lines = (
        '',
        'Storm Objects are used as view objects for manipulating data in the Storm Runtime and in the Cortex itself.'
        '')
    typespage.addLines(*lines)
    s_autodoc.docStormTypes(typespage, priminfo, linkprefix='stormprims')

    return libspage, typespage
Example #2
0
async def docModel(outp,
                   core):
    coreinfo = await core.getCoreInfo()
    _, model = coreinfo.get('modeldef')[0]

    ctors = model.get('ctors')
    types = model.get('types')
    forms = model.get('forms')
    univs = model.get('univs')
    props = collections.defaultdict(list)

    ctors = sorted(ctors, key=lambda x: x[0])
    univs = sorted(univs, key=lambda x: x[0])
    types = sorted(types, key=lambda x: x[0])
    forms = sorted(forms, key=lambda x: x[0])
    univ_names = {univ[0] for univ in univs}

    for fname, fnfo, fprops in forms:
        for prop in fprops:
            props[fname].append(prop)

    [v.sort() for k, v in props.items()]

    dochelp = DocHelp(ctors, types, forms, props, univs)

    # Validate examples
    for form, example in dochelp.formhelp.items():
        if example is None:
            continue
        if example.startswith('('):
            q = f"[{form}={example}]"
        else:
            q = f"[{form}='{example}']"
        node = False
        async for (mtyp, mnfo) in core.storm(q, {'editformat': 'none'}):
            if mtyp in ('init', 'fini'):
                continue
            if mtyp == 'err':  # pragma: no cover
                raise s_exc.SynErr(mesg='Invalid example', form=form, example=example, info=mnfo)
            if mtyp == 'node':
                node = True
        if not node:  # pramga: no cover
            raise s_exc.SynErr(mesg='Unable to make a node from example.', form=form, example=example)

    rst = s_autodoc.RstHelp()
    rst.addHead('Synapse Data Model - Types', lvl=0)

    processCtors(rst, dochelp, ctors)
    processTypes(rst, dochelp, types)

    rst2 = s_autodoc.RstHelp()
    rst2.addHead('Synapse Data Model - Forms', lvl=0)

    processFormsProps(rst2, dochelp, forms, univ_names)
    processUnivs(rst2, dochelp, univs)

    return rst, rst2
Example #3
0
async def docStormpkg(pkgpath):
    pkgdef = s_genpkg.loadPkgProto(pkgpath)
    pkgname = pkgdef.get('name')

    rst = s_autodoc.RstHelp()

    # Disable default python highlighting
    rst.addLines('.. highlight:: none\n')

    hname = pkgname
    if ':' in pkgname:
        hname = pkgname.replace(':', raw_back_slash_colon)

    rst.addHead(f'Storm Package\\: {hname}')
    lines = ['The following Commands are available from this package.',
             f'This documentation is generated for version '
             f'{s_version.fmtVersion(*pkgdef.get("version"))} of the package.',
             ]
    rst.addLines(*lines)

    commands = pkgdef.get('commands')
    if commands:
        await processStormCmds(rst, pkgname, commands)

    # TODO: Modules are not currently documented.

    return rst, pkgname
Example #4
0
async def docStormsvc(ctor):
    cls = s_dyndeps.tryDynLocal(ctor)

    if not hasattr(cls, 'cellapi'):
        raise Exception('ctor must have a cellapi attr')

    clsname = cls.__name__

    cellapi = cls.cellapi

    if not issubclass(cellapi, s_stormsvc.StormSvc):
        raise Exception('cellapi must be a StormSvc implementation')

    # Make a dummy object
    class MockSess:
        def __init__(self):
            self.user = None

    class DummyLink:
        def __init__(self):
            self.info = {'sess': MockSess()}

        def get(self, key):
            return self.info.get(key)

    async with await cellapi.anit(s_common.novalu, DummyLink(), s_common.novalu) as obj:
        svcinfo = await obj.getStormSvcInfo()

    rst = s_autodoc.RstHelp()

    # Disable default python highlighting
    rst.addLines('.. highlight:: none\n')

    rst.addHead(f'{clsname} Storm Service')
    lines = ['The following Storm Packages and Commands are available from this service.',
             f'This documentation is generated for version '
             f'{s_version.fmtVersion(*svcinfo.get("vers"))} of the service.',
             f'The Storm Service name is ``{svcinfo.get("name")}``.',
             ]
    rst.addLines(*lines)

    for pkg in svcinfo.get('pkgs'):
        pname = pkg.get('name')
        pver = pkg.get('version')
        commands = pkg.get('commands')

        hname = pname
        if ':' in pname:
            hname = pname.replace(':', raw_back_slash_colon)

        rst.addHead(f'Storm Package\\: {hname}', lvl=1)

        rst.addLines(f'This documentation for {pname} is generated for version {s_version.fmtVersion(*pver)}')

        if commands:
            await processStormCmds(rst, pname, commands)

        # TODO: Modules are not currently documented.

    return rst, clsname
Example #5
0
async def docStormTypes():
    registry = s_stormtypes.registry

    libsinfo = registry.getLibDocs()

    libspage = s_autodoc.RstHelp()

    libspage.addHead('Storm Libraries', lvl=0, link='.. _stormtypes-libs-header:')

    lines = (
        '',
        'Storm Libraries represent powerful tools available inside of the Storm query language.',
        ''
    )
    libspage.addLines(*lines)

    # This value is appended to the end of the ref to the first level header of a type.
    # This prevents accidental cross linking between parts of the docs; which can happen
    # when secondary properties of a type may overlap with the main name of the type.
    types_suffix = 'f527'

    s_autodoc.docStormTypes(libspage, libsinfo, linkprefix='stormlibs', islib=True,
                            known_types=registry.known_types, types_prefix='stormprims', types_suffix=types_suffix)

    priminfo = registry.getTypeDocs()
    typespage = s_autodoc.RstHelp()

    typespage.addHead('Storm Types', lvl=0, link='.. _stormtypes-prim-header:')

    lines = (
        '',
        'Storm Objects are used as view objects for manipulating data in the Storm Runtime and in the Cortex itself.'
        ''
    )
    typespage.addLines(*lines)
    s_autodoc.docStormTypes(typespage, priminfo, linkprefix='stormprims', known_types=registry.known_types,
                            types_prefix='stormprims', types_suffix=types_suffix)

    return libspage, typespage
Example #6
0
async def docConfdefs(ctor, reflink=':ref:`devops-cell-config`', doc_title=None):
    cls = s_dyndeps.tryDynLocal(ctor)

    if not hasattr(cls, 'confdefs'):
        raise Exception('ctor must have a confdefs attr')

    rst = s_autodoc.RstHelp()

    clsname = cls.__name__
    conf = cls.initCellConf()  # type: s_config.Config
    if doc_title is None:
        doc_title = clsname
    rst.addHead(f'{doc_title} Configuration Options', lvl=0, link=f'.. _autodoc-{clsname.lower()}-conf:')
    rst.addLines(f'The following are boot-time configuration options for the cell.')

    rst.addLines(f'See {reflink} for details on how to set these options.')

    # access raw config data

    # Get envar and argparse mapping
    name2envar = conf.getEnvarMapping()
    name2cmdline = conf.getCmdlineMapping()

    schema = conf.json_schema.get('properties', {})

    for name, conf in sorted(schema.items(), key=lambda x: x[0]):

        if conf.get('hideconf'):
            continue

        nodesc = f'No description available for ``{name}``.'
        hname = name
        if ':' in name:
            hname = name.replace(':', raw_back_slash_colon)

        rst.addHead(hname, lvl=1)

        desc = conf.get('description', nodesc)
        if not desc.endswith('.'):  # pragma: no cover
            logger.warning(f'Description for [{name}] is missing a period.')

        lines = []
        lines.append(desc)

        extended_description = conf.get('extended_description')
        if extended_description:
            lines.append('\n')
            lines.append(extended_description)

        # Type/additional information

        lines.append('\n')

        ctyp = conf.get('type')
        lines.append('Type')
        lines.append(f'    ``{ctyp}``\n')

        if ctyp == 'object':
            if conf.get('properties'):
                lines.append('Properties')
                lines.append('    The object expects the following properties:')
                data = {k: v for k, v in conf.items() if k not in (
                    'description', 'default', 'type', 'hideconf', 'hidecmdl',
                )}
                parts = json.dumps(data, sort_keys=True, indent=2).split('\n')
                lines.append('    ::')
                lines.append('\n')
                lines.extend([f'      {p}' for p in parts])
                lines.append('\n')

        defval = conf.get('default', s_common.novalu)
        if defval is not s_common.novalu:
            lines.append('Default Value')
            lines.append(f'    ``{repr(defval)}``\n')

        envar = name2envar.get(name)
        if envar:
            lines.append('Environment Variable')
            lines.append(f'    ``{envar}``\n')

        cmdline = name2cmdline.get(name)
        if cmdline:
            lines.append('Command Line Argument')
            lines.append(f'    ``--{cmdline}``\n')

        rst.addLines(*lines)

    return rst, clsname
Example #7
0
async def docStormsvc(ctor):
    cls = s_dyndeps.tryDynLocal(ctor)

    if not hasattr(cls, 'cellapi'):
        raise Exception('ctor must have a cellapi attr')

    clsname = cls.__name__

    cellapi = cls.cellapi

    if not issubclass(cellapi, s_stormsvc.StormSvc):
        raise Exception('cellapi must be a StormSvc implementation')

    # Make a dummy object
    class MockSess:
        def __init__(self):
            self.user = None

    class DummyLink:
        def __init__(self):
            self.info = {'sess': MockSess()}

        def get(self, key):
            return self.info.get(key)

    async with await cellapi.anit(s_common.novalu, DummyLink(),
                                  s_common.novalu) as obj:
        svcinfo = await obj.getStormSvcInfo()

    rst = s_autodoc.RstHelp()

    # Disable default python highlighting
    rst.addLines('.. highlight:: none\n')

    rst.addHead(f'{clsname} Storm Service')
    lines = [
        'The following Storm Packages and Commands are available from this service.',
        f'This documentation is generated for version '
        f'{s_version.fmtVersion(*svcinfo.get("vers"))} of the service.',
        f'The Storm Service name is ``{svcinfo.get("name")}``.',
    ]
    rst.addLines(*lines)

    for pkg in svcinfo.get('pkgs'):
        pname = pkg.get('name')
        pver = pkg.get('version')
        commands = pkg.get('commands')

        hname = pname
        if ':' in pname:
            hname = pname.replace(':', raw_back_slash_colon)

        rst.addHead(f'Storm Package\\: {hname}', lvl=1)

        rst.addLines(
            f'This documentation for {pname} is generated for version {s_version.fmtVersion(*pver)}'
        )

        if commands:
            rst.addHead('Storm Commands', lvl=2)

            rst.addLines(
                f'This package implements the following Storm Commands.\n')

            for cdef in commands:

                cname = cdef.get('name')
                cdesc = cdef.get('descr')
                cargs = cdef.get('cmdargs')

                # command names cannot have colons in them thankfully
                cref = f'.. _stormcmd-{pname.replace(":", "-")}-{cname.replace(".", "-")}:'
                rst.addHead(cname, lvl=3, link=cref)

                # Form the description
                lines = ['::\n']

                # Generate help from args
                pars = s_storm.Parser(prog=cname, descr=cdesc)
                if cargs:
                    for (argname, arginfo) in cargs:
                        pars.add_argument(argname, **arginfo)
                pars.help()

                for line in pars.mesgs:
                    if '\n' in line:
                        for subl in line.split('\n'):
                            lines.append(f'    {subl}')
                    else:
                        lines.append(f'    {line}')

                lines.append('\n')

                forms = cdef.get('forms', {})
                iforms = forms.get('input')
                oforms = forms.get('output')
                nodedata = forms.get('nodedata')

                if iforms:
                    line = 'The command is aware of how to automatically handle the following forms as input nodes:\n'
                    lines.append(line)
                    for form in iforms:
                        lines.append(f'- ``{form}``')
                    lines.append('\n')

                if oforms:
                    line = 'The command may make the following types of nodes in the graph as a result of its execution:\n'
                    lines.append(line)
                    for form in oforms:
                        lines.append(f'- ``{form}``')
                    lines.append('\n')

                if nodedata:
                    line = 'The command may add nodedata with the following keys to the corresponding forms:\n'
                    lines.append(line)
                    for key, form in nodedata:
                        lines.append(f'- ``{key}`` on ``{form}``')
                    lines.append('\n')

                rst.addLines(*lines)

        # TODO: Modules are not currently documented.

    return rst, clsname