Skip to content

Frequenz Core Library¤

Build Status PyPI Package Docs

Introduction¤

Core utilities to complement Python's standard library. This library provides essential building blocks for Python applications, including mathematical utilities, datetime constants, typing helpers, strongly-typed identifiers, and module introspection tools.

The frequenz-core library is designed to be lightweight, type-safe, and follow modern Python best practices. It fills common gaps in the standard library with utilities that are frequently needed across different projects.

Supported Platforms¤

The following platforms are officially supported (tested):

  • Python: 3.11
  • Operating System: Ubuntu Linux 20.04
  • Architectures: amd64, arm64

Installation¤

You can install the library from PyPI using pip:

python -m pip install frequenz-core

Or add it to your project's dependencies in pyproject.toml:

[project]
dependencies = [
    "frequenz-core >= 1.0.2, < 2",
]

[!NOTE] We recommend pinning the dependency to the latest version for programs, like "frequenz-core == 1.0.2", and specifying a version range spanning one major version for libraries, like "frequenz-core >= 1.0.2, < 2". We follow semver.

Quick Start¤

Here's a quick overview of the main functionality:

from frequenz.core.math import is_close_to_zero, Interval
from frequenz.core.datetime import UNIX_EPOCH
from frequenz.core.module import get_public_module_name

# Math utilities
print(is_close_to_zero(1e-10))  # True - check if float is close to zero
interval = Interval(1, 10)
print(5 in interval)  # True - check if value is in range

# Datetime utilities
print(UNIX_EPOCH)  # 1970-01-01 00:00:00+00:00

# Module utilities
public_name = get_public_module_name("my.package._private.module")
print(public_name)  # "my.package"

Code Examples¤

Math Utilities¤

The math module provides utilities for floating-point comparisons and interval checking:

from frequenz.core.math import is_close_to_zero, Interval

# Robust floating-point zero comparison
assert is_close_to_zero(1e-10)  # True
assert not is_close_to_zero(0.1)  # False

# Interval checking with inclusive bounds
numbers = Interval(0, 100)
assert 50 in numbers  # True
assert not (150 in numbers)  # False - 150 is outside the interval

# Unbounded intervals
positive = Interval(0, None)  # [0, ∞]
assert 1000 in positive  # True

Enum with deprecated members¤

Define enums with deprecated members that raise deprecation warnings when accessed:

from frequenz.core.enum import Enum, DeprecatedMember

class TaskStatus(Enum):
   OPEN = 1
   IN_PROGRESS = 2
   PENDING = DeprecatedMember(1, "PENDING is deprecated, use OPEN instead")
   DONE = DeprecatedMember(3, "DONE is deprecated, use FINISHED instead")
   FINISHED = 4

status1 = TaskStatus.PENDING  # Warns: "PENDING is deprecated, use OPEN instead"
assert status1 is TaskStatus.OPEN

Typing Utilities¤

Disable class constructors to enforce factory pattern usage:

from frequenz.core.typing import disable_init

@disable_init
class ApiClient:
    @classmethod
    def create(cls, api_key: str) -> "ApiClient":
        # Factory method with validation
        instance = cls.__new__(cls)
        # Custom initialization logic here
        return instance

# This will raise TypeError:
# client = ApiClient()  # ❌ TypeError

# Use factory method instead:
client = ApiClient.create("my-api-key")  # ✅ Works

Strongly-Typed IDs¤

Create type-safe identifiers for different entities:

from frequenz.core.id import BaseId

class UserId(BaseId, str_prefix="USR"):
    pass

class OrderId(BaseId, str_prefix="ORD"):
    pass

user_id = UserId(123)
order_id = OrderId(456)

print(f"User: {user_id}")  # User: USR123
print(f"Order: {order_id}")  # Order: ORD456

# Type safety prevents mixing different ID types
def process_user(user_id: UserId) -> None:
    print(f"Processing user: {user_id}")

process_user(user_id)  # ✅ Works
# process_user(order_id)  # ❌ Type error

Documentation¤

For information on how to use this library, please refer to the documentation.

Contributing¤

If you want to know how to build this project and contribute to it, please check out the Contributing Guide.