Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions src/guidellm/benchmark/aggregator.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@
GenerativeTextResponseStats,
)
from guidellm.config import settings
from guidellm.objects import (
RunningStats,
TimeRunningStats,
)
from guidellm.request import (
GenerationRequest,
GenerativeRequestLoaderDescription,
Expand All @@ -38,7 +34,13 @@
SchedulerRequestResult,
WorkerDescription,
)
from guidellm.utils import StandardBaseModel, StatusBreakdown, check_load_processor
from guidellm.utils import (
RunningStats,
StandardBaseModel,
StatusBreakdown,
TimeRunningStats,
check_load_processor,
)

__all__ = [
"AggregatorT",
Expand Down
9 changes: 5 additions & 4 deletions src/guidellm/benchmark/benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@
SynchronousProfile,
ThroughputProfile,
)
from guidellm.objects import (
StatusDistributionSummary,
)
from guidellm.request import (
GenerativeRequestLoaderDescription,
RequestLoaderDescription,
Expand All @@ -30,7 +27,11 @@
ThroughputStrategy,
WorkerDescription,
)
from guidellm.utils import StandardBaseModel, StatusBreakdown
from guidellm.utils import (
StandardBaseModel,
StatusBreakdown,
StatusDistributionSummary,
)

__all__ = [
"Benchmark",
Expand Down
12 changes: 7 additions & 5 deletions src/guidellm/benchmark/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@
ThroughputProfile,
)
from guidellm.config import settings
from guidellm.objects import (
DistributionSummary,
StatusDistributionSummary,
)
from guidellm.presentation import UIDataBuilder
from guidellm.presentation.injector import create_report
from guidellm.scheduler import strategy_display_str
from guidellm.utils import Colors, StandardBaseModel, split_text_list_by_length
from guidellm.utils import (
Colors,
DistributionSummary,
StandardBaseModel,
StatusDistributionSummary,
split_text_list_by_length,
)

__all__ = [
"GenerativeBenchmarksConsole",
Expand Down
15 changes: 0 additions & 15 deletions src/guidellm/objects/__init__.py

This file was deleted.

2 changes: 1 addition & 1 deletion src/guidellm/presentation/data_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
if TYPE_CHECKING:
from guidellm.benchmark.benchmark import GenerativeBenchmark

from guidellm.objects.statistics import DistributionSummary
from guidellm.utils.statistics import DistributionSummary


class Bucket(BaseModel):
Expand Down
30 changes: 28 additions & 2 deletions src/guidellm/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
from .auto_importer import AutoImporterMixin
from .colors import Colors
from .default_group import DefaultGroupHandler
from .functions import (
all_defined,
safe_add,
safe_divide,
safe_format_timestamp,
safe_getattr,
safe_multiply,
)
from .hf_datasets import (
SUPPORTED_TYPES,
save_dataset_to_file,
Expand All @@ -18,11 +26,18 @@
from .random import IntegerRangeSampler
from .registry import RegistryMixin
from .singleton import SingletonMixin, ThreadSafeSingletonMixin
from .statistics import (
DistributionSummary,
Percentiles,
RunningStats,
StatusDistributionSummary,
TimeRunningStats,
)
from .text import (
EndlessTextCreator,
clean_text,
filter_text,
is_puncutation,
is_punctuation,
load_text,
split_text,
split_text_list_by_length,
Expand All @@ -33,21 +48,32 @@
"AutoImporterMixin",
"Colors",
"DefaultGroupHandler",
"DistributionSummary",
"EndlessTextCreator",
"IntegerRangeSampler",
"Percentiles",
"PydanticClassRegistryMixin",
"RegistryMixin",
"ReloadableBaseModel",
"RunningStats",
"SingletonMixin",
"StandardBaseDict",
"StandardBaseModel",
"StatusBreakdown",
"StatusDistributionSummary",
"ThreadSafeSingletonMixin",
"TimeRunningStats",
"all_defined",
"check_load_processor",
"clean_text",
"filter_text",
"is_puncutation",
"is_punctuation",
"load_text",
"safe_add",
"safe_divide",
"safe_format_timestamp",
"safe_getattr",
"safe_multiply",
"save_dataset_to_file",
"split_text",
"split_text_list_by_length",
Expand Down
130 changes: 130 additions & 0 deletions src/guidellm/utils/functions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
"""
Utility functions for safe operations and value handling.

Provides defensive programming utilities for common operations that may encounter
None values, invalid inputs, or edge cases. Includes safe arithmetic operations,
attribute access, and timestamp formatting.
"""

from __future__ import annotations

from datetime import datetime
from typing import Any

__all__ = [
"all_defined",
"safe_add",
"safe_divide",
"safe_format_timestamp",
"safe_getattr",
"safe_multiply",
]


def safe_getattr(obj: Any | None, attr: str, default: Any = None) -> Any:
"""
Safely get an attribute from an object with None handling.

:param obj: Object to get the attribute from, or None
:param attr: Name of the attribute to retrieve
:param default: Value to return if object is None or attribute doesn't exist
:return: Attribute value or default if not found or object is None
"""
if obj is None:
return default

return getattr(obj, attr, default)


def all_defined(*values: Any | None) -> bool:
"""
Check if all provided values are defined (not None).

:param values: Variable number of values to check for None
:return: True if all values are not None, False otherwise
"""
return all(value is not None for value in values)


def safe_divide(
numerator: int | float | None,
denominator: int | float | None,
num_default: float = 0.0,
den_default: float = 1.0,
) -> float:
"""
Safely divide two numbers with None handling and zero protection.

:param numerator: Number to divide, or None to use num_default
:param denominator: Number to divide by, or None to use den_default
:param num_default: Default value for numerator if None
:param den_default: Default value for denominator if None
:return: Division result with protection against division by zero
"""
numerator = numerator if numerator is not None else num_default
denominator = denominator if denominator is not None else den_default

return numerator / (denominator or 1e-10)


def safe_multiply(*values: int | float | None, default: float = 1.0) -> float:
"""
Safely multiply multiple numbers with None handling.

:param values: Variable number of values to multiply, None values treated as 1.0
:param default: Starting value for multiplication
:return: Product of all non-None values multiplied by default
"""
result = default
for val in values:
result *= val if val is not None else 1.0
return result


def safe_add(
*values: int | float | None, signs: list[int] | None = None, default: float = 0.0
) -> float:
"""
Safely add multiple numbers with None handling and optional signs.

:param values: Variable number of values to add, None values use default
:param signs: Optional list of 1 (add) or -1 (subtract) for each value.
If None, all values are added. Must match length of values.
:param default: Value to substitute for None values
:return: Result of adding all values safely (default used when value is None)
"""
if not values:
return default

values = list(values)

if signs is None:
signs = [1] * len(values)

if len(signs) != len(values):
raise ValueError("Length of signs must match length of values")

result = values[0] if values[0] is not None else default

for ind in range(1, len(values)):
val = values[ind] if values[ind] is not None else default
result += signs[ind] * val

return result


def safe_format_timestamp(
timestamp: float | None, format_: str = "%H:%M:%S", default: str = "N/A"
) -> str:
"""
Safely format a timestamp with error handling and validation.

:param timestamp: Unix timestamp to format, or None
:param format_: Strftime format string for timestamp formatting
:param default: Value to return if timestamp is invalid or None
:return: Formatted timestamp string or default value
"""
try:
return datetime.fromtimestamp(timestamp).strftime(format_)
except (ValueError, TypeError, OverflowError, OSError):
return default
Loading
Loading