1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
|
#
# This file is part of pysnmp software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://www.pysnmp.com/pysnmp/license.html
#
from typing import TYPE_CHECKING
from pysnmp import error
if TYPE_CHECKING:
from pysnmp.entity.engine import SnmpEngine
class MetaObserver:
r"""This is a simple facility for exposing internal SNMP Engine working details to pysnmp applications.
These details are basically local scope variables at a fixed point of
execution. Two modes of operations are offered:
1. Consumer: app can request an execution point context by execution point ID.
2. Provider: app can register its callback function (and context) to be invoked
once execution reaches specified point. All local scope variables
will be passed to the callback as in #1.
It's important to realize that execution context is only guaranteed
to exist to functions that are at the same or deeper level of invocation
relative to execution point specified.
"""
def __init__(self):
"""Create a meta observer instance."""
self.__observers = {}
self.__contexts = {}
self.__execpoints = {}
def register_observer(self, cbFun, *execpoints, **kwargs):
"""Register a callback function to be invoked at specified execution points.
Args:
cbFun (callable): Callback function to be invoked.
execpoints (str): Execution point ID(s) to trigger the callback.
cbCtx (object): Arbitrary object to be passed to the callback.
Raises:
PySnmpError: If observer is already registered.
"""
if cbFun in self.__contexts:
raise error.PySnmpError("duplicate observer %s" % cbFun)
else:
self.__contexts[cbFun] = kwargs.get("cbCtx")
for execpoint in execpoints:
if execpoint not in self.__observers:
self.__observers[execpoint] = []
self.__observers[execpoint].append(cbFun)
def unregister_observer(self, cbFun=None):
"""Unregister a callback function.
Args:
cbFun (callable): Callback function to be unregistered. If not specified,
all observers will be unregistered.
"""
if cbFun is None:
self.__observers.clear()
self.__contexts.clear()
else:
for execpoint in dict(self.__observers):
if cbFun in self.__observers[execpoint]:
self.__observers[execpoint].remove(cbFun)
if not self.__observers[execpoint]:
del self.__observers[execpoint]
def store_execution_context(self, snmpEngine: "SnmpEngine", execpoint, variables):
"""Store execution context at specified execution point.
Args:
execpoint (str): Execution point ID.
variables (dict): Local scope variables to store.
"""
self.__execpoints[execpoint] = variables
if execpoint in self.__observers:
for cbFun in self.__observers[execpoint]:
cbFun(snmpEngine, execpoint, variables, self.__contexts[cbFun])
def clear_execution_context(self, snmpEngine: "SnmpEngine", *execpoints):
"""Clear execution context at specified execution points.
Args:
execpoints (str): Execution point ID(s) to clear.
"""
if execpoints:
for execpoint in execpoints:
del self.__execpoints[execpoint]
else:
self.__execpoints.clear()
def get_execution_context(self, execpoint):
"""Retrieve execution context at specified execution point.
Args:
execpoint (str): Execution point ID.
Returns:
dict: Local scope variables at the specified execution point.
"""
return self.__execpoints[execpoint]
|