From 4a71e563ba2ad9946515f1b4d75df8ec6dcb1749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20H=C3=B6rist?= Date: Wed, 5 Feb 2025 19:27:10 +0100 Subject: [PATCH 1/2] Add python-gnupg stubs --- stubs/python-gnupg/METADATA.toml | 2 + stubs/python-gnupg/gnupg/__init__.pyi | 257 ++++++++++++++++++++++++++ 2 files changed, 259 insertions(+) create mode 100644 stubs/python-gnupg/METADATA.toml create mode 100644 stubs/python-gnupg/gnupg/__init__.pyi diff --git a/stubs/python-gnupg/METADATA.toml b/stubs/python-gnupg/METADATA.toml new file mode 100644 index 000000000000..7a17d640c61d --- /dev/null +++ b/stubs/python-gnupg/METADATA.toml @@ -0,0 +1,2 @@ +version = "0.5.*" +upstream_repository = "https://github.com/vsajip/python-gnupg" diff --git a/stubs/python-gnupg/gnupg/__init__.pyi b/stubs/python-gnupg/gnupg/__init__.pyi new file mode 100644 index 000000000000..215cffa0c30e --- /dev/null +++ b/stubs/python-gnupg/gnupg/__init__.pyi @@ -0,0 +1,257 @@ +import logging +import re +from typing import Any + +__version__: str = ... +__author__: str = ... +__date__: str = ... + +from typing import Protocol + +string_types: type[str] = ... +text_type: type[str] = ... +path_types: tuple[type[str]] = ... + +log_everything: bool = ... +logger: logging.Logger = ... +fsencoding: str = ... + +UNSAFE: re.Pattern[Any] = ... + +def shell_quote(s: str) -> str: ... +def no_quote(s: str) -> str: ... + +class _ReadableFile(Protocol): + def read(self, size: int) -> bytes: ... + +class StatusHandler: + + on_data_failure: Exception | None = ... + def __init__(self, gpg: GPG) -> None: ... + def handle_status(self, key: str, value: str) -> None: ... + +class Verify(StatusHandler): + + TRUST_EXPIRED: int = ... + TRUST_UNDEFINED: int = ... + TRUST_NEVER: int = ... + TRUST_MARGINAL: int = ... + TRUST_FULLY: int = ... + TRUST_ULTIMATE: int = ... + TRUST_LEVELS: dict[str, int] = ... + GPG_SYSTEM_ERROR_CODES: dict[int, str] = ... + GPG_ERROR_CODES: dict[int, str] = ... + returncode: int | None = ... + def __init__(self, gpg: GPG) -> None: ... + def __nonzero__(self) -> bool: ... + def __bool__(self) -> bool: ... + def handle_status(self, key: str, value: str) -> None: ... + +class ImportResult(StatusHandler): + + counts: list[str] = ... + returncode: int | None = ... + def __init__(self, gpg: GPG) -> None: ... + def __nonzero__(self) -> bool: ... + def __bool__(self) -> bool: ... + + ok_reason: dict[str, str] = ... + problem_reason: dict[str, str] = ... + def handle_status(self, key: str, value: str) -> None: ... + def summary(self) -> str: ... + +ESCAPE_PATTERN: re.Pattern[Any] = ... +BASIC_ESCAPES: dict[str, str] = ... + +class SendResult(StatusHandler): + + returncode: int | None = ... + def handle_status(self, key: str, value: str) -> None: ... + +class SearchKeys(StatusHandler, list[dict[Any, Any]]): + + UID_INDEX: int = ... + FIELDS: list[str] = ... + returncode: int | None = ... + def __init__(self, gpg: GPG) -> None: ... + def get_fields(self, args: Any) -> dict[str, Any]: ... + def pub(self, args: Any) -> None: ... + def uid(self, args: Any) -> None: ... + def handle_status(self, key: str, value: str) -> None: ... + +class ListKeys(SearchKeys): + + UID_INDEX: int = ... + FIELDS: list[str] = ... + def __init__(self, gpg: GPG) -> None: ... + def key(self, args: Any) -> None: ... + sec: Any = ... + def fpr(self, args: Any) -> None: ... + def grp(self, args: Any) -> None: ... + def sub(self, args: Any) -> None: ... + def ssb(self, args: Any) -> None: ... + def sig(self, args: Any) -> None: ... + +class ScanKeys(ListKeys): + def sub(self, args: Any) -> None: ... + +class TextHandler: ... + +class Crypt(Verify, TextHandler): + def __init__(self, gpg: GPG) -> None: ... + def __nonzero__(self) -> bool: ... + def __bool__(self) -> bool: ... + def handle_status(self, key: str, value: str) -> None: ... + +class GenKey(StatusHandler): + + returncode: int | None = ... + def __init__(self, gpg: GPG) -> None: ... + def __nonzero__(self) -> bool: ... + def __bool__(self) -> bool: ... + def handle_status(self, key: str, value: str) -> None: ... + +class AddSubkey(StatusHandler): + + returncode: int | None = ... + def __init__(self, gpg: GPG) -> None: ... + def __nonzero__(self) -> bool: ... + def __bool__(self) -> bool: ... + def handle_status(self, key: str, value: str) -> None: ... + +class ExportResult(GenKey): + def handle_status(self, key: str, value: str) -> None: ... + +class DeleteResult(StatusHandler): + + returncode: int | None = ... + def __init__(self, gpg: GPG) -> None: ... + + problem_reason: dict[str, str] = ... + def handle_status(self, key: str, value: str) -> None: ... + def __nonzero__(self) -> bool: ... + def __bool__(self) -> bool: ... + +class TrustResult(DeleteResult): ... + +class Sign(StatusHandler, TextHandler): + + returncode: int | None = ... + def __init__(self, gpg: GPG) -> None: ... + def __nonzero__(self) -> bool: ... + def __bool__(self) -> bool: ... + def handle_status(self, key: str, value: str) -> None: ... + +class AutoLocateKey(StatusHandler): + def __init__(self, gpg: GPG) -> None: ... + def handle_status(self, key: str, value: str) -> None: ... + def pub(self, args: Any) -> None: ... + def uid(self, args: Any) -> None: ... + def sub(self, args: Any) -> None: ... + def fpr(self, args: Any) -> None: ... + +VERSION_RE: re.Pattern[Any] = ... +HEX_DIGITS_RE: re.Pattern[Any] = ... +PUBLIC_KEY_RE: re.Pattern[Any] = ... + +class GPG: + + error_map: None = ... + decode_errors: str = ... + buffer_size: int = ... + result_map: dict[str, Any] = ... + def __init__( + self, + gpgbinary: str = ..., + gnupghome: str | None = ..., + verbose: bool = ..., + use_agent: bool = ..., + keyring: str | list[str] | None = ..., + options: list[str] | None = ..., + secret_keyring: str | list[str] | None = ..., + env: dict[str, str] | None = ..., + ) -> None: ... + def make_args(self, args: list[str], passphrase: str) -> list[str]: ... + def is_valid_file(self, fileobj: Any) -> bool: ... + def sign(self, message: str | bytes, **kwargs: Any) -> Sign: ... + def set_output_without_confirmation(self, args: list[str], output: str) -> None: ... + def is_valid_passphrase(self, passphrase: str) -> bool: ... + def sign_file( + self, + fileobj_or_path: str | _ReadableFile, + keyid: str | None = ..., + passphrase: str | None = ..., + clearsign: bool = ..., + detach: bool = ..., + binary: bool = ..., + output: str | None = ..., + extra_args: list[str] | None = ..., + ) -> Sign: ... + def verify(self, data: str | bytes, **kwargs: Any) -> Verify: ... + def verify_file( + self, + fileobj_or_path: str | _ReadableFile, + data_filename: str | None = ..., + close_file: bool = ..., + extra_args: list[str] | None = ..., + ) -> Verify: ... + def verify_data(self, sig_filename: str, data: str | bytes, extra_args: list[str] | None = ...) -> Verify: ... + def import_keys( + self, key_data: str | bytes, extra_args: list[str] | None = ..., passphrase: str | None = ... + ) -> ImportResult: ... + def import_keys_file(self, key_path: str, **kwargs: Any) -> ImportResult: ... + def recv_keys(self, keyserver: str, *keyids: str, **kwargs: Any) -> ImportResult: ... + def send_keys(self, keyserver: str, *keyids: str, **kwargs: Any) -> SendResult: ... + def delete_keys( + self, + fingerprints: str | list[str], + secret: bool = ..., + passphrase: str | None = ..., + expect_passphrase: bool = ..., + exclamation_mode: bool = ..., + ) -> DeleteResult: ... + def export_keys( + self, + keyids: str | list[str], + secret: bool = ..., + armor: bool = ..., + minimal: bool = ..., + passphrase: str | None = ..., + expect_passphrase: bool = ..., + output: str | None = ..., + ) -> ExportResult: ... + def list_keys(self, secret: bool = ..., keys: str | list[str] | None = ..., sigs: bool = ...) -> ListKeys: ... + def scan_keys(self, filename: str) -> ScanKeys: ... + def scan_keys_mem(self, key_data: str | bytes) -> ScanKeys: ... + def search_keys(self, query: str, keyserver: str = ..., extra_args: list[str] | None = ...) -> SearchKeys: ... + def auto_locate_key(self, email: str, mechanisms: list[str] | None = ..., **kwargs: Any) -> AutoLocateKey: ... + def gen_key(self, input: str) -> GenKey: ... + def gen_key_input(self, **kwargs: Any) -> str: ... + def add_subkey( + self, master_key: str, master_passphrase: str | None = ..., algorithm: str = ..., usage: str = ..., expire: str = ... + ) -> AddSubkey: ... + def encrypt_file( + self, + fileobj_or_path: str | _ReadableFile, + recipients: str | list[str], + sign: str | None = ..., + always_trust: bool = ..., + passphrase: str | None = ..., + armor: bool = ..., + output: str | None = ..., + symmetric: bool = ..., + extra_args: list[str] | None = ..., + ) -> Crypt: ... + def encrypt(self, data: str | bytes, recipients: str | list[str], **kwargs: Any) -> Crypt: ... + def decrypt(self, message: str | bytes, **kwargs: Any) -> Crypt: ... + def decrypt_file( + self, + fileobj_or_path: str | _ReadableFile, + always_trust: bool = ..., + passphrase: str | None = ..., + output: str | None = ..., + extra_args: list[str] | None = ..., + ) -> Crypt: ... + def get_recipients(self, message: str | bytes, **kwargs: Any) -> list[str]: ... + def get_recipients_file(self, fileobj_or_path: str | _ReadableFile, extra_args: list[str] | None = ...) -> list[str]: ... + def trust_keys(self, fingerprints: str | list[str], trustlevel: str) -> TrustResult: ... From e8b03f84518efb82da5f51fe4b54cebbc6646f69 Mon Sep 17 00:00:00 2001 From: lovetox Date: Wed, 26 Feb 2025 21:37:42 +0100 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: Sebastian Rittau --- stubs/python-gnupg/gnupg/__init__.pyi | 76 +++++++++++++-------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/stubs/python-gnupg/gnupg/__init__.pyi b/stubs/python-gnupg/gnupg/__init__.pyi index 215cffa0c30e..5a8b000f59ff 100644 --- a/stubs/python-gnupg/gnupg/__init__.pyi +++ b/stubs/python-gnupg/gnupg/__init__.pyi @@ -2,19 +2,19 @@ import logging import re from typing import Any -__version__: str = ... -__author__: str = ... -__date__: str = ... +__version__: Final[str] +__author__: Final[str] +__date__: Final[str] from typing import Protocol -string_types: type[str] = ... -text_type: type[str] = ... -path_types: tuple[type[str]] = ... +string_types: Final[type[str]] +text_type: Final[type[str]] +path_types: Final[tuple[type[str]]] -log_everything: bool = ... -logger: logging.Logger = ... -fsencoding: str = ... +log_everything: bool +logger: logging.Logger +fsencoding: str UNSAFE: re.Pattern[Any] = ... @@ -22,7 +22,8 @@ def shell_quote(s: str) -> str: ... def no_quote(s: str) -> str: ... class _ReadableFile(Protocol): - def read(self, size: int) -> bytes: ... + def read(self, size: int = ..., /) -> bytes: ... + def close(self) -> object: ... class StatusHandler: @@ -31,16 +32,15 @@ class StatusHandler: def handle_status(self, key: str, value: str) -> None: ... class Verify(StatusHandler): - - TRUST_EXPIRED: int = ... - TRUST_UNDEFINED: int = ... - TRUST_NEVER: int = ... - TRUST_MARGINAL: int = ... - TRUST_FULLY: int = ... - TRUST_ULTIMATE: int = ... - TRUST_LEVELS: dict[str, int] = ... - GPG_SYSTEM_ERROR_CODES: dict[int, str] = ... - GPG_ERROR_CODES: dict[int, str] = ... + TRUST_EXPIRED: Final = 0 + TRUST_UNDEFINED: Final = 1 + TRUST_NEVER: Final = 2 + TRUST_MARGINAL: Final = 3 + TRUST_FULLY: Final = 4 + TRUST_ULTIMATE: Final = 5 + TRUST_LEVELS: Final[dict[str, int]] + GPG_SYSTEM_ERROR_CODES: Final[dict[int, str]] + GPG_ERROR_CODES: Final[dict[int, str]] returncode: int | None = ... def __init__(self, gpg: GPG) -> None: ... def __nonzero__(self) -> bool: ... @@ -55,13 +55,13 @@ class ImportResult(StatusHandler): def __nonzero__(self) -> bool: ... def __bool__(self) -> bool: ... - ok_reason: dict[str, str] = ... - problem_reason: dict[str, str] = ... + ok_reason: Final[dict[str, str]] + problem_reason: Final[dict[str, str]] def handle_status(self, key: str, value: str) -> None: ... def summary(self) -> str: ... -ESCAPE_PATTERN: re.Pattern[Any] = ... -BASIC_ESCAPES: dict[str, str] = ... +ESCAPE_PATTERN: Final[re.Pattern[str]] +BASIC_ESCAPES: Final[dict[str, str]] class SendResult(StatusHandler): @@ -70,9 +70,9 @@ class SendResult(StatusHandler): class SearchKeys(StatusHandler, list[dict[Any, Any]]): - UID_INDEX: int = ... - FIELDS: list[str] = ... - returncode: int | None = ... + UID_INDEX: Final = 1 + FIELDS: Final[list[str]] + returncode: int | None def __init__(self, gpg: GPG) -> None: ... def get_fields(self, args: Any) -> dict[str, Any]: ... def pub(self, args: Any) -> None: ... @@ -150,9 +150,9 @@ class AutoLocateKey(StatusHandler): def sub(self, args: Any) -> None: ... def fpr(self, args: Any) -> None: ... -VERSION_RE: re.Pattern[Any] = ... -HEX_DIGITS_RE: re.Pattern[Any] = ... -PUBLIC_KEY_RE: re.Pattern[Any] = ... +VERSION_RE: Final[re.Pattern[str]] +HEX_DIGITS_RE: Final[re.Pattern[str]] +PUBLIC_KEY_RE: Final[re.Pattern[str]] class GPG: @@ -162,14 +162,14 @@ class GPG: result_map: dict[str, Any] = ... def __init__( self, - gpgbinary: str = ..., - gnupghome: str | None = ..., - verbose: bool = ..., - use_agent: bool = ..., - keyring: str | list[str] | None = ..., - options: list[str] | None = ..., - secret_keyring: str | list[str] | None = ..., - env: dict[str, str] | None = ..., + gpgbinary: str = "gpg", + gnupghome: str | None = None, + verbose: bool = False, + use_agent: bool = False, + keyring: str | list[str] | None = None, + options: list[str] | None = None, + secret_keyring: str | list[str] | None = None, + env: dict[str, str] | None = None, ) -> None: ... def make_args(self, args: list[str], passphrase: str) -> list[str]: ... def is_valid_file(self, fileobj: Any) -> bool: ...