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.4.4.tar.gz (9.9 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.4.4-py3-none-any.whl (8.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: eo4eu_base_utils-0.4.4.tar.gz
  • Upload date:
  • Size: 9.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.11.11

File hashes

Hashes for eo4eu_base_utils-0.4.4.tar.gz
Algorithm Hash digest
SHA256 6bff3de90e05bf95f7afe46ecdf87d1bc8ab43e70b260452963041a5c21d7182
MD5 ded776302b278ea35ed524e78a92d219
BLAKE2b-256 a37f7fdfa30e0693a30ee170bc1a867ac68977d24cd02451f0501d5f8f64b9b1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for eo4eu_base_utils-0.4.4-py3-none-any.whl
Algorithm Hash digest
SHA256 c501e4e335c78a836bf1bbab3092d8c46c0a37447e6ba336e3bf22f4c747e4fe
MD5 6de7afb9e3c8a9f636099ebbb2da63d5
BLAKE2b-256 9a84b1e2be934bb76d4fae655ccb40fd27261443bcf702f1a679bc10b2a971d3

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