Metadata-Version: 2.4
Name: egos-helpers
Version: 1.4.1
Summary: A python library for helper functions
License-Expression: MIT
License-File: LICENSE
Author: Alex Thomae
Author-email: egos-helpers@egos.tech
Requires-Python: >=3.12
Classifier: Intended Audience :: Developers
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Software Development :: Libraries
Provides-Extra: crypto
Requires-Dist: cryptography (>=50.0.0) ; extra == "crypto"
Requires-Dist: pygelf (==0.4.3)
Project-URL: Homepage, https://gitlab.com/egos-tech/egos-helpers
Project-URL: Source, https://gitlab.com/egos-tech/egos-helpers
Description-Content-Type: text/markdown

# egos-helpers

A python library for helper functions. Used in the [egos-tech](https://gitlab.com/egos-tech) projects.

## Functions

* `gather_environ`: Return a dict of environment variables correlating to the keys dict.
* `get_environ_value`: Resolve a single value from an environment variable or its `_FILE` companion (file-based secrets).
* `short_msg`: Truncates the message to `chars` characters and adds two dots at the end.
* `strtobool`: Converts a string to a boolean
* `redact`: Replaces in `message` the `param` string with `replace_value`
* `key_to_title`: Converts a key in the form `a_is_b` to a title in the form `A Is B`
* `slugify`: Converts a string to a URL-safe slug of at most `max_length` characters
* `setup_logger`: Sets up and returns a logger, optionally with a GELF handler
* `get_formatter`: Builds the log record formatter, which adds source locations at `DEBUG`

See [egos_helpers/core.py](https://gitlab.com/egos-tech/egos-helpers/-/blob/main/egos_helpers/core.py) for the full description of each function.

`egos_helpers.crypto` encrypts values an application has to store. It lives behind
the `crypto` extra, so a plain install does not pull it in. See
[docs/crypto.md](docs/crypto.md).

## Usage example

Install `egos-helpers`:

```sh
python3 -m venv .venv
source .venv/bin/activate
# if you don't have a requirements.txt file
pip install -U egos-helpers
# if you do have a requirements.txt file
pip install -U -r requirements.txt
```

In your python project:

```py
from egos_helpers import gather_environ


class MyClass:
    keys = {
        "key_one": {
            "default": ["one", 2],
            "type": "list",
        },
        "key_two": {
            "hidden": True,
            "default": False,
            "type": "boolean",
        },
        "key_three": {
            "default": {},
            "type": "filter",
        },
        "key_four": {
            "default": None,
            "redact": True,
            "type": "string",
        },
        "key_five": {
            "default": 12,
            "type": "int",
        },
        "key_six": {
            "default": "INFO",
            "type": "enum",
            "values": ["DEBUG", "INFO", "WARNING", "ERROR"],
        },
        "key_seven": {
            "default": "12",
            "deprecated": True,
            "replaced_by": "key_five",
            "type": "int",
        },
    }

    def __init__(self):
        envkeys = gather_environ(keys=MyClass.keys)
        print(envkeys)
```

With `KEY_ONE=one`, `KEY_THREE=foo=bar`, `KEY_FOUR=super_secret_string`, `KEY_FIVE=33`,
`KEY_SIX=WARNING` and the rest unset, `gather_environ` returns:

```py
{
    "key_one": ["one"],
    "key_two": False,
    "key_three": {"foo": "bar"},
    "key_four": "super_secret_string",
    "key_five": 33,
    "key_six": "WARNING",
}
```

`key_seven` is deprecated and unset, so it is left out. A key that is unset returns its
`default` exactly as declared, without being converted to the key's type.

### File-based secrets

Use `get_environ_value` to resolve a value from either an environment variable or a
`<NAME>_FILE` file path (the container secrets convention). It reads `<NAME>_FILE`
first (returning the file contents stripped of surrounding whitespace), falls back
to `<NAME>`, and returns `None` when neither is set. Setting both raises an error.
So does an unreadable `<NAME>_FILE` path.

```py
from egos_helpers import get_environ_value

# MYAPP_TOKEN=secret123           -> "secret123"
# MYAPP_TOKEN_FILE=/run/secrets/t -> contents of the file, stripped
token = get_environ_value("MYAPP_TOKEN")
```

### Encrypted values

A secret the application mints while it runs has to be persisted somewhere, and
`egos_helpers.crypto` keeps it from landing in the store in the clear. Install the extra
with `pip install -U "egos-helpers[crypto]"`.

```py
from egos_helpers.crypto import decode_encryption_key, decrypt_secret_text, encrypt_secret

key = decode_encryption_key(get_environ_value("MYAPP_SECRET_KEY"))
blob = encrypt_secret(key, "the-token")  # bytes, safe to store
token = decrypt_secret_text(key, blob)  # "the-token"
```

Each blob names the key that wrote it, so you can encrypt with a new key and keep
the old one around for reads until nothing needs it.
[docs/crypto.md](docs/crypto.md) covers key replacement, binding a value to where
it is stored, and the blob format.

