Skip to main content

General utilities for EO4EU

Project description

Base utilities for EO4EU

This package serves as a common base of utilities used in other eo4eu-[...]-utils packages. You may find it generally useful.

General

  • The if_none function helps with the writing of optional parameters. For example:
def validate(input: str, accepted: list[str]|None = None):
    accepted = if_none(accepted, ["yes", "definitely", "absolutely"])
    if input not in accepted:
        raise ValueError(f"Input \"{input}\" not in {accepted}")

Typing

The eo4eu_base_utils.typing submodule provides some of the types found in the standard library typing module. The difference is, for versions below 3.10, this module will pull them from typing_extensions instead.

Unify

The eo4eu_base_utils.unify submodule provides functions for working with dictionaries. Namely:

  • overlay combines two dictionaries recursively, preserving nested keys if possible. In the case of conflicts, overlay will prefer the second dictionary provided. Example:
from pprint import pprint
from eo4eu_base_utils.unify import overlay

h0 = {
    "name": "bobby.png",
    "dataset": "hamster images",
    "date": None,
    "metadata": {
        "size": "3TB",
        "color": "brown",
    },
}
h1 = {
    "path": "/usr/hamsters/bobby.png",
    "date": "2025-14-01",
    "metadata": {
        "color": "brown and white, actually",
        "type": "chubby",
    },
}

pprint(overlay(h0, h1))

Output:

{'dataset': 'hamster images',
 'date': '2025-14-01',
 'metadata': {'color': 'brown and white, actually',
              'size': '3TB',
              'type': 'chubby'},
 'name': 'bobby.png',
 'path': '/usr/hamsters/bobby.png'}
  • unify is similar to overlay, but raises a eo4eu_base_utils.unify.UnifyError in the case of conflicts. This function has a more general notion of values being "compatible"; one or both of the dictionaries might have types as values, thus serving as more of a schema. An example:
from pprint import pprint
from eo4eu_base_utils.unify import overlay

schema = {
    "service": "elasticsearch",
    "auth": {
        "username": str,
        "password": str,
    },
    "port": int,
}

good_data = {
    "service": "elasticsearch",
    "mood": "good",
    "auth": {
        "username": "buddy",
        "password": "pasword",
    },
    "port": 6868,
}

also_good_data = {  # doesn't matter if keys are missing
    "auth": {
        "username": "buddy",
    },
}

bad_data = {
    "auth": {
        "username": 007,  # not a string
    },
}

pprint(unify(schema, good_data))
pprint(unify(schema, also_good_data))
pprint(unify(schema, bad_data))  # this will raise an error

unify is commutative, therefore unify(d0, d1) == unify(d1, d0).

Result

The Result type is a hacky attempt to get something like rust's Result type, and have errors as values instead of exceptions. It has several constructors:

def parse_num(num_str: str) -> Result[float]:
    try:
        return Result.ok(float(num_str))
    except Exception as e:
        return Result.err(str(e))

The above function may also be written as:

def parse_num(num_str: str) -> Result[float]:
    return Result.wrap(float, num_str)

The Result type allows you to do a few neat things. For example, instead of this pattern:

config = None
try:
    config = read_from_file(config_file)
except Exception as e:
    logger.error(f"Failed to read config: {e}")

You can do this:

config = read_from_file(config_file)  # returns Result
if config.is_err():
    logger.error(f"Failed to read config: {config.fmt_err()}")

There is also result.is_ok() which is the opposite of result.is_err(). Also, things like:

some_num = (Result.wrap(get_user_input)
                  .default("7")
                  .map_ok(lambda num_str: float(num_str))
                  .map_ok(lambda num: num if num > 0 else 0)
                  .unwrap())  # this raises an exception if the result is an error

Which would normally be written as:

def get_some_num():
    user_input = "7"
    try:
        user_input = get_user_input()
    except Exception:
        pass

    num = float(user_input)
    if num < 0:
        num = 0
    return num

Possibly a bad example, but anyway...

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

eo4eu_base_utils-0.6.0.tar.gz (11.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

eo4eu_base_utils-0.6.0-py3-none-any.whl (10.9 kB view details)

Uploaded Python 3

File details

Details for the file eo4eu_base_utils-0.6.0.tar.gz.

File metadata

  • Download URL: eo4eu_base_utils-0.6.0.tar.gz
  • Upload date:
  • Size: 11.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.8

File hashes

Hashes for eo4eu_base_utils-0.6.0.tar.gz
Algorithm Hash digest
SHA256 e425e792b68b9c4cef51fc4ac2940e772f5ae749c793e019122b6387097d52dd
MD5 115fb10777b384404bef91ed4f25279e
BLAKE2b-256 a283987c1193fa47f31beae2fca6c9b8ca3640ea49c8d7836eeec6e45cfdd4d9

See more details on using hashes here.

File details

Details for the file eo4eu_base_utils-0.6.0-py3-none-any.whl.

File metadata

File hashes

Hashes for eo4eu_base_utils-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5aba7485f0b60bad94cf289059aabebe69869fd148bfdf30dc4e38207d624eaa
MD5 d6f639402ecaee313e0213ce1c0f244e
BLAKE2b-256 291f487ccad37ec87a7a471076fe4c7d3be20f3edbc2f7b148e52fed203feb5f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page