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
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))
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)
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
async def _setops(self, name, valu, editatom, init=False): ''' Generate operations to set a property on a node. ''' 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'NoSuchProp: name={name}') return False if self.isrunt: if prop.info.get('ro'): raise s_exc.IsRuntForm( mesg='Cannot set read-only props on runt nodes', form=self.form.full, prop=name, valu=valu) return await self.snap.core.runRuntPropSet(self, prop, valu) 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.BadPropValu, mesg, name=prop.name, valu=valu, emesg=str(e)) # do we already have the value? if curv == norm: return False 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 sops = prop.getSetOps(self.buid, norm) editatom.sops.extend(sops) # self.props[prop.name] = norm editatom.npvs.append((self, prop, curv, norm)) # do we have any auto nodes to add? auto = self.snap.model.form(prop.type.name) if auto is not None: buid = s_common.buid((auto.name, norm)) await self.snap._addNodeFnibOps((auto, norm, info, buid), editatom) # does the type think we have special auto nodes to add? # ( used only for adds which do not meet the above block ) for autoname, autovalu in info.get('adds', ()): auto = self.snap.model.form(autoname) autonorm, autoinfo = auto.type.norm(autovalu) buid = s_common.buid((auto.name, autonorm)) await self.snap._addNodeFnibOps((auto, autovalu, autoinfo, buid), editatom) # do we need to set any sub props? subs = info.get('subs') if subs is not None: for subname, subvalu in subs.items(): full = prop.name + ':' + subname subprop = self.form.prop(full) if subprop is None: continue await self._setops(full, subvalu, editatom, init=init) return True