-
-
Notifications
You must be signed in to change notification settings - Fork 641
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
lint: mypy type stubs for LIEF #650
Comments
Hi @fanquake. I don't have objection to add such typing but my concern is more about the cost of maintaining these typing information. |
Yes, ideally we'd be able to use stubgen (a tool packaged with mypy), to automatically generate the type stubs. Note that typeshed will accept incomplete, or partial stubs, so that could potentially reduce the maintenance burden of generating them all / keeping them up to date. |
Ok so yes I think this feature could be helpful :) |
Any progress on this? I doubt whether |
I welcome external contribution on this issue. If someone wants to take the lead, let me know :) |
I'm not sure this is particularly useful without some manual maintenance effort though. Briefly searching around I did come across pybind11-stubgen which might be useful as well, but I've not tried it directly. Generated Stubs (for lief 0.12.1)from typing import Any, ClassVar, Iterable, Iterator, List
from typing import overload
class ARCHITECTURES:
ARM: ClassVar[ARCHITECTURES] = ...
ARM64: ClassVar[ARCHITECTURES] = ...
INTEL: ClassVar[ARCHITECTURES] = ...
MIPS: ClassVar[ARCHITECTURES] = ...
NONE: ClassVar[ARCHITECTURES] = ...
PPC: ClassVar[ARCHITECTURES] = ...
RISCV: ClassVar[ARCHITECTURES] = ...
SPARC: ClassVar[ARCHITECTURES] = ...
SYSZ: ClassVar[ARCHITECTURES] = ...
X86: ClassVar[ARCHITECTURES] = ...
XCORE: ClassVar[ARCHITECTURES] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __getstate__(self) -> int: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __ne__(self, other: object) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
class Binary(Object):
class VA_TYPES:
AUTO: ClassVar[Binary.VA_TYPES] = ...
RVA: ClassVar[Binary.VA_TYPES] = ...
VA: ClassVar[Binary.VA_TYPES] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __getstate__(self) -> int: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __ne__(self, other: object) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
class it_relocations:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, index) -> Any: ...
def __iter__(self) -> Iterator: ...
def __len__(self) -> int: ...
def __next__(self) -> Any: ...
class it_sections:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, index) -> Any: ...
def __iter__(self) -> Iterator: ...
def __len__(self) -> int: ...
def __next__(self) -> Any: ...
class it_symbols:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, index) -> Any: ...
def __iter__(self) -> Iterator: ...
def __len__(self) -> int: ...
def __next__(self) -> Any: ...
name: str
def __init__(self, *args, **kwargs) -> None: ...
def get_content_from_virtual_address(self, virtual_address: int, size: int, va_type: Binary.VA_TYPES = ...) -> List[int]: ...
def get_function_address(self, function_name: str) -> int: ...
def get_symbol(self, *args, **kwargs) -> Any: ...
def has_symbol(self, symbol_name: str) -> bool: ...
def offset_to_virtual_address(self, offset: int, slide: int = ...) -> int: ...
@overload
def patch_address(self, address: int, patch_value: List[int], va_type: Binary.VA_TYPES = ...) -> None: ...
@overload
def patch_address(self, address: int, patch_value: int, size: int = ..., va_type: Binary.VA_TYPES = ...) -> None: ...
def remove_section(self, name: str, clear: bool = ...) -> None: ...
def xref(self, virtual_address: int) -> List[int]: ...
@property
def abstract(self) -> object: ...
@property
def concrete(self) -> object: ...
@property
def ctor_functions(self) -> Any: ...
@property
def entrypoint(self) -> int: ...
@property
def exported_functions(self) -> Any: ...
@property
def format(self) -> EXE_FORMATS: ...
@property
def has_nx(self) -> bool: ...
@property
def header(self) -> Any: ...
@property
def imagebase(self) -> int: ...
@property
def imported_functions(self) -> Any: ...
@property
def is_pie(self) -> bool: ...
@property
def libraries(self) -> Any: ...
@property
def relocations(self) -> Binary.it_relocations: ...
@property
def sections(self) -> Any: ...
@property
def symbols(self) -> Binary.it_symbols: ...
class DictStringVersion:
def __init__(self) -> None: ...
def items(self) -> ItemsView[DictStringVersion]: ...
def keys(self) -> KeysView[DictStringVersion]: ...
def values(self) -> ValuesView[DictStringVersion]: ...
def __bool__(self) -> bool: ...
@overload
def __contains__(self, arg0: str) -> bool: ...
@overload
def __contains__(self, arg0: object) -> bool: ...
def __delitem__(self, arg0: str) -> None: ...
def __getitem__(self, arg0: str) -> str: ...
def __iter__(self) -> Iterator: ...
def __len__(self) -> int: ...
def __setitem__(self, arg0: str, arg1: str) -> None: ...
class ENDIANNESS:
BIG: ClassVar[ENDIANNESS] = ...
LITTLE: ClassVar[ENDIANNESS] = ...
NONE: ClassVar[ENDIANNESS] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __getstate__(self) -> int: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __ne__(self, other: object) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
class EXE_FORMATS:
ELF: ClassVar[EXE_FORMATS] = ...
MACHO: ClassVar[EXE_FORMATS] = ...
PE: ClassVar[EXE_FORMATS] = ...
UNKNOWN: ClassVar[EXE_FORMATS] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __getstate__(self) -> int: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __ne__(self, other: object) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
class Function(Symbol):
class FLAGS:
CONSTRUCTOR: ClassVar[Function.FLAGS] = ...
DEBUG: ClassVar[Function.FLAGS] = ...
DESTRUCTOR: ClassVar[Function.FLAGS] = ...
EXPORTED: ClassVar[Function.FLAGS] = ...
IMPORTED: ClassVar[Function.FLAGS] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __getstate__(self) -> int: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __ne__(self, other: object) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
address: int
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, arg0: str) -> None: ...
@overload
def __init__(self, arg0: int) -> None: ...
@overload
def __init__(self, arg0: str, arg1: int) -> None: ...
def add(self, flag: Function.FLAGS) -> Function: ...
@property
def flags(self) -> List[Function.FLAGS]: ...
class Header(Object):
architecture: Any
endianness: ENDIANNESS
entrypoint: int
modes: Set[MODES]
object_type: OBJECT_TYPES
def __init__(self) -> None: ...
@property
def is_32(self) -> bool: ...
@property
def is_64(self) -> bool: ...
class ItemsView[DictStringVersion]:
def __init__(self, *args, **kwargs) -> None: ...
def __iter__(self) -> Iterator: ...
def __len__(self) -> int: ...
class KeysView[DictStringVersion]:
def __init__(self, *args, **kwargs) -> None: ...
@overload
def __contains__(self, arg0: str) -> bool: ...
@overload
def __contains__(self, arg0: object) -> bool: ...
def __iter__(self) -> Iterator: ...
def __len__(self) -> int: ...
class ListLangCodeItem:
__hash__: ClassVar[None] = ...
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, arg0: ListLangCodeItem) -> None: ...
@overload
def __init__(self, arg0: Iterable) -> None: ...
def append(self, x: PE.LangCodeItem) -> None: ...
def clear(self) -> None: ...
def count(self, x: PE.LangCodeItem) -> int: ...
@overload
def extend(self, L: ListLangCodeItem) -> None: ...
@overload
def extend(self, L: Iterable) -> None: ...
def insert(self, i: int, x: PE.LangCodeItem) -> None: ...
@overload
def pop(self) -> PE.LangCodeItem: ...
@overload
def pop(self, i: int) -> PE.LangCodeItem: ...
def remove(self, x: PE.LangCodeItem) -> None: ...
def __bool__(self) -> bool: ...
def __contains__(self, x: PE.LangCodeItem) -> bool: ...
@overload
def __delitem__(self, arg0: int) -> None: ...
@overload
def __delitem__(self, arg0: slice) -> None: ...
def __eq__(self, arg0: ListLangCodeItem) -> bool: ...
@overload
def __getitem__(self, s: slice) -> ListLangCodeItem: ...
@overload
def __getitem__(self, arg0: int) -> PE.LangCodeItem: ...
def __iter__(self) -> Iterator: ...
def __len__(self) -> int: ...
def __ne__(self, arg0: ListLangCodeItem) -> bool: ...
@overload
def __setitem__(self, arg0: int, arg1: PE.LangCodeItem) -> None: ...
@overload
def __setitem__(self, arg0: slice, arg1: ListLangCodeItem) -> None: ...
class MODES:
ARM: ClassVar[MODES] = ...
M16: ClassVar[MODES] = ...
M32: ClassVar[MODES] = ...
M64: ClassVar[MODES] = ...
MCLASS: ClassVar[MODES] = ...
MIPS3: ClassVar[MODES] = ...
MIPS32: ClassVar[MODES] = ...
MIPS32R6: ClassVar[MODES] = ...
MIPS64: ClassVar[MODES] = ...
MIPSGP64: ClassVar[MODES] = ...
NONE: ClassVar[MODES] = ...
THUMB: ClassVar[MODES] = ...
UNDEFINED: ClassVar[MODES] = ...
V7: ClassVar[MODES] = ...
V8: ClassVar[MODES] = ...
V9: ClassVar[MODES] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __getstate__(self) -> int: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __ne__(self, other: object) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
class OBJECT_TYPES:
EXECUTABLE: ClassVar[OBJECT_TYPES] = ...
LIBRARY: ClassVar[OBJECT_TYPES] = ...
NONE: ClassVar[OBJECT_TYPES] = ...
OBJECT: ClassVar[OBJECT_TYPES] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __getstate__(self) -> int: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __ne__(self, other: object) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
class Object:
def __init__(self, *args, **kwargs) -> None: ...
class PLATFORMS:
ANDROID: ClassVar[PLATFORMS] = ...
IOS: ClassVar[PLATFORMS] = ...
LINUX: ClassVar[PLATFORMS] = ...
OSX: ClassVar[PLATFORMS] = ...
UNKNOWN: ClassVar[PLATFORMS] = ...
WINDOWS: ClassVar[PLATFORMS] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@overload
def __eq__(self, other: object) -> bool: ...
@overload
def __eq__(self, arg0: int) -> bool: ...
def __getstate__(self) -> int: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
@overload
def __ne__(self, other: object) -> bool: ...
@overload
def __ne__(self, arg0: int) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
class Relocation(Object):
address: int
size: int
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, address: int, size: int) -> None: ...
def __eq__(self, arg0: Relocation) -> bool: ...
def __hash__(self) -> int: ...
def __ne__(self, arg0: Relocation) -> bool: ...
class Section(Object):
content: memoryview
name: object
offset: int
size: int
virtual_address: int
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, name: str) -> None: ...
@overload
def search(self, number: int, pos: int = ..., size: int = ...) -> int: ...
@overload
def search(self, str: str, pos: int = ...) -> int: ...
@overload
def search_all(self, number: int, size: int = ...) -> List[int]: ...
@overload
def search_all(self, str: str) -> List[int]: ...
@property
def entropy(self) -> float: ...
@property
def fullname(self) -> str: ...
class Symbol(Object):
name: object
size: int
value: int
def __init__(self) -> None: ...
class ValuesView[DictStringVersion]:
def __init__(self, *args, **kwargs) -> None: ...
def __iter__(self) -> Iterator: ...
def __len__(self) -> int: ...
class bad_file(exception): ...
class bad_format(bad_file): ...
class builder_error(exception): ...
class conversion_error(exception): ...
class corrupted(exception): ...
class exception(Exception): ...
class integrity_error(exception): ...
class lief_errors:
__entries: ClassVar[dict] = ...
asn1_bad_tag: ClassVar[lief_errors] = ...
build_error: ClassVar[lief_errors] = ...
conversion_error: ClassVar[lief_errors] = ...
corrupted: ClassVar[lief_errors] = ...
data_too_large: ClassVar[lief_errors] = ...
file_error: ClassVar[lief_errors] = ...
file_format_error: ClassVar[lief_errors] = ...
not_found: ClassVar[lief_errors] = ...
not_implemented: ClassVar[lief_errors] = ...
not_supported: ClassVar[lief_errors] = ...
parsing_error: ClassVar[lief_errors] = ...
read_error: ClassVar[lief_errors] = ...
read_out_of_bound: ClassVar[lief_errors] = ...
def __init__(self, value: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __getstate__(self) -> int: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __ne__(self, other: object) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
class not_found(exception): ...
class not_implemented(exception): ...
class not_supported(exception): ...
class ok_t:
def __init__(self, *args, **kwargs) -> None: ...
def __bool__(self) -> bool: ...
class parser_error(exception): ...
class pe_bad_section_name(pe_error): ...
class pe_error(exception): ...
class read_out_of_bound(exception): ...
class type_error(exception): ...
@overload
def art_version(filename: str) -> int: ...
@overload
def art_version(raw: List[int]) -> int: ...
def breakp() -> object: ...
def current_platform() -> PLATFORMS: ...
def demangle(arg0: str) -> object: ...
@overload
def dex_version(filename: str) -> int: ...
@overload
def dex_version(raw: List[int]) -> int: ...
@overload
def hash(arg0: Object) -> int: ...
@overload
def hash(arg0: List[int]) -> int: ...
@overload
def hash(arg0: bytes) -> int: ...
@overload
def hash(arg0: str) -> int: ...
@overload
def is_art(filename: str) -> bool: ...
@overload
def is_art(raw: List[int]) -> bool: ...
@overload
def is_dex(filename: str) -> bool: ...
@overload
def is_dex(raw: List[int]) -> bool: ...
@overload
def is_elf(filename: str) -> bool: ...
@overload
def is_elf(raw: List[int]) -> bool: ...
@overload
def is_macho(filename: str) -> bool: ...
@overload
def is_macho(raw: List[int]) -> bool: ...
@overload
def is_oat(filename: str) -> bool: ...
@overload
def is_oat(raw: List[int]) -> bool: ...
@overload
def is_oat(elf: ELF.Binary) -> bool: ...
@overload
def is_pe(filename: str) -> bool: ...
@overload
def is_pe(raw: List[int]) -> bool: ...
@overload
def is_vdex(filename: str) -> bool: ...
@overload
def is_vdex(raw: List[int]) -> bool: ...
@overload
def oat_version(filename: str) -> int: ...
@overload
def oat_version(raw: List[int]) -> int: ...
@overload
def oat_version(elf: ELF.Binary) -> int: ...
@overload
def parse(raw: bytes, name: str = ...) -> Binary: ...
@overload
def parse(filepath: str) -> Binary: ...
@overload
def parse(raw: List[int], name: str = ...) -> Binary: ...
@overload
def parse(io: object, name: str = ...) -> Binary: ...
def shell() -> object: ...
def to_json(arg0: Object) -> str: ...
def to_json_from_abstract(arg0: Object) -> str: ...
@overload
def vdex_version(filename: str) -> int: ...
@overload
def vdex_version(raw: List[int]) -> int: ... Edit: Tried fiddling with the library I mentioned above, it fails with a bunch of errors about failing to parse C++ return types and links to some pybind11 docs about that. Full output below: pybind11-stubgen output (against lief 0.12.1)Command used:
I'm not sure offhand how hard it'd be to resolve the return types in docstrings for this library (and if its worth doing so). |
Thanks for creating |
Yes absolutely @chinggg |
Hi! I have made a draft PR to send generated type stubs to Suggested next steps:
I think some of the errors are caused by incompetence of |
Hello @chinggg, |
@romainthomas Thanks. I find Having inspected some errors, I can classify them into these categories:
|
I started to address this issue. First, I fixed some piece of code in LIEF which makes Here are an example of the stub generated: lief-stub.zip |
Great! I assume the stubs will also be getting upstreamed to https://github.com/python/typeshed ? |
They will be packaged along with the native Python bindings. (I'm refactoring this part) |
Thank you for your efforts! |
I noticed that there are still some issues with the type hints in the latest version of LIEF, which cause the type hints not work properly in VSCode. Such as Fixing these issues is simple, but I am unsure if submitting a PR directly modifying the pyi files is correct (as they might be autogenerated). If possible, I will manually fix these errors and submit a PR. |
Hello @Cirn09, Regarding Lines 2621 to 2623 in 8a6b579
Does anyone else experienced these issues? (cc @fanquake) For the context, I tested the stubs/completion with jedi |
Just next line: Lines 2620 to 2625 in 8a6b579
And here is my patch (not include return type Patchesdiff --git a/api/python/lief/DEX.pyi b/api/python/lief/DEX.pyi
index 0858bdc3..5dcb6ac6 100644
--- a/api/python/lief/DEX.pyi
+++ b/api/python/lief/DEX.pyi
@@ -3,12 +3,6 @@ from typing import Any, ClassVar, Iterator, List, Tuple
from typing import overload
import lief # type: ignore
import lief.DEX # type: ignore
-import lief.DEX.Class # type: ignore
-import lief.DEX.File # type: ignore
-import lief.DEX.MapItem # type: ignore
-import lief.DEX.MapList # type: ignore
-import lief.DEX.Prototype # type: ignore
-import lief.DEX.Type # type: ignore
class ACCESS_FLAGS:
__members__: ClassVar[dict] = ... # read-only
diff --git a/api/python/lief/ELF.pyi b/api/python/lief/ELF.pyi
index 3a85c528..88d57642 100644
--- a/api/python/lief/ELF.pyi
+++ b/api/python/lief/ELF.pyi
@@ -3,15 +3,6 @@ from typing import Any, ClassVar, Dict, Iterable, Iterator, List, Set
from typing import overload
import lief # type: ignore
import lief.ELF # type: ignore
-import lief.ELF.Binary # type: ignore
-import lief.ELF.Builder # type: ignore
-import lief.ELF.CoreAuxv # type: ignore
-import lief.ELF.CoreFile # type: ignore
-import lief.ELF.CorePrStatus # type: ignore
-import lief.ELF.Section # type: ignore
-import lief.ELF.Segment # type: ignore
-import lief.ELF.SymbolVersionDefinition # type: ignore
-import lief.ELF.SymbolVersionRequirement # type: ignore
class ARCH:
__members__: ClassVar[dict] = ... # read-only
diff --git a/api/python/lief/MachO.pyi b/api/python/lief/MachO.pyi
index 2625b186..41642669 100644
--- a/api/python/lief/MachO.pyi
+++ b/api/python/lief/MachO.pyi
@@ -3,14 +3,6 @@ from typing import Any, ClassVar, Iterator, List, Set, Tuple
from typing import overload
import lief # type: ignore
import lief.MachO # type: ignore
-import lief.MachO.Binary # type: ignore
-import lief.MachO.BuildToolVersion # type: ignore
-import lief.MachO.BuildVersion # type: ignore
-import lief.MachO.DataCodeEntry # type: ignore
-import lief.MachO.DyldChainedFixups # type: ignore
-import lief.MachO.DyldInfo # type: ignore
-import lief.MachO.FatBinary # type: ignore
-import lief.MachO.SegmentCommand # type: ignore
class ARM64_RELOCATION:
__members__: ClassVar[dict] = ... # read-only
diff --git a/api/python/lief/OAT.pyi b/api/python/lief/OAT.pyi
index 5c890a72..029f686f 100644
--- a/api/python/lief/OAT.pyi
+++ b/api/python/lief/OAT.pyi
@@ -6,10 +6,6 @@ import lief.Android # type: ignore
import lief.DEX # type: ignore
import lief.ELF # type: ignore
import lief.OAT # type: ignore
-import lief.OAT.Binary # type: ignore
-import lief.OAT.Class # type: ignore
-import lief.OAT.Header # type: ignore
-import lief.OAT.Header.it_key_values_t # type: ignore
class Binary(lief.ELF.Binary):
class it_classes:
diff --git a/api/python/lief/PE.pyi b/api/python/lief/PE.pyi
index 02a6cb3f..bb166a9d 100644
--- a/api/python/lief/PE.pyi
+++ b/api/python/lief/PE.pyi
@@ -3,20 +3,6 @@ from typing import Any, ClassVar, Iterable, Iterator, List, Set, Tuple
from typing import overload
import lief # type: ignore
import lief.PE # type: ignore
-import lief.PE.Binary # type: ignore
-import lief.PE.DelayImport # type: ignore
-import lief.PE.Export # type: ignore
-import lief.PE.ExportEntry # type: ignore
-import lief.PE.Import # type: ignore
-import lief.PE.Pogo # type: ignore
-import lief.PE.Relocation # type: ignore
-import lief.PE.ResourceDialog # type: ignore
-import lief.PE.ResourceNode # type: ignore
-import lief.PE.ResourcesManager # type: ignore
-import lief.PE.RichHeader # type: ignore
-import lief.PE.Signature # type: ignore
-import lief.PE.SignerInfo # type: ignore
-import lief.PE.x509 # type: ignore
class ACCELERATOR_FLAGS:
__members__: ClassVar[dict] = ... # read-only
diff --git a/api/python/lief/VDEX.pyi b/api/python/lief/VDEX.pyi
index c81e60c1..cc496854 100644
--- a/api/python/lief/VDEX.pyi
+++ b/api/python/lief/VDEX.pyi
@@ -3,7 +3,7 @@ from typing import List
from typing import overload
import lief # type: ignore
import lief.Android # type: ignore
-import lief.OAT.Binary # type: ignore
+import lief.OAT # type: ignore
import lief.VDEX # type: ignore
class File(lief.Object):
diff --git a/api/python/lief/__init__.pyi b/api/python/lief/__init__.pyi
index 10386939..ee7808fe 100644
--- a/api/python/lief/__init__.pyi
+++ b/api/python/lief/__init__.pyi
@@ -2,9 +2,17 @@ from typing import Any, ClassVar, Iterator, List, Set
from typing import overload
import lief # type: ignore
-import lief.Binary # type: ignore
-import lief.ELF # type: ignore
-import lief.Function # type: ignore
+from . import (
+ Android,
+ ART,
+ DEX,
+ ELF,
+ logging,
+ MachO,
+ OAT,
+ PE,
+ VDEX,
+)
class ARCHITECTURES:
__members__: ClassVar[dict] = ... # read-only I did not use any additional tools to test, but before the patch, VSCode was detecting the return value of |
Fixed @Cirn09. Thanks for the feedback on this! |
Not all LIEF/api/python/src/PE/objects/pyParser.cpp Lines 43 to 50 in 683fc6c
There are still some functions return Line 1030 in 683fc6c
It seems that the common feature among them is that their return value types are uncertain in the CPP code: LIEF/api/python/src/PE/objects/pyImport.cpp Lines 126 to 129 in 683fc6c
|
Actually yes. If the parsing fails, the |
Another issue is that VSCode cannot find However, |
Hummm I'm not in favor of duplicating the documentation. This point should be addressed by VSCode, not LIEF. |
I mean DocString: https://peps.python.org/pep-0257/
|
I understood your request but the documentation is already present in python -c "import lief;print(lief.PE.parse.__doc__)"
parse(*args, **kwargs)
Overloaded function.
1. parse(filename: str) -> LIEF::PE::Binary
Parse the PE binary from the given **file path** and return a :class:`~lief.PE.Binary` object
[...] So even if stugen supports this, I won't enable it. Please use the discussions section for this kind of request |
I'm currently using LIEF in a project that uses mypy for Python type-checking. We use an ignore directive on our
import lief #type:ignore
statements, as type stubs for lief are not currently available. I've been considering generating and contributing stubs to https://github.com/python/typeshed, so that we can remove the ignores, and maybe others will find them useful. However I wanted to raise it here first, in case you had an objection / thoughts etc.The text was updated successfully, but these errors were encountered: