puresnmp.util module
Collection of utility functions for the puresnmp package.
- class puresnmp.util.BulkResult(scalars: Dict[ObjectIdentifier, Any], listing: Dict[ObjectIdentifier, Any])
Bases:
object
A representation for results of a “bulk” request.
These requests get both “non-repeating values” (scalars) and “repeating values” (lists). This wrapper makes these terms a bit friendlier to use.
- listing: Dict[ObjectIdentifier, Any]
A mapping from object-identifiers to “walk” results below those OIDs
- scalars: Dict[ObjectIdentifier, Any]
A mapping from object-identifiers to scalar (single) values for those OIDs
- class puresnmp.util.TDigestable(*args, **kwargs)
Bases:
Protocol
Typing protocol copied from https://github.com/python/typeshed/blob/569fcea637023b3df2fe45c6f08c26037bfa6a74/stdlib/hashlib.pyi#L5
- copy() TDigestable
- class puresnmp.util.WalkRow(value: Any, unfinished: bool)
Bases:
object
A wrapper around an SNMP Walk item.
This also keeps track whether this walk result should be considered the last row or not.
- puresnmp.util.generate_engine_id_ip(pen: int, ip: IPv4Address | IPv6Address) bytes
Generates a valid SNMP Engine ID using a private enterprise number and an ip-address.
>>> from ipaddress import ip_address >>> generate_engine_id_ip(696, ip_address("192.0.2.1")) b'\x80\x00\x02\xb8\x01\xc0\x00\x02\x01'
See also
- Engine ID structure
ASN.1 definition for engine-id encoding
- Engine ID types
List of valid engine-id variants
- PEN list
List of publicly registered private enterprise numbers
- puresnmp.util.generate_engine_id_mac(pen: int, mac_address: str) bytes
Generates a valid SNMP Engine ID using a private enterprise number and a mac-address.
>>> generate_engine_id_mac(696, "01:02:03:04:05:06") b'\x80\x00\x02\xb8\x03\x01\x02\x03\x04\x05\x06'
See also
- Engine ID structure
ASN.1 definition for engine-id encoding
- Engine ID types
List of valid engine-id variants
- PEN list
List of publicly registered private enterprise numbers
- puresnmp.util.generate_engine_id_octets(pen: int, octets: bytes) bytes
Generates a valid SNMP Engine ID using a private enterprise number and a custom byte-string (no longer than 27 bytes)
>>> generate_engine_id_octets(696, b"hello") b'\x80\x00\x02\xb8\x05hello'
See also
- Engine ID structure
ASN.1 definition for engine-id encoding
- Engine ID types
List of valid engine-id variants
- PEN list
List of publicly registered private enterprise numbers
- puresnmp.util.generate_engine_id_text(pen: int, text: str) bytes
Generates a valid SNMP Engine ID using a private enterprise number and a custom text (no longer than 27 characters).
>>> generate_engine_id_text(696, "hello") b'\x80\x00\x02\xb8\x04hello'
See also
- Engine ID structure
ASN.1 definition for engine-id encoding
- Engine ID types
List of valid engine-id variants
- PEN list
List of publicly registered private enterprise numbers
- puresnmp.util.get_request_id() int
Generates a SNMP request ID.
This returns a simple integer used to validate if a given response matches with the given request.
- puresnmp.util.get_unfinished_walk_oids(grouped_oids: Dict[ObjectIdentifier, List[VarBind]]) List[Tuple[ObjectIdentifier, WalkRow]]
Create a list of OIDs which still have subsequent values in a “walk” operation
- Parameters:
grouped_oids – A dictionary containing VarBinds as values. The keys are the base OID of those VarBinds as requested by the user. We need to keep track of the base to be able to tell when a walk over OIDs is finished (that is, when we hit the first OID outside the base).
- puresnmp.util.group_varbinds(varbinds: List[VarBind], effective_roots: List[ObjectIdentifier], user_roots: List[ObjectIdentifier] | None = None) Dict[ObjectIdentifier, List[VarBind]]
Takes a list of varbinds and a list of base OIDs and returns a mapping from those base IDs to lists of varbinds.
Varbinds returned from a walk operation which targets multiple OIDs is returned as “interleaved” list. This functions extracts these interleaved items into a more usable dictionary.
>>> from x690.types import Integer >>> result = group_varbinds( ... [ ... VarBind(ObjectIdentifier("1.1.1"), Integer(1)), ... VarBind(ObjectIdentifier("2.2.2"), Integer(1)), ... VarBind(ObjectIdentifier("1.1.2"), Integer(1)), ... VarBind(ObjectIdentifier("2.2.3"), Integer(1)), ... ], ... [ ... ObjectIdentifier("1.1"), ... ObjectIdentifier("2.2"), ... ], ... ) >>> sorted(result.keys()) [ObjectIdentifier('1.1'), ObjectIdentifier('2.2')] >>> result[ObjectIdentifier("1.1")] [VarBind(oid=ObjectIdentifier('1.1.1'), value=Integer(1)), VarBind(oid=ObjectIdentifier('1.1.2'), value=Integer(1))] >>> result[ObjectIdentifier("2.2")] [VarBind(oid=ObjectIdentifier('2.2.2'), value=Integer(1)), VarBind(oid=ObjectIdentifier('2.2.3'), value=Integer(1))]
- Parameters:
varbinds – A list of VarBind instances.
effective_roots – The list of OIDs that were requested from the SNMP agent.
user_roots – The set of VarBind instances that were requested by the user. This is used internally for walk requests. On each request following the first, the requested OIDs will differ from the OIDs requested by the user. This list will keep track of the original OIDs to determine when the walk needs to terminate.
- puresnmp.util.iter_namespace(ns_pkg: ModuleType) Generator[ModuleInfo, None, None]
Iterates over modules inside the given namespace
- puresnmp.util.localise_key(credentials: V3, engine_id: bytes) bytes
Derive a localised key from the user-credentials.
This follows the logic as dictated by RFC 3414 melding the recipient engine-id with the user-credentials into a kay used for de-/en-cryption of packets.
>>> from puresnmp.credentials import V3, Auth, Priv >>> engine_id = b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02" >>> localised = localise_key( ... V3(b"user", Auth(b"maplesyrup", "md5"), Priv(b"privkey", "des")), ... engine_id ... ) >>> localised.hex() '4924c679907476d038b258097995a15c'
- puresnmp.util.password_to_key(hash_implementation: Callable[[bytes], TDigestable], padding_length: int) Callable[[bytes, bytes], bytes]
Create a helper function to convert passwords to SNMP compliant keys according to RFC 3414.
>>> hasher = password_to_key(hashlib.sha1, 20) >>> key = hasher(b"mypasswd", b"target-engine-id") >>> key.hex() '999ec23ca66b9d3f187ab5208840c30b0450b452'
- Parameters:
hash_implementation – A callable that creates an object with a “.digest()” method from a bytes-object. Usable examples are hashlib.md5 and hashlib.sha1
padding_length – The padding length to be used during hashing (as defined in the SNMP rfc)
- Returns:
A callable which can be used to derive an SNMP compliant key from a password.
- puresnmp.util.sync(coro: Awaitable[T]) T
Execute an asyncio corouting in the current event-loop and return the result
>>> async def foo(): ... return "hello" >>> sync(foo()) 'hello'
Warning
This is intended for debugging and testing. If possible you should use your own async environment.
- puresnmp.util.tablify(varbinds: Iterable[VarBind], num_base_nodes: int = 0, base_oid: str = '', _rowtype: Type[TTableRow] = typing.Dict[str, typing.Any]) List[TTableRow]
Converts a list of varbinds into a table-like structure. num_base_nodes can be used for table which row-ids consist of multiple OID tree nodes. By default, the last node is considered the row ID, and the second-last is the column ID. Example:
By default, for the table-cell at OID
1.2.3.4.5
,4
is the column index and5
is the row index.Using
num_base_nodes=2
will only use the first two nodes (1.2
) as table-identifier, so3
becomes the column index, and4.5
becomes the row index.The output should not be considered ordered in any way. If you need it sorted, you must sort it after retrieving the table from this function!
Each element of the output is a dictionary where each key is the column index. By default the index
0
will be added, representing the row ID.Example:
>>> data = [ ... (ObjectIdentifier('1.2.1.1'), 'row 1 col 1'), ... (ObjectIdentifier('1.2.1.2'), 'row 2 col 1'), ... (ObjectIdentifier('1.2.2.1'), 'row 1 col 2'), ... (ObjectIdentifier('1.2.2.2'), 'row 2 col 2'), ... ] >>> tablify(data) [{'0': '1', '1': 'row 1 col 1', '2': 'row 1 col 2'}, {'0': '2', '1': 'row 2 col 1', '2': 'row 2 col 2'}]
Example with longer row ids (using the first two as table identifiers):
>>> data = [ ... (ObjectIdentifier('1.2.1.5.10'), 'row 5.10 col 1'), ... (ObjectIdentifier('1.2.1.6.10'), 'row 6.10 col 1'), ... (ObjectIdentifier('1.2.2.5.10'), 'row 5.10 col 2'), ... (ObjectIdentifier('1.2.2.6.10'), 'row 6.10 col 2'), ... ] >>> tablify(data, num_base_nodes=2) [{'0': '5.10', '1': 'row 5.10 col 1', '2': 'row 5.10 col 2'}, {'0': '6.10', '1': 'row 6.10 col 1', '2': 'row 6.10 col 2'}]
- puresnmp.util.validate_response_id(request_id: int, response_id: int) None
Compare request and response IDs and raise an appropriate error.
Raises an appropriate error if the IDs differ. Otherwise returns
This helper method ensures we’re always returning the same exception type on invalid response IDs.