Collection of common python utils for machine learning and scientific computing workflows
—
Collection of general-purpose Python utilities including environment detection, iteration helpers, text processing, error handling, lazy imports, and language feature enhancements for robust Python development.
Utilities for detecting the current Python execution environment.
def is_notebook() -> bool:
"""
Detect if running in a Jupyter notebook environment.
Returns:
True if running in Jupyter notebook, False otherwise
"""
def is_test() -> bool:
"""
Detect if running in a test environment.
Returns:
True if running in test context, False otherwise
"""Advanced import utilities for lazy loading and module management.
def lazy_imports(**modules) -> Any:
"""
Create lazy import proxy objects for deferred loading.
Args:
**modules: Module names and import paths
Returns:
Lazy import proxy object
Example:
np = lazy_imports(numpy='numpy')
# numpy only imported when first used
"""
def lazy_api_imports(**api_modules) -> Any:
"""
Create lazy API import utilities for modular APIs.
Args:
**api_modules: API module definitions
Returns:
Lazy API import system
"""
def binary_adhoc(module_path: str) -> Any:
"""
Import binary modules ad-hoc for specialized use cases.
Args:
module_path: Path to binary module
Returns:
Imported binary module
"""Enhanced iteration functions for data processing.
def groupby(
iterable: Iterable[T],
key: Callable[[T], K] | None = None
) -> dict[K, list[T]]:
"""
Group iterable elements by key function.
Args:
iterable: Items to group
key: Function to generate grouping key
Returns:
Dictionary mapping keys to grouped items
"""
def splitby(
iterable: Iterable[T],
condition: Callable[[T], bool]
) -> tuple[list[T], list[T]]:
"""
Split iterable into two lists based on condition.
Args:
iterable: Items to split
condition: Function returning True/False for each item
Returns:
Tuple of (items_matching, items_not_matching)
"""
def zip_dict(*dicts: dict) -> dict[Any, tuple]:
"""
Zip multiple dictionaries by matching keys.
Args:
*dicts: Dictionaries to zip together
Returns:
Dictionary with keys mapped to tuples of values
"""Utilities for enhancing Python language features.
def frozen(cls: type) -> type:
"""
Decorator to make class instances immutable.
Args:
cls: Class to make frozen
Returns:
Frozen class where instances cannot be modified
"""
def is_namedtuple(obj: Any) -> bool:
"""
Check if object is a named tuple.
Args:
obj: Object to check
Returns:
True if object is a named tuple, False otherwise
"""
def issubclass(obj: Any, base: type) -> bool:
"""
Safe subclass checking that handles non-class objects.
Args:
obj: Object to check
base: Base class to check against
Returns:
True if obj is subclass of base, False otherwise
"""
def wraps_cls(cls: type) -> Callable:
"""
Class-based version of functools.wraps.
Args:
cls: Class to wrap
Returns:
Decorator function for wrapping classes
"""
class StrEnum(str, Enum):
"""
String enumeration that inherits from both str and Enum.
Allows enum values to be used as strings while maintaining enum benefits.
"""
passEnhanced context management utilities.
class ContextManager:
"""
Enhanced context manager with additional functionality.
"""
def __init__(self, enter_fn: Callable, exit_fn: Callable) -> None: ...
def __enter__(self) -> Any: ...
def __exit__(self, exc_type, exc_val, exc_tb) -> None: ...
class ExitStack:
"""
Enhanced exit stack for managing multiple context managers.
"""
def __init__(self) -> None: ...
def enter_context(self, cm: Any) -> Any: ...
def push(self, exit_fn: Callable) -> None: ...
def close(self) -> None: ...Utilities for enhanced error handling and exception management.
def reraise(
exception: Exception,
message: str | None = None
) -> NoReturn:
"""
Reraise exception with optional additional message.
Args:
exception: Exception to reraise
message: Additional message to include
Raises:
The provided exception with enhanced context
"""
def maybe_reraise(
exception: Exception,
condition: bool,
message: str | None = None
) -> None:
"""
Conditionally reraise exception based on condition.
Args:
exception: Exception to potentially reraise
condition: Whether to reraise the exception
message: Additional message if reraising
Raises:
The provided exception if condition is True
"""Text manipulation and formatting utilities.
def dedent(text: str) -> str:
"""
Remove leading whitespace from text while preserving relative indentation.
Args:
text: Text to dedent
Returns:
Dedented text
"""
def diff_str(str1: str, str2: str) -> str:
"""
Generate visual diff between two strings.
Args:
str1: First string
str2: Second string
Returns:
String showing differences between inputs
"""
def pprint(obj: Any, **kwargs) -> None:
"""
Pretty print object with enhanced formatting.
Args:
obj: Object to pretty print
**kwargs: Additional formatting options
"""
def pretty_repr(obj: Any) -> str:
"""
Generate pretty string representation of object.
Args:
obj: Object to represent
Returns:
Pretty string representation
"""
def pretty_repr_top_level(obj: Any) -> str:
"""
Generate pretty representation for top-level objects.
Args:
obj: Object to represent
Returns:
Top-level pretty representation
"""
class Lines:
"""
Utility class for manipulating text lines.
"""
def __init__(self, lines: list[str] | str) -> None: ...
def __str__(self) -> str: ...
def __len__(self) -> int: ...
def append(self, line: str) -> None: ...
def join(self, separator: str = '\\n') -> str: ...Advanced regex utilities for text processing.
def reverse_fstring(
template: str,
text: str
) -> dict[str, str]:
"""
Reverse f-string formatting to extract values.
Args:
template: F-string template (e.g., "Hello {name}, age {age}")
text: Formatted text (e.g., "Hello Alice, age 25")
Returns:
Dictionary of extracted values (e.g., {"name": "Alice", "age": "25"})
"""Additional modules providing specialized functionality.
_internal: ModuleType # Internal utilities module
typing: ModuleType # Enhanced typing utilities
testing: ModuleType # Testing utilities (when pytest available)from etils import epy
# Detect execution environment
if epy.is_notebook():
print("Running in Jupyter notebook")
# Use notebook-specific features
from IPython.display import display
else:
print("Running in regular Python")
if epy.is_test():
print("Running in test environment")
# Use test-specific configurations
DEBUG = True
else:
DEBUG = Falsefrom etils import epy
# Lazy import expensive modules
lazy_modules = epy.lazy_imports(
np='numpy',
pd='pandas',
plt='matplotlib.pyplot'
)
# Modules only imported when first accessed
data = lazy_modules.np.array([1, 2, 3]) # numpy imported here
df = lazy_modules.pd.DataFrame(data) # pandas imported here
# Lazy API imports for modular systems
api = epy.lazy_api_imports(
vision='my_package.vision',
nlp='my_package.nlp'
)from etils import epy
# Group items by category
items = [
{'name': 'apple', 'type': 'fruit'},
{'name': 'carrot', 'type': 'vegetable'},
{'name': 'banana', 'type': 'fruit'},
{'name': 'broccoli', 'type': 'vegetable'}
]
grouped = epy.groupby(items, key=lambda x: x['type'])
# Result: {
# 'fruit': [{'name': 'apple', 'type': 'fruit'}, {'name': 'banana', 'type': 'fruit'}],
# 'vegetable': [{'name': 'carrot', 'type': 'vegetable'}, {'name': 'broccoli', 'type': 'vegetable'}]
# }
# Split by condition
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens, odds = epy.splitby(numbers, lambda x: x % 2 == 0)
# evens: [2, 4, 6, 8, 10], odds: [1, 3, 5, 7, 9]
# Zip dictionaries
dict1 = {'a': 1, 'b': 2, 'c': 3}
dict2 = {'a': 'x', 'b': 'y', 'c': 'z'}
zipped = epy.zip_dict(dict1, dict2)
# Result: {'a': (1, 'x'), 'b': (2, 'y'), 'c': (3, 'z')}from etils import epy
# Create immutable classes
@epy.frozen
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
point = Point(1, 2)
# point.x = 3 # Would raise error - object is frozen
# String enums
class Color(epy.StrEnum):
RED = 'red'
GREEN = 'green'
BLUE = 'blue'
# Can use as string or enum
color = Color.RED
print(f"Color: {color}") # Works as string
assert color == 'red' # String comparison works
# Safe subclass checking
class Animal: pass
class Dog(Animal): pass
assert epy.issubclass(Dog, Animal) # True
assert not epy.issubclass("not a class", Animal) # False, no error
# Named tuple detection
from collections import namedtuple
Person = namedtuple('Person', ['name', 'age'])
person = Person('Alice', 25)
assert epy.is_namedtuple(person) # True
assert not epy.is_namedtuple({'name': 'Bob'}) # Falsefrom etils import epy
def risky_operation(data):
try:
return process_data(data)
except ValueError as e:
# Reraise with additional context
epy.reraise(e, "Failed to process data in risky_operation")
def conditional_error_handling(data, strict_mode=False):
try:
return validate_data(data)
except ValidationError as e:
# Only reraise in strict mode
epy.maybe_reraise(e, strict_mode, "Validation failed in strict mode")
return None # Return None if not strictfrom etils import epy
# Dedent multi-line strings
code = '''
def hello():
print("Hello, world!")
return True
'''
clean_code = epy.dedent(code)
# Removes leading whitespace while preserving structure
# Pretty printing
complex_data = {
'model': {'layers': [64, 128, 256], 'dropout': 0.1},
'training': {'epochs': 100, 'batch_size': 32}
}
epy.pprint(complex_data) # Enhanced pretty printing
# String diffing
old_text = "The quick brown fox"
new_text = "The quick red fox"
diff = epy.diff_str(old_text, new_text)
print(diff) # Shows differences visually
# Reverse f-strings
template = "Hello {name}, you are {age} years old"
text = "Hello Alice, you are 25 years old"
values = epy.reverse_fstring(template, text)
# Result: {'name': 'Alice', 'age': '25'}from etils import epy
# Enhanced context manager
def my_context_manager():
print("Entering context")
try:
yield "context value"
finally:
print("Exiting context")
with epy.ContextManager(
enter_fn=lambda: print("Setup"),
exit_fn=lambda: print("Cleanup")
):
print("In context")
# Exit stack for multiple resources
with epy.ExitStack() as stack:
file1 = stack.enter_context(open('file1.txt'))
file2 = stack.enter_context(open('file2.txt'))
# Both files automatically closedfrom etils import epy
# Work with text lines
lines = epy.Lines([
"Line 1",
"Line 2",
"Line 3"
])
lines.append("Line 4")
text = lines.join('\\n') # Join with newlines
print(f"Total lines: {len(lines)}")
# From string
content = "Line A\\nLine B\\nLine C"
lines = epy.Lines(content)
# Automatically splits on newlinesInstall with Tessl CLI
npx tessl i tessl/pypi-etils