summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorPeter LaFosse <peter@vector35.com>2026-01-16 10:36:58 -0500
committerPeter LaFosse <peter@vector35.com>2026-01-16 11:51:23 -0500
commitdd31558a0a1600342da23e2d0745be01ad19202b (patch)
tree7f04ed5998d798aeb518d4956fac495e2b7c4a1a /python
parentf327d9565f49b047d38bc1a7583e5f4e3776261a (diff)
Add get_metadata() method and make query_metadata() raise KeyError consistently
Introduces a Pythonic get_metadata() method to BinaryView, Function, Project, TypeArchive, and TypeLibrary classes. This method behaves like dict.get(), returning a default value (None by default) when a key doesn't exist, instead of raising a KeyError. Additionally, updates query_metadata() in TypeArchive and TypeLibrary to raise KeyError when a key is not found, making them consistent with BinaryView, Function, and Project. Previously these two classes returned None on missing keys. This breaking change is documented in the method docstrings. This provides a more consistent and Pythonic API for querying metadata across all metadata-supporting classes. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Diffstat (limited to 'python')
-rw-r--r--python/binaryview.py27
-rw-r--r--python/function.py29
-rw-r--r--python/project.py29
-rw-r--r--python/typearchive.py36
-rw-r--r--python/typelibrary.py36
5 files changed, 149 insertions, 8 deletions
diff --git a/python/binaryview.py b/python/binaryview.py
index 491b023c..df534abd 100644
--- a/python/binaryview.py
+++ b/python/binaryview.py
@@ -10330,6 +10330,33 @@ to a the type "tagRECT" found in the typelibrary "winX64common"
raise KeyError(key)
return metadata.Metadata(handle=md_handle).value
+ def get_metadata(self, key: str, default: Any = None) -> 'metadata.MetadataValueType | Any':
+ """
+ `get_metadata` retrieves a metadata value associated with the given key stored in the current BinaryView.
+
+ This method behaves like `dict.get()`:
+ - If the key exists, its metadata value is returned.
+ - If the key does not exist and `default` is not provided, `None` is returned.
+ - If the key does not exist and `default` is provided, `default` is returned.
+
+ :param str key: key to query
+ :param default: value to return if the key does not exist (defaults to None)
+ :rtype: metadata associated with the key or the default value
+ :Example:
+
+ >>> bv.store_metadata("integer", 1337)
+ >>> bv.get_metadata("integer")
+ 1337L
+ >>> bv.get_metadata("missing")
+ None
+ >>> bv.get_metadata("missing", 42)
+ 42
+ """
+ md_handle = core.BNBinaryViewQueryMetadata(self.handle, key)
+ if md_handle is None:
+ return default
+ return metadata.Metadata(handle=md_handle).value
+
def store_metadata(self, key: str, md: metadata.MetadataValueType, isAuto: bool = False) -> None:
"""
`store_metadata` stores an object for the given key in the current BinaryView. Objects stored using
diff --git a/python/function.py b/python/function.py
index 29527f4d..66a8c0dc 100644
--- a/python/function.py
+++ b/python/function.py
@@ -3644,7 +3644,7 @@ class Function:
def query_metadata(self, key: str) -> 'metadata.MetadataValueType':
"""
- `query_metadata` retrieves metadata associated with the given key stored in the current function.
+ `query_metadata` retrieves metadata associated with the given key stored in the current Function.
:param str key: key to query
:rtype: metadata associated with the key
@@ -3654,6 +3654,33 @@ class Function:
raise KeyError(key)
return metadata.Metadata(handle=md_handle).value
+ def get_metadata(self, key: str, default: Any = None) -> 'metadata.MetadataValueType | Any':
+ """
+ `get_metadata` retrieves a metadata value associated with the given key stored in the current Function.
+
+ This method behaves like `dict.get()`:
+ - If the key exists, its metadata value is returned.
+ - If the key does not exist and `default` is not provided, `None` is returned.
+ - If the key does not exist and `default` is provided, `default` is returned.
+
+ :param str key: key to query
+ :param default: value to return if the key does not exist (defaults to None)
+ :rtype: metadata associated with the key or the default value
+ :Example:
+
+ >>> current_function.store_metadata("integer", 1337)
+ >>> current_function.get_metadata("integer")
+ 1337L
+ >>> current_function.get_metadata("missing")
+ None
+ >>> current_function.get_metadata("missing", 42)
+ 42
+ """
+ md_handle = core.BNFunctionQueryMetadata(self.handle, key)
+ if md_handle is None:
+ return default
+ return metadata.Metadata(handle=md_handle).value
+
def remove_metadata(self, key: str) -> None:
"""
`remove_metadata` removes the metadata associated with key from the current function.
diff --git a/python/project.py b/python/project.py
index c3504dd4..ba7cf2d3 100644
--- a/python/project.py
+++ b/python/project.py
@@ -22,7 +22,7 @@ import ctypes
from contextlib import contextmanager
from os import PathLike
-from typing import Callable, List, Optional, Union
+from typing import Any, Callable, List, Optional, Union
import binaryninja
from . import _binaryninjacore as core
@@ -545,6 +545,33 @@ class Project:
raise KeyError(key)
return Metadata(handle=md_handle).value
+ def get_metadata(self, key: str, default: Any = None) -> 'metadata.MetadataValueType | Any':
+ """
+ `get_metadata` retrieves a metadata value associated with the given key stored in the current Project.
+
+ This method behaves like `dict.get()`:
+ - If the key exists, its metadata value is returned.
+ - If the key does not exist and `default` is not provided, `None` is returned.
+ - If the key does not exist and `default` is provided, `default` is returned.
+
+ :param str key: key to query
+ :param default: value to return if the key does not exist (defaults to None)
+ :rtype: metadata associated with the key or the default value
+ :Example:
+
+ >>> current_project.store_metadata("integer", 1337)
+ >>> current_project.get_metadata("integer")
+ 1337L
+ >>> current_project.get_metadata("missing")
+ None
+ >>> current_project.get_metadata("missing", 42)
+ 42
+ """
+ md_handle = core.BNProjectQueryMetadata(self._handle, key)
+ if md_handle is None:
+ return default
+ return Metadata(handle=md_handle).value
+
def store_metadata(self, key: str, value: MetadataValueType) -> bool:
"""
Stores metadata within the project
diff --git a/python/typearchive.py b/python/typearchive.py
index f0c521c8..218589b3 100644
--- a/python/typearchive.py
+++ b/python/typearchive.py
@@ -20,7 +20,7 @@
import ctypes
import traceback
-from typing import Optional, List, Dict, Union, Tuple
+from typing import Any, Optional, List, Dict, Union, Tuple
# Binary Ninja components
import binaryninja
@@ -603,10 +603,13 @@ class TypeArchive:
finally:
core.BNFreeStringList(ids, count.value)
- def query_metadata(self, key: str) -> Optional['metadata.MetadataValueType']:
+ def query_metadata(self, key: str) -> 'metadata.MetadataValueType':
"""
Look up a metadata entry in the archive
+ ..note: As of Binary Ninja 5.3 this API now raises KeyError on failure. Please use `get_metadata`
+ for a non-raising version of the API.
+
:param string key: key to query
:rtype: Metadata associated with the key, if it exists. Otherwise, None
:Example:
@@ -618,7 +621,34 @@ class TypeArchive:
"""
md_handle = core.BNTypeArchiveQueryMetadata(self.handle, key)
if md_handle is None:
- return None
+ raise KeyError(key)
+ return metadata.Metadata(handle=md_handle).value
+
+ def get_metadata(self, key: str, default: Any = None) -> 'metadata.MetadataValueType | Any':
+ """
+ `get_metadata` retrieves a metadata value associated with the given key stored in the current TypeArchive.
+
+ This method behaves like `dict.get()`:
+ - If the key exists, its metadata value is returned.
+ - If the key does not exist and `default` is not provided, `None` is returned.
+ - If the key does not exist and `default` is provided, `default` is returned.
+
+ :param str key: key to query
+ :param default: value to return if the key does not exist (defaults to None)
+ :rtype: metadata associated with the key or the default value
+ :Example:
+
+ >>> ta.store_metadata("integer", 1337)
+ >>> ta.get_metadata("integer")
+ 1337L
+ >>> ta.get_metadata("missing")
+ None
+ >>> ta.get_metadata("missing", 42)
+ 42
+ """
+ md_handle = core.BNTypeArchiveQueryMetadata(self.handle, key)
+ if md_handle is None:
+ return default
return metadata.Metadata(handle=md_handle).value
def store_metadata(self, key: str, md: 'metadata.MetadataValueType') -> None:
diff --git a/python/typelibrary.py b/python/typelibrary.py
index 612375e8..457cbd99 100644
--- a/python/typelibrary.py
+++ b/python/typelibrary.py
@@ -19,7 +19,7 @@
# IN THE SOFTWARE.
import ctypes
-from typing import Optional, List, Dict, Union
+from typing import Any, Optional, List, Dict, Union
import uuid
# Binary Ninja components
@@ -233,12 +233,15 @@ class TypeLibrary:
"""
return core.BNFinalizeTypeLibrary(self.handle)
- def query_metadata(self, key: str) -> Optional['metadata.MetadataValueType']:
+ def query_metadata(self, key: str) -> 'metadata.MetadataValueType':
"""
`query_metadata` retrieves a metadata associated with the given key stored in the type library
:param string key: key to query
:rtype: metadata associated with the key
+ ..note: As of Binary Ninja 5.3 this API now raises KeyError on failure. Please use `get_metadata`
+ for a non-raising version of the API.
+
:Example:
>>> lib.store_metadata("ordinals", {"9": "htons"})
@@ -247,7 +250,34 @@ class TypeLibrary:
"""
md_handle = core.BNTypeLibraryQueryMetadata(self.handle, key)
if md_handle is None:
- return None
+ raise KeyError(key)
+ return metadata.Metadata(handle=md_handle).value
+
+ def get_metadata(self, key: str, default: Any = None) -> 'metadata.MetadataValueType | Any':
+ """
+ `get_metadata` retrieves a metadata value associated with the given key stored in the current BinaryView.
+
+ This method behaves like `dict.get()`:
+ - If the key exists, its metadata value is returned.
+ - If the key does not exist and `default` is not provided, `None` is returned.
+ - If the key does not exist and `default` is provided, `default` is returned.
+
+ :param str key: key to query
+ :param default: value to return if the key does not exist (defaults to None)
+ :rtype: metadata associated with the key or the default value
+ :Example:
+
+ >>> tl.store_metadata("integer", 1337)
+ >>> tl.get_metadata("integer")
+ 1337L
+ >>> tl.get_metadata("missing")
+ None
+ >>> tl.get_metadata("missing", 42)
+ 42
+ """
+ md_handle = core.BNTypeLibraryQueryMetadata(self.handle, key)
+ if md_handle is None:
+ return default
return metadata.Metadata(handle=md_handle).value
def store_metadata(self, key: str, md: metadata.Metadata) -> None: