tsnmp is a package-first SNMP runtime. Start with numeric OIDs and no bundle;
add compiled JSON only when you need symbolic resolution or better display metadata.
pip install trishul-snmp
For local development:
pip install -e ".[dev]"
Requires Python >=3.10.
Current main-branch baseline:
get, get_next, get_bulk, walk, bulkwalkDeliberately out of scope:
trishul-smisetThis works with no bundle loaded.
import asyncio
from trishul_snmp import V2cManager
async def main() -> None:
async with V2cManager(host="10.0.0.10", community="public") as manager:
response = await manager.get("1.3.6.1.2.1.1.3.0")
for varbind in response.varbinds:
print(varbind.oid_str, varbind.value_type, varbind.display_value)
asyncio.run(main())
If you already have compiled JSON artifacts, load them and use symbolic names.
import asyncio
from trishul_snmp import V2cManager, load_bundle
bundle = load_bundle("./IF-MIB.json")
async def main() -> None:
async with V2cManager(
host="10.0.0.10",
community="public",
bundle=bundle,
) as manager:
response = await manager.get("IF-MIB::ifDescr.1")
for varbind in response.varbinds:
print(varbind.display_name, "=", varbind.display_value)
asyncio.run(main())
import asyncio
from trishul_snmp import V2cManager, load_bundle
bundle = load_bundle("./mibs-json")
async def main() -> None:
async with V2cManager(
host="10.0.0.10",
community="public",
bundle=bundle,
) as manager:
rows = await manager.walk("IF-MIB::ifTable")
for row in rows:
print(row.display_name, "=", row.display_value)
asyncio.run(main())
import asyncio
from trishul_snmp import IntegerValue, V2cNotifier, load_bundle
bundle = load_bundle("./mibs-json")
async def main() -> None:
async with V2cNotifier(
host="10.0.0.20",
community="public",
bundle=bundle,
) as notifier:
await notifier.send_trap(
"IF-MIB::linkDown",
varbinds=[("IF-MIB::ifIndex.7", IntegerValue(7))],
uptime=123,
)
asyncio.run(main())
import asyncio
from trishul_snmp import IntegerValue, OctetStringValue, V2cResponder, load_bundle
bundle = load_bundle("./mibs-json")
async def main() -> None:
async with V2cResponder(
host="127.0.0.1",
port=1161,
communities=["public"],
bundle=bundle,
) as responder:
responder.set_objects(
[
("IF-MIB::ifIndex.1", IntegerValue(1)),
("IF-MIB::ifDescr.1", OctetStringValue(b"eth0")),
]
)
await responder.serve_forever()
asyncio.run(main())
No SNMP traffic is involved here.
from trishul_snmp import load_bundle
bundle = load_bundle("./mibs-json")
print(bundle.translate("IF-MIB::ifDescr.7"))
print(bundle.translate("1.3.6.1.2.1.2.2.1.2.7"))
Offline translation:
tsmi or provide an equivalent supported JSON artifact.load_bundle().tsnmp validates and normalizes the bundle.Live numeric GET with no bundle:
manager.get() with numeric OIDs.display_value is still available without symbolic metadata.Live symbolic walk with a bundle:
load_bundle().manager.walk("IF-MIB::ifTable").GETBULK by default or GETNEXT when requested.Live notification send:
send_trap() or send_inform() on V2cNotifier.tsnmp auto-populates sysUpTime.0 and snmpTrapOID.0 unless you override them.Responder simulation:
V2cResponder with either the default in-memory source or a callback-backed source.serve() or serve_forever() to answer GET, GET_NEXT, and GET_BULK.noSuchObject; end-of-tree lookups return endOfMibView.tsnmp/tsmi split, supported inputs, and current pairing status