예제 #1
0
파일: snap.py 프로젝트: wesinator/synapse
    async def nodesByPropValu(self, full, cmpr, valu):

        if cmpr == 'type=':
            async for node in self.nodesByPropValu(full, '=', valu):
                yield node

            async for node in self.nodesByPropTypeValu(full, valu):
                yield node
            return

        prop = self.core.model.prop(full)
        if prop is None:
            mesg = f'No property named "{full}".'
            raise s_exc.NoSuchProp(mesg=mesg)

        cmprvals = prop.type.getStorCmprs(cmpr, valu)
        # an empty return probably means ?= with invalid value
        if not cmprvals:
            return

        if prop.isrunt:
            for storcmpr, storvalu, _ in cmprvals:
                async for node in self.getRuntNodes(prop.full,
                                                    valu=storvalu,
                                                    cmpr=storcmpr):
                    yield node
            return

        if prop.isform:

            for layr in self.layers:
                genr = layr.liftByFormValu(prop.name, cmprvals)

                async for node in self._joinStorGenr(layr, genr):

                    # TODO merge sort rather than use bylayer
                    if node.bylayer.get('ndef') != layr:
                        continue

                    yield node

            return

        if prop.isuniv:

            for layr in self.layers:
                genr = layr.liftByPropValu(None, prop.name, cmprvals)
                async for node in self._joinStorGenr(layr, genr):
                    if node.bylayer['props'].get(prop.name) != layr:
                        continue
                    yield node

            return

        for layr in self.layers:
            genr = layr.liftByPropValu(prop.form.name, prop.name, cmprvals)
            async for node in self._joinStorGenr(layr, genr):
                if node.bylayer['props'].get(prop.name) != layr:
                    continue
                yield node
예제 #2
0
    async def nodesByPropArray(self, full, cmpr, valu):

        prop = self.core.model.prop(full)
        if prop is None:
            mesg = f'No property named "{full}".'
            raise s_exc.NoSuchProp(mesg=mesg)

        if not isinstance(prop.type, s_types.Array):
            mesg = f'Array synax is invalid on non array type: {prop.type.name}.'
            raise s_exc.BadTypeValu(mesg=mesg)

        cmprvals = prop.type.arraytype.getStorCmprs(cmpr, valu)

        if prop.isform:
            async for (buid, sodes) in self.core._liftByPropArray(
                    prop.name, None, cmprvals, self.layers):
                node = await self._joinSodes(buid, sodes)
                if node is not None:
                    yield node
            return

        formname = None
        if prop.form is not None:
            formname = prop.form.name

        async for (buid, sodes) in self.core._liftByPropArray(
                formname, prop.name, cmprvals, self.layers):
            node = await self._joinSodes(buid, sodes)
            if node is not None:
                yield node
예제 #3
0
    async def _getPropDelEdits(self, name, init=False):

        prop = self.form.prop(name)
        if prop is None:
            if self.snap.strict:
                mesg = f'No property named {name}.'
                raise s_exc.NoSuchProp(mesg=mesg,
                                       name=name,
                                       form=self.form.name)
            await self.snap.warn(f'No Such Property: {name}')
            return ()

        if not init:

            if prop.info.get('ro'):
                if self.snap.strict:
                    raise s_exc.ReadOnlyProp(name=name)
                await self.snap.warn(f'Property is read-only: {name}')
                return ()

        curv = self.props.get(name, s_common.novalu)
        if curv is s_common.novalu:
            return ()

        edits = ((s_layer.EDIT_PROP_DEL, (prop.name, None, prop.type.stortype),
                  ()), )
        return edits
예제 #4
0
파일: snap.py 프로젝트: freecamel/synapse
    async def nodesByPropArray(self, full, cmpr, valu):

        prop = self.core.model.prop(full)
        if prop is None:
            mesg = f'No property named "{full}".'
            raise s_exc.NoSuchProp(mesg=mesg)

        if not isinstance(prop.type, s_types.Array):
            mesg = f'Array synax is invalid on non array type: {prop.type.name}.'
            raise s_exc.BadTypeValu(mesg=mesg)

        cmprvals = prop.type.arraytype.getStorCmprs(cmpr, valu)

        if prop.isform:

            for layr in self.layers:
                genr = layr.liftByPropArray(prop.name, None, cmprvals)
                async for node in self._joinStorGenr(layr, genr):
                    if node.bylayer['ndef'] != layr:
                        continue
                    yield node

            return

        formname = None
        if prop.form is not None:
            formname = prop.form.name

        for layr in self.layers:
            genr = layr.liftByPropArray(formname, prop.name, cmprvals)
            async for node in self._joinStorGenr(layr, genr):
                if node.bylayer['props'].get(prop.name) != layr:
                    continue
                yield node
예제 #5
0
파일: node.py 프로젝트: wesinator/synapse
    async def pop(self, name, init=False):
        '''
        Remove a property from a node and return the value
        '''
        prop = self.form.prop(name)
        if prop is None:
            if self.snap.strict:
                raise s_exc.NoSuchProp(name=name, form=self.form.name)
            await self.snap.warn(f'No Such Property: {name}')
            return False

        if self.form.isrunt:
            if prop.info.get('ro'):
                raise s_exc.IsRuntForm(
                    mesg='Cannot delete read-only props on runt nodes',
                    form=self.form.full,
                    prop=name)
            return await self.snap.core.runRuntPropDel(self, prop)

        if not init:

            if prop.info.get('ro'):
                if self.snap.strict:
                    raise s_exc.ReadOnlyProp(name=name)
                await self.snap.warn(f'Property is read-only: {name}')
                return False

        curv = self.props.pop(name, s_common.novalu)
        if curv is s_common.novalu:
            return False

        edits = ((s_layer.EDIT_PROP_DEL, (prop.name, None, prop.type.stortype),
                  ()), )

        await self.snap.applyNodeEdit((self.buid, self.form.name, edits))
예제 #6
0
파일: ast.py 프로젝트: rjammala/synapse
    async def run(self, runt, genr):
        warned = False
        name = self.kids[1].value()

        prop = runt.snap.model.props.get(name)
        if prop is None:
            raise s_exc.NoSuchProp(name=name)

        # TODO if we are pivoting to a form, use ndef!

        async for node, path in genr:

            if self.isjoin:
                yield node, path

            valu = await self.kids[0].compute(path)
            if valu is None:
                continue

            # TODO cache/bypass normalization in loop!
            try:
                async for pivo in runt.snap.getNodesBy(prop.full, valu):
                    yield pivo, path.fork(pivo)
            except (s_exc.BadTypeValu, s_exc.BadLiftValu) as e:
                if not warned:
                    logger.warning(f'Caught error during pivot: {e.items()}')
                    warned = True
                items = e.items()
                mesg = items.pop('mesg', '')
                mesg = ': '.join(
                    (f'{e.__class__.__qualname__} [{repr(valu)}] during pivot',
                     mesg))
                await runt.snap.fire('warn', mesg=mesg, **items)
예제 #7
0
    async def _getNodesByProp(self, full, valu=None, cmpr='='):

        prop = self.model.prop(full)
        if prop is None:
            raise s_exc.NoSuchProp(name=full)

        if prop.isrunt:

            async for node in self.getRuntNodes(full, valu, cmpr):
                yield node

            return

        lops = prop.getLiftOps(valu, cmpr=cmpr)

        if prop.isform and cmpr == '=' and valu is not None and len(
                lops) == 1 and lops[0][1][2][0][0] == 'eq':
            # Shortcut to buid lookup if primary prop = valu
            norm, _ = prop.type.norm(valu)
            node = await self.getNodeByNdef((full, norm))
            if node is None:
                return

            yield node

            return

        cmpf = prop.type.getLiftHintCmpr(valu, cmpr=cmpr)

        async for row, node in self.getLiftNodes(lops, prop.name, cmpf):
            yield node
예제 #8
0
파일: model.py 프로젝트: wesinator/synapse
    async def _methEdgeDel(self, verb, key):
        '''
        Delete a key from the key-value store for a verb.

        Args:
            verb (str): The name of the Edge verb to remove a key from.

            key (str): The name of the key to remove from the key-value store.

        Returns:
            None: Returns None.
        '''
        verb = await s_stormtypes.tostr(verb)
        await self._chkEdgeVerbInView(verb)

        key = await s_stormtypes.tostr(key)
        await self._chkKeyName(key)

        path = self.hivepath + (verb, 'extprops')
        kvdict = await self.runt.snap.core.getHiveKey(path) or {}

        oldv = kvdict.pop(key, None)
        if oldv is None:
            raise s_exc.NoSuchProp(mesg=f'Key is not set for this edge verb',
                                   verb=verb,
                                   name=key)

        await self.runt.snap.core.setHiveKey(path, kvdict)
예제 #9
0
    async def nodesByPropValu(self, full, cmpr, valu):
        if cmpr == 'type=':
            async for node in self.nodesByPropValu(full, '=', valu):
                yield node

            async for node in self.nodesByPropTypeValu(full, valu):
                yield node
            return

        prop = self.core.model.prop(full)
        if prop is None:
            mesg = f'No property named "{full}".'
            raise s_exc.NoSuchProp(mesg=mesg)

        cmprvals = prop.type.getStorCmprs(cmpr, valu)
        # an empty return probably means ?= with invalid value
        if not cmprvals:
            return

        if prop.isrunt:
            for storcmpr, storvalu, _ in cmprvals:
                async for node in self.getRuntNodes(prop.full,
                                                    valu=storvalu,
                                                    cmpr=storcmpr):
                    yield node
            return

        if prop.isform:

            found = 0
            async for (buid, sodes) in self.core._liftByFormValu(
                    prop.name, cmprvals, self.layers):
                node = await self._joinSodes(buid, sodes)
                if node is not None:
                    found += 1
                    yield node

            return

        if prop.isuniv:
            async for (buid, sodes) in self.core._liftByPropValu(
                    None, prop.name, cmprvals, self.layers):
                node = await self._joinSodes(buid, sodes)
                if node is not None:
                    yield node
            return

        async for (buid,
                   sodes) in self.core._liftByPropValu(prop.form.name,
                                                       prop.name, cmprvals,
                                                       self.layers):
            node = await self._joinSodes(buid, sodes)
            if node is not None:
                yield node
예제 #10
0
    def _normPyTuple(self, valu):
        try:
            propname, propvalu = valu
        except Exception as e:
            raise s_exc.BadTypeValu(name=self.name, valu=valu, mesg=str(e)) from None

        prop = self.modl.prop(propname)
        if prop is None:
            raise s_exc.NoSuchProp(name=self.name, prop=propname)

        propnorm, info = prop.type.norm(propvalu)
        return (prop.full, propnorm), {'subs': {'prop': prop.full}}
예제 #11
0
    async def _getNodesByProp(self, full, valu=None, cmpr='='):

        prop = self.model.prop(full)
        if prop is None:
            raise s_exc.NoSuchProp(name=full)
        if prop.isrunt:
            async for node in self.getRuntNodes(full, valu, cmpr):
                yield node
        else:
            lops = prop.getLiftOps(valu, cmpr=cmpr)
            cmpf = prop.type.getLiftHintCmpr(valu, cmpr=cmpr)
            async for row, node in self.getLiftNodes(lops, prop.name, cmpf):
                yield node
예제 #12
0
    async def nodesByProp(self, full):

        prop = self.core.model.prop(full)
        if prop is None:
            mesg = f'No property named "{full}".'
            raise s_exc.NoSuchProp(mesg=mesg)

        if prop.isrunt:

            async for node in self.getRuntNodes(prop.full):
                yield node

            return

        if prop.isform:

            for layr in self.layers:
                genr = layr.liftByProp(prop.name, None)

                async for node in self._joinStorGenr(layr, genr):

                    # TODO merge sort rather than use bylayer
                    if node.bylayer.get('ndef') != layr:
                        continue

                    yield node
            return

        if prop.isuniv:

            for layr in self.layers:
                genr = layr.liftByProp(None, prop.name)
                async for node in self._joinStorGenr(layr, genr):
                    # TODO should these type of filters yield?
                    if node.bylayer['props'].get(prop.name) != layr:
                        continue
                    yield node
            return

        formname = None
        if not prop.isuniv:
            formname = prop.form.name

        # Prop is secondary prop

        for layr in self.layers:
            genr = layr.liftByProp(formname, prop.name)
            async for node in self._joinStorGenr(layr, genr):
                if node.bylayer['props'].get(prop.name) != layr:
                    continue
                yield node
예제 #13
0
파일: ast.py 프로젝트: rjammala/synapse
    async def run(self, runt, genr):

        name = self.kids[0].value()

        univ = runt.snap.model.props.get(name)
        if univ is None:
            raise s_exc.NoSuchProp(name=name)

        async for node, path in genr:

            runt.allowed('prop:del', name)

            await node.pop(name)
            yield node, path
예제 #14
0
파일: node.py 프로젝트: wesinator/synapse
    def repr(self, name=None, defv=None):

        if name is None:
            return self.form.type.repr(self.ndef[1])

        prop = self.form.props.get(name)
        if prop is None:
            raise s_exc.NoSuchProp(form=self.form.name, prop=name)

        valu = self.props.get(name)
        if valu is None:
            return defv

        return prop.type.repr(valu)
예제 #15
0
    def repr(self, name=None, defv=None):

        if name is None:
            return self.form.type.repr(self.ndef[1])

        prop = self.form.props.get(name)
        if prop is None:
            mesg = f'No property named {name}.'
            raise s_exc.NoSuchProp(mesg=mesg, form=self.form.name, prop=name)

        valu = self.props.get(name)
        if valu is None:
            return defv

        return prop.type.repr(valu)
예제 #16
0
파일: ast.py 프로젝트: rjammala/synapse
    async def run(self, runt, genr):

        name = self.kids[0].value()

        async for node, path in genr:

            prop = node.form.props.get(name)
            if prop is None:
                raise s_exc.NoSuchProp(name=name, form=node.form.name)

            runt.allowed('prop:del', prop.full)

            await node.pop(name)

            yield node, path
예제 #17
0
    async def _methEdgeDel(self, verb, key):
        verb = await s_stormtypes.tostr(verb)
        await self._chkEdgeVerbInView(verb)

        key = await s_stormtypes.tostr(key)
        await self._chkKeyName(key)

        path = self.hivepath + (verb, 'extprops')
        kvdict = await self.runt.snap.core.getHiveKey(path) or {}

        oldv = kvdict.pop(key, None)
        if oldv is None:
            raise s_exc.NoSuchProp(mesg=f'Key is not set for this edge verb',
                                   verb=verb, name=key)

        await self.runt.snap.core.setHiveKey(path, kvdict)
예제 #18
0
    def delFormProp(self, formname, propname):

        form = self.forms.get(formname)
        if form is None:
            raise s_exc.NoSuchForm(name=formname)

        prop = form.props.pop(propname, None)
        if prop is None:
            raise s_exc.NoSuchProp(name=f'{formname}:{propname}')

        form.props.pop(prop.name, None)
        form.defvals.pop(prop.name, None)
        self.props.pop(prop.full, None)
        self.props.pop((form.name, prop.name), None)

        self.propsbytype[prop.type.name].remove(prop)
예제 #19
0
    def delFormProp(self, formname, propname):

        form = self.forms.get(formname)
        if form is None:
            raise s_exc.NoSuchForm(name=formname)

        prop = form.delProp(propname)
        if prop is None:
            raise s_exc.NoSuchProp(name=f'{formname}:{propname}')

        if isinstance(prop.type, s_types.Array):
            self.arraysbytype[prop.type.arraytype.name].remove(prop)

        self.props.pop(prop.full, None)
        self.props.pop((form.name, prop.name), None)

        self.propsbytype[prop.type.name].remove(prop)
예제 #20
0
파일: ast.py 프로젝트: rjammala/synapse
    async def run(self, runt, genr):

        name = self.kids[0].value()

        async for node, path in genr:

            valu = await self.kids[1].compute(path)

            prop = node.form.props.get(name)
            if prop is None:
                raise s_exc.NoSuchProp(name=name, form=node.form.name)

            runt.allowed('prop:set', prop.full)

            await node.set(name, valu)

            yield node, path
예제 #21
0
    async def nodesByProp(self, full):

        prop = self.core.model.prop(full)
        if prop is None:
            mesg = f'No property named "{full}".'
            raise s_exc.NoSuchProp(mesg=mesg)

        if prop.isrunt:
            async for node in self.getRuntNodes(prop.full):
                yield node
            return

        if prop.isform:
            async for (buid,
                       sodes) in self.core._liftByProp(prop.name, None,
                                                       self.layers):
                node = await self._joinSodes(buid, sodes)
                if node is not None:
                    yield node
            return

        if prop.isuniv:
            async for (buid,
                       sodes) in self.core._liftByProp(None, prop.name,
                                                       self.layers):
                node = await self._joinSodes(buid, sodes)
                if node is not None:
                    yield node
            return

        formname = None
        if not prop.isuniv:
            formname = prop.form.name

        # Prop is secondary prop
        async for (buid,
                   sodes) in self.core._liftByProp(formname, prop.name,
                                                   self.layers):
            node = await self._joinSodes(buid, sodes)
            if node is not None:
                yield node
예제 #22
0
    async def pop(self, name, init=False):
        '''
        Remove a property from a node and return the value
        '''
        prop = self.form.prop(name)
        if prop is None:
            if self.snap.strict:
                raise s_exc.NoSuchProp(name=name, form=self.form.name)
            await self.snap.warn(f'No Such Property: {name}')
            return False

        if self.isrunt:
            if prop.info.get('ro'):
                raise s_exc.IsRuntForm(
                    mesg='Cannot delete read-only props on runt nodes',
                    form=self.form.full,
                    prop=name)
            return await self.snap.core.runRuntPropDel(self, prop)

        if not init:

            if prop.info.get('ro'):
                if self.snap.strict:
                    raise s_exc.ReadOnlyProp(name=name)
                await self.snap.warn(f'Property is read-only: {name}')
                return False

        curv = self.props.pop(name, s_common.novalu)
        if curv is s_common.novalu:
            return False

        sops = prop.getDelOps(self.buid)
        splice = self.snap.splice('prop:del',
                                  ndef=self.ndef,
                                  prop=prop.name,
                                  valu=curv)
        await self.snap.stor(sops, [splice])

        await prop.wasDel(self, curv)
예제 #23
0
파일: ast.py 프로젝트: rjammala/synapse
    def getCondEval(self, runt):

        name = self.kids[0].value()

        prop = runt.snap.model.props.get(name)
        if prop is None:
            raise s_exc.NoSuchProp(name=name)

        if prop.isform:

            async def cond(node, path):
                return node.form.name == prop.name

            return cond

        async def cond(node, path):

            if node.form.name != prop.form.name:
                return False

            return node.has(prop.name)

        return cond
예제 #24
0
    async def getNodesByArray(self, name, valu, cmpr='='):
        '''
        Yield nodes by an array property with *items* matching <cmpr> <valu>
        '''

        prop = self.model.props.get(name)
        if prop is None:
            mesg = f'No property named {name}.'
            raise s_exc.NoSuchProp(mesg=mesg)

        if not isinstance(prop.type, s_types.Array):
            mesg = f'Prop ({name}) is not an array type.'
            raise s_exc.BadTypeValu(mesg=mesg)

        iops = prop.type.arraytype.getIndxOps(valu, cmpr=cmpr)

        prefix = prop.pref + b'\x01'
        lops = (('indx', (prop.dbname, prefix, iops)), )

        #TODO post-lift cmpr filter
        #cmpf = prop.type.getLiftHintCmpr(valu, cmpr=cmpr)
        async for row, node in self.getLiftNodes(lops, prop.name):
            yield node
예제 #25
0
파일: ast.py 프로젝트: rjammala/synapse
    def getCondEval(self, runt):

        name = self.kids[0].value()
        cmpr = self.kids[1].value()

        prop = runt.snap.model.props.get(name)
        if prop is None:
            raise s_exc.NoSuchProp(name=name)

        ctor = prop.type.getCmprCtor(cmpr)
        if ctor is None:
            raise s_exc.NoSuchCmpr(cmpr=cmpr, name=prop.type.name)

        if prop.isform:

            async def cond(node, path):

                if node.ndef[0] != name:
                    return False

                val1 = node.ndef[1]
                val2 = await self.kids[2].compute(path)

                return ctor(val2)(val1)

            return cond

        async def cond(node, path):
            val1 = node.get(prop.name)
            if val1 is None:
                return False

            val2 = await self.kids[2].compute(path)
            return ctor(val2)(val1)

        return cond
예제 #26
0
파일: syntax.py 프로젝트: rjammala/synapse
    def oper(self):
        '''
        '''

        self.ignore(whitespace)

        if not self.more():
            self._raiseSyntaxError('unexpected end of query text')

        if self.nextstr('{'):
            return self.subquery()

        # some syntax elements prior to a prop/oper name...
        if self.nextstr('->'):
            return self.formpivot()

        if self.nextstr('-+>'):
            return self.formjoin()

        if self.nextstr('<-'):
            return self.formpivotin()

        if self.nextstr('<+-'):
            return self.formjoinin()

        if self.nextstr('##'):
            return self.lifttagtag()

        char = self.nextchar()

        # var list assignment
        # ($foo, $bar) = $baz
        if char == '(':
            varl = self.varlist()

            self.ignore(whitespace)

            self.nextmust('=')
            self.ignore(whitespace)

            valu = self.valu()

            return s_ast.VarListSetOper(kids=(varl, valu))

        # $foo = valu var assignment
        if char == '$':

            varn = self.varname()

            self.ignore(whitespace)

            self.nextmust('=')

            self.ignore(whitespace)

            valu = self.valu()

            kids = (varn, valu)
            return s_ast.VarSetOper(kids=kids)

        if char in ('+', '-'):
            return self.filtoper()

        if char == '#':
            return self.liftbytag()

        # :foo:bar relative property
        if char == ':':

            prop = self.relprop()

            # :foo=10 here could be assignment...

            self.ignore(whitespace)
            if self.nextstr('->'):
                return self.proppivot(prop)

            if self.nextstr('-+>'):
                return self.propjoin(prop)

            if self.nextstrs('<-', '<+-'):
                self._raiseSyntaxError('Pivot in syntax does not currently support relative properties.')

        tokn = self.peek(varset)
        if tokn == 'for':
            return self.forloop()

        if tokn == 'switch':
            return self.switchcase()

        if tokn == 'break':
            self.offs += 5
            return s_ast.BreakOper()

        if tokn == 'continue':
            self.offs += 8
            return s_ast.ContinueOper()

        noff = self.offs

        name = self.noms(varset)
        if not name:
            self._raiseSyntaxError('unknown query syntax')

        if self.modelinfo.isprop(name):

            # before ignoring more whitespace, check for form#tag[=time]
            if self.nextstr('#'):

                tag = self.tagname()
                form = s_ast.Const(name)

                self.ignore(whitespace)

                kids = [form, tag]

                if self.nextchar() in cmprstart:
                    kids.append(self.cmpr())
                    kids.append(self.valu())

                return s_ast.LiftFormTag(kids=kids)

            self.ignore(whitespace)

            if self.nextchar() in cmprstart:

                cmpr = self.cmpr()
                valu = self.valu()

                kids = (s_ast.Const(name), cmpr, valu)
                return s_ast.LiftPropBy(kids=kids)

            # lift by prop only
            return s_ast.LiftProp(kids=(s_ast.Const(name),))

        if name in self.stormcmds:

            argv = self.cmdargv()

            self.ignore(whitespace)

            # eat a trailing | from a command at the beginning
            if self.nextstr('|'):
                self.offs += 1

            return s_ast.CmdOper(kids=(s_ast.Const(name), argv))

        # rewind and noms until whitespace
        self.offs = noff

        tokn = self.noms(until=whitespace)

        ndefs = list(s_scrape.scrape(tokn))
        if ndefs:
            return s_ast.LiftByScrape(ndefs)

        self.offs = noff
        raise s_exc.NoSuchProp(name=name)
예제 #27
0
파일: ast.py 프로젝트: rjammala/synapse
    async def run(self, runt, genr):
        warned = False
        name = self.kids[0].value()

        prop = runt.snap.model.props.get(name)
        if prop is None:
            raise s_exc.NoSuchProp(name=name)

        # -> baz:ndef
        if isinstance(prop.type, s_types.Ndef):

            async for node, path in genr:

                if self.isjoin:
                    yield node, path

                async for pivo in runt.snap.getNodesBy(prop.full, node.ndef):
                    yield pivo, path.fork(pivo)

            return

        if not prop.isform:

            # plain old pivot...
            async for node, path in genr:

                if self.isjoin:
                    yield node, path

                valu = node.ndef[1]

                # TODO cache/bypass normalization in loop!
                try:
                    async for pivo in runt.snap.getNodesBy(prop.full, valu):
                        yield pivo, path.fork(pivo)
                except (s_exc.BadTypeValu, s_exc.BadLiftValu) as e:
                    if not warned:
                        logger.warning(
                            f'Caught error during pivot: {e.items()}')
                        warned = True
                    items = e.items()
                    mesg = items.pop('mesg', '')
                    mesg = ': '.join((
                        f'{e.__class__.__qualname__} [{repr(valu)}] during pivot',
                        mesg))
                    await runt.snap.fire('warn', mesg=mesg, **items)

        # form -> form pivot is nonsensical. Lets help out...

        # if dest form is a subtype of a graph "edge", use N1 automatically
        if isinstance(prop.type, s_types.Edge):

            full = prop.name + ':n1'

            async for node, path in genr:

                if self.isjoin:
                    yield node, path

                async for pivo in runt.snap.getNodesBy(full, node.ndef):
                    yield pivo, path.fork(pivo)

            return

        # form name and type name match
        formprop = prop
        destform = prop.name

        # TODO: both of these should be precomputed in the model

        @s_cache.memoize()
        def getsrc(form):
            names = []
            for name, prop in form.props.items():
                if prop.type.name == destform:
                    names.append(name)
            return names

        @s_cache.memoize()
        def getdst(form):
            # formprop is really a form here...
            names = []
            for name, prop in formprop.props.items():
                if prop.type.name == form.type.name:
                    names.append(prop.full)
            return names

        async for node, path in genr:

            if self.isjoin:
                yield node, path

            # <syn:tag> -> <form> is "from tags to nodes" pivot
            if node.form.name == 'syn:tag' and prop.isform:
                async for pivo in runt.snap.getNodesBy(
                        f'{prop.name}#{node.ndef[1]}'):
                    yield pivo, path.fork(pivo)

                continue

            # if the source node is a graph edge, use n2
            if isinstance(node.form.type, s_types.Edge):

                n2def = node.get('n2')
                if n2def[0] != destform:
                    continue

                pivo = await runt.snap.getNodeByNdef(node.get('n2'))
                yield pivo, path.fork(pivo)

                continue

            names = getsrc(node.form)
            if names:
                for name in names:

                    valu = node.get(name)
                    if valu is None:
                        continue

                    async for pivo in runt.snap.getNodesBy(prop.name, valu):
                        yield pivo, path.fork(pivo)

                continue

            names = getdst(node.form)
            if names:
                for name in names:
                    found = True

                    valu = node.ndef[1]
                    async for pivo in runt.snap.getNodesBy(name, valu):
                        yield pivo, path.fork(pivo)

                continue

            raise s_exc.NoSuchPivot(n1=node.form.name, n2=destform)
예제 #28
0
 async def _chkKeyName(self, key):
     if key not in self.validedgekeys:
         raise s_exc.NoSuchProp(
             mesg=f'The requested key is not valid for light edge metadata.',
             name=key)
예제 #29
0
    async def execStormCmd(self, runt, genr):

        snap = runt.snap

        if snap.user is not None and not snap.user.admin:
            await snap.warn('reindex requires an admin')
            return

        # are we re-indexing a type?
        if self.opts.type is not None:

            # is the type also a form?
            form = snap.model.forms.get(self.opts.type)

            if form is not None:

                await snap.printf(f'reindex form: {form.name}')

                async for buid, norm in snap.xact.iterFormRows(form.name):
                    await snap.stor(form.getSetOps(buid, norm))

            for prop in snap.model.getPropsByType(self.opts.type):

                await snap.printf(f'reindex prop: {prop.full}')

                formname = prop.form.name

                async for buid, norm in snap.xact.iterPropRows(
                        formname, prop.name):
                    await snap.stor(prop.getSetOps(buid, norm))

            return

        if self.opts.subs:

            async for node, path in genr:

                form, valu = node.ndef
                norm, info = node.form.type.norm(valu)

                subs = info.get('subs')
                if subs is not None:
                    for subn, subv in subs.items():
                        if node.form.props.get(subn):
                            await node.set(subn, subv, init=True)

                yield node, path

            return

        if self.opts.form_counts:
            await snap.printf(f'reindex form counts (full) beginning...')
            await snap.core._calcFormCounts()
            await snap.printf(f'...done')
            return

        if self.opts.fire_handler:
            obj = None
            name = None
            tname = None

            if self.opts.fire_handler.startswith('#'):
                name, _ = runt.snap.model.prop('syn:tag').type.norm(
                    self.opts.fire_handler)
                tname = '#' + name
            else:
                obj = runt.snap.model.prop(self.opts.fire_handler)
                if obj is None:
                    raise s_exc.NoSuchProp(mesg='',
                                           name=self.opts.fire_handler)

            async for node, path in genr:
                if hasattr(obj, 'wasAdded'):
                    if node.form.full != obj.full:
                        continue
                    await obj.wasAdded(node)
                elif hasattr(obj, 'wasSet'):
                    if obj.form.name != node.form.name:
                        continue
                    valu = node.get(obj.name)
                    if valu is None:
                        continue
                    await obj.wasSet(node, valu)
                else:
                    # We're a tag...
                    valu = node.get(tname)
                    if valu is None:
                        continue
                    await runt.snap.core.runTagAdd(node, name, valu)

                yield node, path

            return
예제 #30
0
    async def set(self, name, valu, init=False):
        '''
        Set a property on the node.

        Args:
            name (str): The name of the property.
            valu (obj): The value of the property.
            init (bool): Set to True to disable read-only enforcement

        Returns:
            (bool): True if the property was changed.
        '''
        if self.snap.readonly:
            mesg = 'Cannot set property in read-only mode.'
            raise s_exc.IsReadOnly(mesg=mesg)

        prop = self.form.prop(name)
        if prop is None:

            if self.snap.strict:
                mesg = f'No property named {name}.'
                raise s_exc.NoSuchProp(mesg=mesg,
                                       name=name,
                                       form=self.form.name)

            await self.snap.warn(f'NoSuchProp: name={name}')
            return False

        if self.form.isrunt:

            if prop.info.get('ro'):
                mesg = 'Cannot set read-only props on runt nodes'
                raise s_exc.IsRuntForm(mesg=mesg,
                                       form=self.form.full,
                                       prop=name,
                                       valu=valu)

            await self.snap.core.runRuntPropSet(self, prop, valu)
            return True

        curv = self.props.get(name)

        # normalize the property value...
        try:
            norm, info = prop.type.norm(valu)

        except Exception as e:
            mesg = f'Bad property value: {prop.full}={valu!r}'
            return await self.snap._raiseOnStrict(s_exc.BadTypeValu,
                                                  mesg,
                                                  name=prop.name,
                                                  valu=valu,
                                                  emesg=str(e))

        # do we already have the value?
        if curv == norm:
            return False

        await self.snap.core._callPropSetHook(self, prop, norm)

        if curv is not None and not init:

            if prop.info.get('ro'):

                if self.snap.strict:
                    raise s_exc.ReadOnlyProp(name=prop.full)

                # not setting a set-once prop unless we are init...
                return False

            # check for type specific merging...
            norm = prop.type.merge(curv, norm)
            if curv == norm:
                return False

        props = {prop.name: norm}
        nodeedits = await self.snap.getNodeAdds(self.form,
                                                self.ndef[1],
                                                props,
                                                addnode=False)

        await self.snap.applyNodeEdits(nodeedits)

        return True