diff --git a/README.md b/README.md index 437a8bb..bafe1e6 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,14 @@ ## Introduction -Core utilities to complement Python's standard library. +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. -## Documentation - -For information on how to use this library, please refer to the -[documentation](https://frequenz-floss.github.io/frequenz-core-python/). +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 @@ -21,6 +23,130 @@ The following platforms are officially supported (tested): - **Operating System:** Ubuntu Linux 20.04 - **Architectures:** amd64, arm64 +## Installation + +You can install the library from PyPI using pip: + +```bash +python -m pip install frequenz-core +``` + +Or add it to your project's dependencies in `pyproject.toml`: + +```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](https://semver.org/). + +## Quick Start + +Here's a quick overview of the main functionality: + +```python +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: + +```python +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 +``` + +### Typing Utilities + +Disable class constructors to enforce factory pattern usage: + +```python +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: + +```python +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](https://frequenz-floss.github.io/frequenz-core-python/). + ## Contributing If you want to know how to build this project and contribute to it, please