diff options
| author | Simeon Simeonov | 2026-04-16 17:14:23 +0200 |
|---|---|---|
| committer | Simeon Simeonov | 2026-04-16 17:14:23 +0200 |
| commit | 3e4185913b584f5cc9a54f16f3c223861e11ec18 (patch) | |
| tree | 33877fd0f3e34e13d911d98641227eb5d03fbb9d /src | |
| parent | bba82a86b137c73832ad7b6a397d3db24fcc625f (diff) | |
Introduce a new marco - %e and migrate the project from GitHub to Codeberg2.2.0
Diffstat (limited to 'src')
| -rw-r--r-- | src/etoolkit/__init__.py | 6 | ||||
| -rw-r--r-- | src/etoolkit/__main__.py | 18 | ||||
| -rw-r--r-- | src/etoolkit/etoolkit.py | 19 |
3 files changed, 23 insertions, 20 deletions
diff --git a/src/etoolkit/__init__.py b/src/etoolkit/__init__.py index 4cf5d6e..fc32b61 100644 --- a/src/etoolkit/__init__.py +++ b/src/etoolkit/__init__.py | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | # etoolkit | 1 | # etoolkit |
| 2 | # Copyright (C) 2021-2024 Simeon Simeonov | 2 | # Copyright (C) 2021-2026 Simeon Simeonov |
| 3 | 3 | ||
| 4 | # This program is free software: you can redistribute it and/or modify | 4 | # This program is free software: you can redistribute it and/or modify |
| 5 | # it under the terms of the GNU General Public License as published by | 5 | # it under the terms of the GNU General Public License as published by |
| @@ -18,11 +18,11 @@ | |||
| 18 | from .etoolkit import EtoolkitInstance, EtoolkitInstanceError | 18 | from .etoolkit import EtoolkitInstance, EtoolkitInstanceError |
| 19 | 19 | ||
| 20 | __author__ = 'Simeon Simeonov' | 20 | __author__ = 'Simeon Simeonov' |
| 21 | __version__ = '2.1.0' | 21 | __version__ = '2.2.0' |
| 22 | __license__ = 'GPL3' | 22 | __license__ = 'GPL3' |
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | def int_or_str(value): | 25 | def int_or_str(value: int | str) -> int | str: |
| 26 | """Returns int value of value when possible""" | 26 | """Returns int value of value when possible""" |
| 27 | try: | 27 | try: |
| 28 | return int(value) | 28 | return int(value) |
diff --git a/src/etoolkit/__main__.py b/src/etoolkit/__main__.py index a2f2f20..cef3d42 100644 --- a/src/etoolkit/__main__.py +++ b/src/etoolkit/__main__.py | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | # etoolkit | 1 | # etoolkit |
| 2 | # Copyright (C) 2021-2024 Simeon Simeonov | 2 | # Copyright (C) 2021-2026 Simeon Simeonov |
| 3 | 3 | ||
| 4 | # This program is free software: you can redistribute it and/or modify | 4 | # This program is free software: you can redistribute it and/or modify |
| 5 | # it under the terms of the GNU General Public License as published by | 5 | # it under the terms of the GNU General Public License as published by |
| @@ -50,7 +50,7 @@ class EtoolkitCLIHandler: | |||
| 50 | a part of the etoolkit API | 50 | a part of the etoolkit API |
| 51 | """ | 51 | """ |
| 52 | 52 | ||
| 53 | def __init__(self, args: argparse.Namespace, config_dict: dict): | 53 | def __init__(self, args: argparse.Namespace, config_dict: dict) -> None: |
| 54 | """ | 54 | """ |
| 55 | :param args: The parsed argparse arguments sent by the caller | 55 | :param args: The parsed argparse arguments sent by the caller |
| 56 | :type args: argparse.Namespace | 56 | :type args: argparse.Namespace |
| @@ -69,7 +69,7 @@ class EtoolkitCLIHandler: | |||
| 69 | 69 | ||
| 70 | self._password_from_env = os.environ.get('ETOOLKIT_MASTER_PASSWORD') | 70 | self._password_from_env = os.environ.get('ETOOLKIT_MASTER_PASSWORD') |
| 71 | 71 | ||
| 72 | def decrypt_value(self): | 72 | def decrypt_value(self) -> None: |
| 73 | """ | 73 | """ |
| 74 | Interactive method for decrypting value(s) | 74 | Interactive method for decrypting value(s) |
| 75 | 75 | ||
| @@ -110,7 +110,7 @@ class EtoolkitCLIHandler: | |||
| 110 | break | 110 | break |
| 111 | return | 111 | return |
| 112 | 112 | ||
| 113 | def encrypt_value(self): | 113 | def encrypt_value(self) -> None: |
| 114 | """ | 114 | """ |
| 115 | Interactive method for encrypting value(s) | 115 | Interactive method for encrypting value(s) |
| 116 | 116 | ||
| @@ -155,7 +155,7 @@ class EtoolkitCLIHandler: | |||
| 155 | break | 155 | break |
| 156 | return | 156 | return |
| 157 | 157 | ||
| 158 | def generate_master_password_hash(self): | 158 | def generate_master_password_hash(self) -> None: |
| 159 | """ | 159 | """ |
| 160 | Interactive method for generating password hash | 160 | Interactive method for generating password hash |
| 161 | 161 | ||
| @@ -168,7 +168,7 @@ class EtoolkitCLIHandler: | |||
| 168 | ) | 168 | ) |
| 169 | print(f'Master password hash: {phash}') | 169 | print(f'Master password hash: {phash}') |
| 170 | 170 | ||
| 171 | def list(self): | 171 | def list(self) -> None: |
| 172 | """Lists all instances defined in the config file""" | 172 | """Lists all instances defined in the config file""" |
| 173 | 173 | ||
| 174 | for instance_name in sorted( | 174 | for instance_name in sorted( |
| @@ -179,7 +179,7 @@ class EtoolkitCLIHandler: | |||
| 179 | ): | 179 | ): |
| 180 | print(instance_name) | 180 | print(instance_name) |
| 181 | 181 | ||
| 182 | def load_instance(self): | 182 | def load_instance(self) -> None: |
| 183 | """Loads a single specified instance from the config file""" | 183 | """Loads a single specified instance from the config file""" |
| 184 | 184 | ||
| 185 | inst = etoolkit.EtoolkitInstance( | 185 | inst = etoolkit.EtoolkitInstance( |
| @@ -208,7 +208,7 @@ class EtoolkitCLIHandler: | |||
| 208 | os.environ.get('SHELL', 'bash').split(), check=False | 208 | os.environ.get('SHELL', 'bash').split(), check=False |
| 209 | ) | 209 | ) |
| 210 | 210 | ||
| 211 | def reencrypt(self): | 211 | def reencrypt(self) -> None: |
| 212 | """ | 212 | """ |
| 213 | Interactive method that prints new configuration data (JSON) to stdout | 213 | Interactive method that prints new configuration data (JSON) to stdout |
| 214 | 214 | ||
| @@ -277,7 +277,7 @@ class EtoolkitCLIHandler: | |||
| 277 | ) | 277 | ) |
| 278 | 278 | ||
| 279 | 279 | ||
| 280 | def main(inargs=None): | 280 | def main(inargs: list = None) -> None: |
| 281 | """main entry point""" | 281 | """main entry point""" |
| 282 | 282 | ||
| 283 | parser = argparse.ArgumentParser( | 283 | parser = argparse.ArgumentParser( |
diff --git a/src/etoolkit/etoolkit.py b/src/etoolkit/etoolkit.py index a933a01..f5ce2a6 100644 --- a/src/etoolkit/etoolkit.py +++ b/src/etoolkit/etoolkit.py | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | # etoolkit | 1 | # etoolkit |
| 2 | # Copyright (C) 2021-2024 Simeon Simeonov | 2 | # Copyright (C) 2021-2026 Simeon Simeonov |
| 3 | 3 | ||
| 4 | # This program is free software: you can redistribute it and/or modify | 4 | # This program is free software: you can redistribute it and/or modify |
| 5 | # it under the terms of the GNU General Public License as published by | 5 | # it under the terms of the GNU General Public License as published by |
| @@ -19,6 +19,7 @@ import base64 | |||
| 19 | import getpass | 19 | import getpass |
| 20 | import hashlib | 20 | import hashlib |
| 21 | import os | 21 | import os |
| 22 | from collections.abc import Callable | ||
| 22 | 23 | ||
| 23 | from cryptography.exceptions import InvalidTag | 24 | from cryptography.exceptions import InvalidTag |
| 24 | from cryptography.hazmat.primitives.ciphers.aead import AESGCM | 25 | from cryptography.hazmat.primitives.ciphers.aead import AESGCM |
| @@ -33,7 +34,7 @@ class EtoolkitInstanceError(Exception): | |||
| 33 | class EtoolkitInstance: | 34 | class EtoolkitInstance: |
| 34 | """A basic class representing a single instance""" | 35 | """A basic class representing a single instance""" |
| 35 | 36 | ||
| 36 | def __init__(self, name: str, data: dict): | 37 | def __init__(self, name: str, data: dict) -> None: |
| 37 | """ | 38 | """ |
| 38 | :param name: Instance name | 39 | :param name: Instance name |
| 39 | :type name: str | 40 | :type name: str |
| @@ -76,14 +77,14 @@ class EtoolkitInstance: | |||
| 76 | ] | 77 | ] |
| 77 | 78 | ||
| 78 | @property | 79 | @property |
| 79 | def master_password(self) -> str: | 80 | def master_password(self) -> str | None: |
| 80 | """master_password-property""" | 81 | """master_password-property""" |
| 81 | if self._master_password is not None: | 82 | if self._master_password is not None: |
| 82 | return self._master_password | 83 | return self._master_password |
| 83 | return None if self._parent is None else self._parent.master_password | 84 | return None if self._parent is None else self._parent.master_password |
| 84 | 85 | ||
| 85 | @master_password.setter | 86 | @master_password.setter |
| 86 | def master_password(self, value): | 87 | def master_password(self, value: str) -> None: |
| 87 | """master_password-property setter""" | 88 | """master_password-property setter""" |
| 88 | self._master_password = value | 89 | self._master_password = value |
| 89 | if self._parent is not None and self._parent.master_password is None: | 90 | if self._parent is not None and self._parent.master_password is None: |
| @@ -95,7 +96,7 @@ class EtoolkitInstance: | |||
| 95 | return self._master_password_hash | 96 | return self._master_password_hash |
| 96 | 97 | ||
| 97 | @master_password_hash.setter | 98 | @master_password_hash.setter |
| 98 | def master_password_hash(self, value): | 99 | def master_password_hash(self, value: str) -> None: |
| 99 | """master_password_hash-property setter""" | 100 | """master_password_hash-property setter""" |
| 100 | self._master_password_hash = value | 101 | self._master_password_hash = value |
| 101 | 102 | ||
| @@ -105,12 +106,12 @@ class EtoolkitInstance: | |||
| 105 | return self._name | 106 | return self._name |
| 106 | 107 | ||
| 107 | @property | 108 | @property |
| 108 | def prompt_func(self): | 109 | def prompt_func(self) -> Callable[[str, bool], str]: |
| 109 | """prompt_func-property""" | 110 | """prompt_func-property""" |
| 110 | return self._prompt_func | 111 | return self._prompt_func |
| 111 | 112 | ||
| 112 | @prompt_func.setter | 113 | @prompt_func.setter |
| 113 | def prompt_func(self, value): | 114 | def prompt_func(self, value: Callable[[str, bool], str]) -> None: |
| 114 | """prompt_func-property setter""" | 115 | """prompt_func-property setter""" |
| 115 | self._prompt_func = value | 116 | self._prompt_func = value |
| 116 | if self._parent is not None and self._parent.prompt_func is None: | 117 | if self._parent is not None and self._parent.prompt_func is None: |
| @@ -294,7 +295,7 @@ class EtoolkitInstance: | |||
| 294 | ) | 295 | ) |
| 295 | 296 | ||
| 296 | @staticmethod | 297 | @staticmethod |
| 297 | def parse_value(value, macros: dict): | 298 | def parse_value(value: object, macros: dict) -> object: |
| 298 | """ | 299 | """ |
| 299 | Returns the value with all macros replaced by their values | 300 | Returns the value with all macros replaced by their values |
| 300 | 301 | ||
| @@ -412,6 +413,8 @@ class EtoolkitInstance: | |||
| 412 | if not value: | 413 | if not value: |
| 413 | # perhaps unset instead of skipping? | 414 | # perhaps unset instead of skipping? |
| 414 | continue | 415 | continue |
| 416 | if isinstance(value, str) and '%e' in value: | ||
| 417 | macros['%e'] = os.environ.get(key, '') | ||
| 415 | if isinstance(value, str) and '%p' in value: | 418 | if isinstance(value, str) and '%p' in value: |
| 416 | macros['%p'] = ( | 419 | macros['%p'] = ( |
| 417 | self._parent.get_environ().get(key, '') | 420 | self._parent.get_environ().get(key, '') |
