Merge remote-tracking branch 'origin/patch'

This commit is contained in:
Ryan Kurtz
2026-01-02 13:33:35 -05:00
3 changed files with 21 additions and 8 deletions

View File

@@ -120,7 +120,7 @@ def consume_program(
object was provided, the same consumer object is returned. Otherwise, a new consumer object
is created and returned.
:raises FileNotFoundError: If the path does not exist in the project.
:raises TypeError: If the path in the project exists but is not a Program.
:raises pyghidra.ProgramTypeError: If the path in the project exists but is not a Program.
"""
```
@@ -139,7 +139,7 @@ def program_context(
:param path: The project path of the program (should start with "/").
:return: The Ghidra program.
:raises FileNotFoundError: If the path does not exist in the project.
:raises TypeError: If the path in the project exists but is not a Program.
:raises pyghidra.ProgramTypeError: If the path in the project exists but is not a Program.
"""
```
@@ -277,6 +277,12 @@ def walk_programs(
"""
```
### pyghidra.ProgramTypeError
```python
class ProgramTypeError(TypeError):
"""Custom exception for when a Program was expected but not received."""
```
## Example
The following example, while not very useful, showcases much of the API:
```python
@@ -564,6 +570,7 @@ import pdb_ # imports Ghidra's pdb
__3.0.2__
* Fixed an issue that prevented [`pyghidra.analysis_properties()`](#pyghidraanalysis_properties)
from having access to all of the analysis properties.
* Fixed issues related to the PyGhidra API inadvertently squashing exceptions
__3.0.1__
* Fixed `AttributeError: module 'pyghidra' has no attribute 'program_conext'` when performing a

View File

@@ -59,6 +59,7 @@ from pyghidra.api import start, started
from pyghidra.api import open_project, open_filesystem, consume_program, program_context, analyze
from pyghidra.api import ghidra_script, transaction, analysis_properties, program_info
from pyghidra.api import program_loader, task_monitor, walk_project, walk_programs
from pyghidra.api import ProgramTypeError
from pyghidra.launcher import DeferredPyGhidraLauncher, GuiPyGhidraLauncher, HeadlessPyGhidraLauncher
from pyghidra.script import get_current_interpreter
from pyghidra.version import ApplicationInfo, ExtensionDetails
@@ -70,5 +71,5 @@ __all__ = [
"HeadlessPyGhidraLauncher", "start", "started", "open_project", "open_filesystem",
"consume_program", "program_context", "analyze", "ghidra_script", "transaction",
"analysis_properties", "program_info", "program_loader", "task_monitor", "walk_project",
"walk_programs"
"walk_programs", "ProgramTypeError"
]

View File

@@ -121,7 +121,7 @@ def consume_program(
object was provided, the same consumer object is returned. Otherwise, a new consumer object
is created and returned.
:raises FileNotFoundError: If the path does not exist in the project.
:raises TypeError: If the path in the project exists but is not a Program.
:raises pyghidra.ProgramTypeError: If the path in the project exists but is not a Program.
"""
from ghidra.program.model.listing import Program
from java.lang import Object # type:ignore @UnresolvedImport
@@ -135,7 +135,7 @@ def consume_program(
program_cls = Program.class_
if not program_cls.isAssignableFrom(dobj.getClass()):
dobj.release(consumer)
raise TypeError(f'"{path}" exists but is not a Program')
raise ProgramTypeError(f'"{path}" exists but is not a Program')
return dobj, consumer
@contextlib.contextmanager
@@ -151,7 +151,7 @@ def program_context(
:param path: The project path of the program (should start with "/").
:return: The Ghidra program.
:raises FileNotFoundError: If the path does not exist in the project.
:raises TypeError: If the path in the project exists but is not a Program.
:raises pyghidra.ProgramTypeError: If the path in the project exists but is not a Program.
"""
program, consumer = consume_program(project, path)
try:
@@ -270,6 +270,7 @@ def transaction(
yield transaction_id
except:
success = False
raise
finally:
program.endTransaction(transaction_id, success)
@@ -361,7 +362,11 @@ def walk_programs(
with program_context(project, file.getPathname()) as program:
if program_filter(file, program):
callback(file, program)
except TypeError:
pass # skip over non-programs
except ProgramTypeError:
pass # skip over non-programs
walk_project(project, process, start=start)
class ProgramTypeError(TypeError):
"""Custom exception for when a Program was expected but not received."""
pass