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.1.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.1-py3-none-any.whl (8.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: eo4eu_base_utils-0.4.1.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.1.tar.gz
Algorithm Hash digest
SHA256 82a90c96befa371cd759ff5d3756a075c4014f24e9bd274c68a99f99a9dc2146
MD5 6881e0eb8f0dab44322dd8a5d70fb20b
BLAKE2b-256 9c3628914da0d1235fa7e4cd19c3fe197556a76684e64a392349f67d11b419e8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for eo4eu_base_utils-0.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 2a9b8630c01171f620b797f37d30084f236616d763c0d543fe6750327dc99ba9
MD5 d0b6d8ae3c2fc775f236000a82369ce0
BLAKE2b-256 2ce7b5fef28ad338e78968f129f494e4e94168851aacb446ebc2864214beaa19

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