From 48c2b5a69711cceb1d2f8a7f55a85d1712976cf0 Mon Sep 17 00:00:00 2001 From: Adam Cecile Date: Tue, 12 Sep 2023 16:49:27 +0200 Subject: [PATCH 1/2] Fix asyncio hlapi double awaitable returns (Fix #19) Commit 67563a19f028d371efa9683f60eb52908a292b86 introduced a bug while converting legacy asyncio API to new "async def" style. Previous methods where NOT decorated with @asyncio.coroutine and returned a Future object being awaitable. Updated code still returns a Future object but adds async keyword to function definition leading to awaitable function returning awaitable Future. That breaks existing API. --- pysnmp/hlapi/asyncio/cmdgen.py | 20 ++++++++------------ pysnmp/hlapi/asyncio/ntforg.py | 5 ++--- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/pysnmp/hlapi/asyncio/cmdgen.py b/pysnmp/hlapi/asyncio/cmdgen.py index 6d93d8f85..b7cca28ce 100644 --- a/pysnmp/hlapi/asyncio/cmdgen.py +++ b/pysnmp/hlapi/asyncio/cmdgen.py @@ -112,14 +112,13 @@ async def getCmd(snmpEngine, authData, transportTarget, contextData, >>> from pysnmp.hlapi.asyncio import * >>> >>> async def run(): - ... result_get = await getCmd( + ... errorIndication, errorStatus, errorIndex, varBinds = await getCmd( ... SnmpEngine(), ... CommunityData('public'), ... UdpTransportTarget(('demo.pysnmp.com', 161)), ... ContextData(), ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)) ... ) - ... errorIndication, errorStatus, errorIndex, varBinds = await result_get ... print(errorIndication, errorStatus, errorIndex, varBinds) >>> >>> asyncio.run(run()) @@ -156,7 +155,7 @@ def __cbFun(snmpEngine, sendRequestHandle, vbProcessor.makeVarBinds(snmpEngine, varBinds), __cbFun, (options.get('lookupMib', True), future) ) - return future + return await future async def setCmd(snmpEngine, authData, transportTarget, contextData, @@ -218,14 +217,13 @@ async def setCmd(snmpEngine, authData, transportTarget, contextData, >>> from pysnmp.hlapi.asyncio import * >>> >>> async def run(): - ... set_result = await setCmd( + ... errorIndication, errorStatus, errorIndex, varBinds = await setCmd( ... SnmpEngine(), ... CommunityData('public'), ... UdpTransportTarget(('demo.pysnmp.com', 161)), ... ContextData(), ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0), 'Linux i386') ... ) - ... errorIndication, errorStatus, errorIndex, varBinds = await set_result ... print(errorIndication, errorStatus, errorIndex, varBinds) >>> >>> asyncio.run(run()) @@ -262,7 +260,7 @@ def __cbFun(snmpEngine, sendRequestHandle, vbProcessor.makeVarBinds(snmpEngine, varBinds), __cbFun, (options.get('lookupMib', True), future) ) - return future + return await future async def nextCmd(snmpEngine, authData, transportTarget, contextData, @@ -328,14 +326,13 @@ async def nextCmd(snmpEngine, authData, transportTarget, contextData, >>> from pysnmp.hlapi.asyncio import * >>> >>> async def run(): - ... next_result = await nextCmd( + ... errorIndication, errorStatus, errorIndex, varBinds = await nextCmd( ... SnmpEngine(), ... CommunityData('public'), ... UdpTransportTarget(('demo.pysnmp.com', 161)), ... ContextData(), ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')) ... ) - ... errorIndication, errorStatus, errorIndex, varBinds = await next_result ... print(errorIndication, errorStatus, errorIndex, varBinds) >>> >>> asyncio.run(run()) @@ -374,7 +371,7 @@ def __cbFun(snmpEngine, sendRequestHandle, vbProcessor.makeVarBinds(snmpEngine, varBinds), __cbFun, (options.get('lookupMib', True), future) ) - return future + return await future async def bulkCmd(snmpEngine, authData, transportTarget, contextData, @@ -468,7 +465,7 @@ async def bulkCmd(snmpEngine, authData, transportTarget, contextData, >>> from pysnmp.hlapi.asyncio import * >>> >>> async def run(): - ... result_bulk = await bulkCmd( + ... errorIndication, errorStatus, errorIndex, varBinds = await bulkCmd( ... SnmpEngine(), ... CommunityData('public'), ... UdpTransportTarget(('demo.pysnmp.com', 161)), @@ -476,7 +473,6 @@ async def bulkCmd(snmpEngine, authData, transportTarget, contextData, ... 0, 2, ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')) ... ) - ... errorIndication, errorStatus, errorIndex, varBinds = await result_bulk ... print(errorIndication, errorStatus, errorIndex, varBinds) >>> >>> asyncio.run(run()) @@ -515,4 +511,4 @@ def __cbFun(snmpEngine, sendRequestHandle, vbProcessor.makeVarBinds(snmpEngine, varBinds), __cbFun, (options.get('lookupMib', True), future) ) - return future + return await future diff --git a/pysnmp/hlapi/asyncio/ntforg.py b/pysnmp/hlapi/asyncio/ntforg.py index 5b5915aac..e52687b82 100644 --- a/pysnmp/hlapi/asyncio/ntforg.py +++ b/pysnmp/hlapi/asyncio/ntforg.py @@ -101,14 +101,13 @@ async def sendNotification(snmpEngine, authData, transportTarget, contextData, >>> from pysnmp.hlapi.asyncio import * >>> >>> async def run(): - ... send_result = await sendNotification( + ... errorIndication, errorStatus, errorIndex, varBinds = await sendNotification( ... SnmpEngine(), ... CommunityData('public'), ... UdpTransportTarget(('demo.pysnmp.com', 162)), ... ContextData(), ... 'trap', ... NotificationType(ObjectIdentity('IF-MIB', 'linkDown'))) - ... errorIndication, errorStatus, errorIndex, varBinds = await send_result ... print(errorIndication, errorStatus, errorIndex, varBinds) ... >>> asyncio.run(run()) @@ -159,4 +158,4 @@ def __trapFun(future): loop = asyncio.get_event_loop() loop.call_soon(__trapFun, future) - return future + return await future From 0569329e22b6d41da9fa5a59eb8d430959c5a024 Mon Sep 17 00:00:00 2001 From: Lex Li Date: Tue, 12 Sep 2023 18:28:17 -0400 Subject: [PATCH 2/2] Updated examples. --- .../asyncio/agent/ntforg/default-v1-trap.py | 4 +-- .../ntforg/multiple-notifications-at-once.py | 3 +-- .../hlapi/asyncio/agent/ntforg/v3-inform.py | 4 +-- .../cmdgen/custom-asn1-mib-search-path.py | 3 +-- .../asyncio/manager/cmdgen/getbulk-to-eom.py | 4 +-- .../cmdgen/multiple-sequential-queries.py | 3 +-- .../hlapi/asyncio/manager/cmdgen/send-trap.py | 26 +++++++++++++++++++ .../asyncio/manager/cmdgen/usm-sha-aes128.py | 3 +-- pysnmp/hlapi/asyncio/slim.py | 16 +++--------- 9 files changed, 39 insertions(+), 27 deletions(-) create mode 100644 examples/hlapi/asyncio/manager/cmdgen/send-trap.py diff --git a/examples/hlapi/asyncio/agent/ntforg/default-v1-trap.py b/examples/hlapi/asyncio/agent/ntforg/default-v1-trap.py index 6f1326b0e..40ee8e990 100644 --- a/examples/hlapi/asyncio/agent/ntforg/default-v1-trap.py +++ b/examples/hlapi/asyncio/agent/ntforg/default-v1-trap.py @@ -26,7 +26,7 @@ async def run(): snmpEngine = SnmpEngine() - trap_result = await sendNotification( + errorIndication, errorStatus, errorIndex, varBinds = await sendNotification( snmpEngine, CommunityData('public', mpModel=0), UdpTransportTarget(('demo.pysnmp.com', 162)), @@ -37,7 +37,7 @@ async def run(): ("1.3.6.1.2.1.1.1.0", OctetString("my system")), ), ) - errorIndication, errorStatus, errorIndex, varBinds = await trap_result + if errorIndication: print(errorIndication) diff --git a/examples/hlapi/asyncio/agent/ntforg/multiple-notifications-at-once.py b/examples/hlapi/asyncio/agent/ntforg/multiple-notifications-at-once.py index 3e863dcf8..4b6cc1022 100644 --- a/examples/hlapi/asyncio/agent/ntforg/multiple-notifications-at-once.py +++ b/examples/hlapi/asyncio/agent/ntforg/multiple-notifications-at-once.py @@ -28,7 +28,7 @@ async def sendone(snmpEngine, hostname, notifyType): - trap_result = await sendNotification( + errorIndication, errorStatus, errorIndex, varBinds = await sendNotification( snmpEngine, CommunityData("public", tag=hostname), UdpTransportTarget((hostname, 162), tagList=hostname), @@ -39,7 +39,6 @@ async def sendone(snmpEngine, hostname, notifyType): ), ) - (errorIndication, errorStatus, errorIndex, varBinds) = await trap_result if errorIndication: print(errorIndication) elif errorStatus: diff --git a/examples/hlapi/asyncio/agent/ntforg/v3-inform.py b/examples/hlapi/asyncio/agent/ntforg/v3-inform.py index b6b4a1c8a..1d7efd3c1 100644 --- a/examples/hlapi/asyncio/agent/ntforg/v3-inform.py +++ b/examples/hlapi/asyncio/agent/ntforg/v3-inform.py @@ -18,7 +18,7 @@ from pysnmp.hlapi.asyncio.transport import UdpTransportTarget async def run(): - iterator = await sendNotification( + errorIndication, errorStatus, errorIndex, varBinds = await sendNotification( SnmpEngine(), UsmUserData('usr-md5-des', 'authkey1', 'privkey1'), UdpTransportTarget(('demo.pysnmp.com', 162)), @@ -33,8 +33,6 @@ async def run(): ) ) - errorIndication, errorStatus, errorIndex, varBinds = await iterator - if errorIndication: print(errorIndication) diff --git a/examples/hlapi/asyncio/manager/cmdgen/custom-asn1-mib-search-path.py b/examples/hlapi/asyncio/manager/cmdgen/custom-asn1-mib-search-path.py index 840befcc3..40b951f2c 100644 --- a/examples/hlapi/asyncio/manager/cmdgen/custom-asn1-mib-search-path.py +++ b/examples/hlapi/asyncio/manager/cmdgen/custom-asn1-mib-search-path.py @@ -20,7 +20,7 @@ async def run(): snmpEngine = SnmpEngine() - get_result = await getCmd( + errorIndication, errorStatus, errorIndex, varBinds = await getCmd( snmpEngine, CommunityData('public'), UdpTransportTarget(('demo.pysnmp.com', 161)), @@ -29,7 +29,6 @@ async def run(): 'https://mibs.pysnmp.com/asn1/@mib@')) ) - errorIndication, errorStatus, errorIndex, varBinds = await get_result if errorIndication: print(errorIndication) elif errorStatus: diff --git a/examples/hlapi/asyncio/manager/cmdgen/getbulk-to-eom.py b/examples/hlapi/asyncio/manager/cmdgen/getbulk-to-eom.py index d27429941..f0d321271 100644 --- a/examples/hlapi/asyncio/manager/cmdgen/getbulk-to-eom.py +++ b/examples/hlapi/asyncio/manager/cmdgen/getbulk-to-eom.py @@ -24,7 +24,7 @@ async def run(varBinds): snmpEngine = SnmpEngine() while True: - bulk_task = await bulkCmd( + errorIndication, errorStatus, errorIndex, varBindTable = await bulkCmd( snmpEngine, UsmUserData('usr-none-none'), UdpTransportTarget(('demo.pysnmp.com', 161)), @@ -33,7 +33,7 @@ async def run(varBinds): 50, *varBinds ) - (errorIndication, errorStatus, errorIndex, varBindTable) = await bulk_task + if errorIndication: print(errorIndication) break diff --git a/examples/hlapi/asyncio/manager/cmdgen/multiple-sequential-queries.py b/examples/hlapi/asyncio/manager/cmdgen/multiple-sequential-queries.py index 50c101e24..d2f836b01 100644 --- a/examples/hlapi/asyncio/manager/cmdgen/multiple-sequential-queries.py +++ b/examples/hlapi/asyncio/manager/cmdgen/multiple-sequential-queries.py @@ -22,7 +22,7 @@ async def getone(snmpEngine, hostname): - result_get = await getCmd( + errorIndication, errorStatus, errorIndex, varBinds = await getCmd( snmpEngine, CommunityData("public"), UdpTransportTarget(hostname), @@ -30,7 +30,6 @@ async def getone(snmpEngine, hostname): ObjectType(ObjectIdentity("SNMPv2-MIB", "sysDescr", 0)), ) - errorIndication, errorStatus, errorIndex, varBinds = await result_get if errorIndication: print(errorIndication) elif errorStatus: diff --git a/examples/hlapi/asyncio/manager/cmdgen/send-trap.py b/examples/hlapi/asyncio/manager/cmdgen/send-trap.py new file mode 100644 index 000000000..52c475476 --- /dev/null +++ b/examples/hlapi/asyncio/manager/cmdgen/send-trap.py @@ -0,0 +1,26 @@ +import asyncio +from pysnmp.hlapi.asyncio import * + +async def run(): + snmpEngine = SnmpEngine() + # Example of how you might update sysUpTime + mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder + sysUpTime, = mibBuilder.importSymbols('__SNMPv2-MIB', 'sysUpTime') + sysUpTime.syntax = TimeTicks(12345) # Set uptime to 12345 + + errorIndication, errorStatus, errorIndex, varBinds = await sendNotification( + snmpEngine, + CommunityData('public', mpModel=0), + UdpTransportTarget(('demo.pysnmp.com', 162)), + ContextData(), + "trap", + NotificationType(ObjectIdentity('NET-SNMP-EXAMPLES-MIB', 'netSnmpExampleNotification')).addVarBinds(ObjectType(ObjectIdentity('NET-SNMP-EXAMPLES-MIB','netSnmpExampleHeartbeatRate'), 1)) + ) + + if errorIndication: + print(errorIndication) + + snmpEngine.transportDispatcher.closeDispatcher() + + +asyncio.run(run()) \ No newline at end of file diff --git a/examples/hlapi/asyncio/manager/cmdgen/usm-sha-aes128.py b/examples/hlapi/asyncio/manager/cmdgen/usm-sha-aes128.py index 835b7115f..00507d3c3 100644 --- a/examples/hlapi/asyncio/manager/cmdgen/usm-sha-aes128.py +++ b/examples/hlapi/asyncio/manager/cmdgen/usm-sha-aes128.py @@ -29,7 +29,7 @@ async def run(): snmpEngine = SnmpEngine() - get_result = await getCmd( + errorIndication, errorStatus, errorIndex, varBinds = await getCmd( snmpEngine, UsmUserData('usr-sha-aes', 'authkey1', 'privkey1', authProtocol=usmHMACSHAAuthProtocol, @@ -38,7 +38,6 @@ async def run(): ContextData(), ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0))) - errorIndication, errorStatus, errorIndex, varBinds = await get_result if errorIndication: print(errorIndication) elif errorStatus: diff --git a/pysnmp/hlapi/asyncio/slim.py b/pysnmp/hlapi/asyncio/slim.py index 857e9d8e3..097373e24 100644 --- a/pysnmp/hlapi/asyncio/slim.py +++ b/pysnmp/hlapi/asyncio/slim.py @@ -105,7 +105,7 @@ async def get(self, communityName, address, port, *varBinds): """ - get_result = await getCmd( + return await getCmd( self.snmpEngine, CommunityData(communityName, mpModel=self.version - 1), UdpTransportTarget((address, port)), @@ -113,8 +113,6 @@ async def get(self, communityName, address, port, *varBinds): *varBinds, ) - return await get_result - async def next(self, communityName, address, port, *varBinds): r"""Creates a generator to perform SNMP GETNEXT query. @@ -180,7 +178,7 @@ async def next(self, communityName, address, port, *varBinds): """ - next_result = await nextCmd( + return await nextCmd( self.snmpEngine, CommunityData(communityName, mpModel=self.version - 1), UdpTransportTarget((address, port)), @@ -188,8 +186,6 @@ async def next(self, communityName, address, port, *varBinds): *varBinds, ) - return await next_result - async def bulk(self, communityName, address, port, nonRepeaters, maxRepetitions, *varBinds): r"""Creates a generator to perform SNMP GETBULK query. @@ -288,7 +284,7 @@ async def bulk(self, communityName, address, port, nonRepeaters, maxRepetitions, version = self.version - 1 if version == 0: raise PySnmpError('Cannot send V2 PDU on V1 session') - bulk_result = await bulkCmd( + return await bulkCmd( self.snmpEngine, CommunityData(communityName, mpModel=version), UdpTransportTarget((address, port)), @@ -298,8 +294,6 @@ async def bulk(self, communityName, address, port, nonRepeaters, maxRepetitions, *varBinds, ) - return await bulk_result - async def set(self, communityName, address, port, *varBinds): r"""Creates a generator to perform SNMP SET query. @@ -361,12 +355,10 @@ async def set(self, communityName, address, port, *varBinds): """ - set_result = await setCmd( + return await setCmd( self.snmpEngine, CommunityData(communityName, mpModel=self.version - 1), UdpTransportTarget((address, port)), ContextData(), *varBinds, ) - - return await set_result