Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 38 additions & 31 deletions synapse/lib/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -2649,6 +2649,9 @@ async def getPivsIn(self, runt, node, path):
async for pivo, link in runt.view.getNdefRefs(node.ndef):
yield pivo, path.fork(pivo, link)

async for pivo, link in runt.view.getNodePropRefs(node.ndef):
yield pivo, path.fork(pivo, link)

for prop, valu in node.getProps().items():
pdef = (f'{name}:{prop}', valu)
async for pivo, link in runt.view.getNodePropRefs(pdef):
Expand Down Expand Up @@ -2679,7 +2682,7 @@ class FormPivot(PivotOper):
def pivogenr(self, runt, prop, virts=None):

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

async def pgenr(node, strict=True):
link = {'type': 'prop', 'prop': prop.name, 'reverse': True}
Expand All @@ -2691,7 +2694,7 @@ async def pgenr(node, strict=True):
# plain old pivot...
async def pgenr(node, strict=True):
if prop.type.isarray:
if isinstance(prop.type.arraytype, s_types.Ndef):
if isinstance(prop.type.arraytype, (s_types.Ndef, s_types.NodeProp)):
ngenr = runt.view.nodesByPropArray(prop.full, '=', node.ndef, norm=False, virts=virts)
else:
norm = prop.arraytypehash is not node.form.typehash
Expand Down Expand Up @@ -2784,26 +2787,28 @@ async def pgenr(node, strict=True):
async for pivo in runt.view.nodesByPropValu(destform.name, '=', refselem, norm=False):
yield pivo, link

for refsname in refs.get('ndef'):
for key in ('ndef', 'nodeprop'):
for refsname in refs.get(key):

found = True
found = True

refsvalu = node.get(refsname)
if refsvalu is not None and refsvalu[0] == destform.name:
pivo = await runt.view.getNodeByNdef(refsvalu)
if pivo is not None:
yield pivo, {'type': 'prop', 'prop': refsname}
refsvalu = node.get(refsname)
if refsvalu is not None and refsvalu[0] == destform.name:
pivo = await runt.view.getNodeByNdef(refsvalu)
if pivo is not None:
yield pivo, {'type': 'prop', 'prop': refsname}

for refsname in refs.get('ndefarray'):
for key in ('ndefarray', 'nodeproparray'):
for refsname in refs.get(key):

found = True
found = True

if (refsvalu := node.get(refsname)) is not None:
link = {'type': 'prop', 'prop': refsname}
for aval in refsvalu:
if aval[0] == destform.name:
if (pivo := await runt.view.getNodeByNdef(aval)) is not None:
yield pivo, link
if (refsvalu := node.get(refsname)) is not None:
link = {'type': 'prop', 'prop': refsname}
for aval in refsvalu:
if aval[0] == destform.name:
if (pivo := await runt.view.getNodeByNdef(aval)) is not None:
yield pivo, link

#########################################################################
# reverse "-> form" pivots (ie inet:fqdn -> inet:dns:a)
Expand Down Expand Up @@ -2836,23 +2841,25 @@ async def pgenr(node, strict=True):
yield pivo, link

# "reverse" ndef references...
for refsname in refs.get('ndef'):
for key in ('ndef', 'nodeprop'):
for refsname in refs.get(key):

found = True
found = True

refsprop = destform.props.get(refsname)
link = {'type': 'prop', 'prop': refsname, 'reverse': True}
async for pivo in runt.view.nodesByPropValu(refsprop.full, '=', node.ndef, norm=False):
yield pivo, link
refsprop = destform.props.get(refsname)
link = {'type': 'prop', 'prop': refsname, 'reverse': True}
async for pivo in runt.view.nodesByPropValu(refsprop.full, '=', node.ndef, norm=False):
yield pivo, link

for refsname in refs.get('ndefarray'):
for key in ('ndefarray', 'nodeproparray'):
for refsname in refs.get(key):

found = True
found = True

refsprop = destform.props.get(refsname)
link = {'type': 'prop', 'prop': refsname, 'reverse': True}
async for pivo in runt.view.nodesByPropArray(refsprop.full, '=', node.ndef, norm=False):
yield pivo, link
refsprop = destform.props.get(refsname)
link = {'type': 'prop', 'prop': refsname, 'reverse': True}
async for pivo in runt.view.nodesByPropArray(refsprop.full, '=', node.ndef, norm=False):
yield pivo, link

if strict and not found:
mesg = f'No pivot found for {node.form.name} -> {destform.name}.'
Expand Down Expand Up @@ -3020,7 +3027,7 @@ async def pgenr(node, srcname, srctype, valu):

# pivoting from an array prop to a non-array prop needs an extra loop
if srctype.isarray and not prop.type.isarray:
if isinstance(srctype.arraytype, s_types.Ndef) and prop.isform:
if isinstance(srctype.arraytype, (s_types.Ndef, s_types.NodeProp)) and prop.isform:
for aval in valu:
if aval[0] != prop.form.name:
continue
Expand All @@ -3036,7 +3043,7 @@ async def pgenr(node, srcname, srctype, valu):

return

if isinstance(srctype, s_types.Ndef) and prop.isform:
if isinstance(srctype, (s_types.Ndef, s_types.NodeProp)) and prop.isform:
if valu[0] != prop.form.name:
return

Expand Down
41 changes: 41 additions & 0 deletions synapse/tests/test_lib_layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2410,6 +2410,47 @@ async def test_layer_nodeprop_indexes(self):
self.len(4, await core.nodes('test:str=faz -> *', opts=viewopts2))
self.len(4, await core.nodes('test:str=faz :pdefs -> *', opts=viewopts2))

await core.nodes('[ test:int=3 (test:str=ndef1 test:str=ndef2 :baz=(test:int, 3)) ]')
nodes = await core.nodes('test:int=3 <- *')
self.len(2, nodes)
self.eq(nodes[0].ndef, ('test:str', 'ndef1'))
self.eq(nodes[1].ndef, ('test:str', 'ndef2'))

nodes = await core.nodes('test:int=3 -> test:str:baz')
self.len(2, nodes)
self.eq(nodes[0].ndef, ('test:str', 'ndef1'))
self.eq(nodes[1].ndef, ('test:str', 'ndef2'))

nodes = await core.nodes('test:str=ndef1 -> test:int')
self.len(1, nodes)
self.eq(nodes[0].ndef, ('test:int', 3))

nodes = await core.nodes('test:str=ndef1 :baz -> test:int')
self.len(1, nodes)
self.eq(nodes[0].ndef, ('test:int', 3))

await core.nodes('[ test:str=ndefarry1 test:str=ndefarry2 :pdefs=((test:int, 3),) ]')

nodes = await core.nodes('test:int=3 -> test:str:pdefs')
self.len(2, nodes)
self.eq(nodes[0].ndef, ('test:str', 'ndefarry1'))
self.eq(nodes[1].ndef, ('test:str', 'ndefarry2'))

nodes = await core.nodes('test:int=3 -> test:str')
self.len(4, nodes)
self.eq(nodes[0].ndef, ('test:str', 'ndef1'))
self.eq(nodes[1].ndef, ('test:str', 'ndef2'))
self.eq(nodes[2].ndef, ('test:str', 'ndefarry1'))
self.eq(nodes[3].ndef, ('test:str', 'ndefarry2'))

nodes = await core.nodes('test:str=ndefarry1 -> test:int')
self.len(1, nodes)
self.eq(nodes[0].ndef, ('test:int', 3))

nodes = await core.nodes('test:str=ndefarry1 :pdefs -> test:int')
self.len(1, nodes)
self.eq(nodes[0].ndef, ('test:int', 3))

async def test_layer_virt_indexes(self):

async with self.getTestCore() as core:
Expand Down
12 changes: 8 additions & 4 deletions synapse/tests/test_model_language.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,22 @@ async def test_model_language(self):
:output:lang={[ lang:language=({"code": "en.us"}) ]}
:desc=Greetings
:engine=*
lang:phrase=Hola
]''')
self.len(1, nodes)
self.len(2, nodes)

self.eq(nodes[0].get('input'), ('lang:phrase', 'Hola'))
self.eq(nodes[0].get('output'), 'Hi')
self.eq(nodes[0].get('input:lang'), '0eae93b46d1c1951525424769faa5205')
self.eq(nodes[0].get('output:lang'), 'a8eeae81da6c305c9cf6e4962bd106b2')
self.eq(nodes[0].get('desc'), 'Greetings')

# FIXME nodeprop indexing...
# self.len(1, await core.nodes('lang:phrase <- *'))
# self.len(1, await core.nodes('lang:translation -> lang:phrase'))
self.len(1, await core.nodes('lang:phrase <- *'))
self.len(1, await core.nodes('lang:translation -> lang:phrase'))
self.len(1, await core.nodes('lang:phrase -> lang:translation'))

self.len(1, await core.nodes('lang:translation :input -> *'))
self.len(1, await core.nodes('lang:translation :input -> lang:phrase'))

self.len(1, await core.nodes('lang:translation -> it:software'))
self.len(2, await core.nodes('lang:translation -> lang:language'))
Expand Down