Address review feedback: Improve UTC compatibility implementation

- Enhance datetime_compat.py documentation
- Add edge case tests for UTC timezone handling
- Update mock patching in tests
- Fix utcnow usage in sqlite.py

Co-Authored-By: Joe Moura <joao@crewai.com>
This commit is contained in:
Devin AI
2025-02-20 02:00:38 +00:00
parent c6ed4eaaf6
commit 529bdbdd83
4 changed files with 48 additions and 9 deletions

View File

@@ -11,6 +11,7 @@ from typing import Any, Dict, Optional, Union
from pydantic import BaseModel
from crewai.flow.persistence.base import FlowPersistence
from crewai.utilities.datetime_compat import UTC
class SQLiteFlowPersistence(FlowPersistence):
@@ -95,7 +96,7 @@ class SQLiteFlowPersistence(FlowPersistence):
""", (
flow_uuid,
method_name,
datetime.utcnow().isoformat(),
datetime.now(UTC).isoformat(),
json.dumps(state_dict),
))

View File

@@ -1,6 +1,23 @@
"""Compatibility module for datetime functionality across Python versions."""
"""Compatibility module for datetime functionality across Python versions.
This module provides timezone constants that work consistently across different
Python versions, particularly focusing on maintaining compatibility between
Python 3.10 and newer versions.
Notes:
- In Python 3.10, datetime.UTC is not available, so we use timezone.utc
- In Python 3.11+, this provides equivalent functionality to datetime.UTC
- This implementation maintains consistent behavior across versions for
timezone-aware datetime operations
- No known limitations or edge cases between versions
- Safe to use with DST transitions and leap years
- Maintains exact timezone offset (always UTC+00:00)
Example:
>>> from datetime import datetime
>>> from crewai.utilities.datetime_compat import UTC
>>> dt = datetime.now(UTC) # Creates timezone-aware datetime with UTC
"""
from datetime import timezone
# Provide UTC timezone constant that works in Python 3.10+
# This is equivalent to datetime.UTC in Python 3.11+
UTC = timezone.utc
UTC = timezone.utc # Equivalent to datetime.UTC (Python 3.11+)

View File

@@ -917,7 +917,7 @@ def test_tool_result_as_answer_is_the_final_answer_for_the_agent():
@pytest.mark.vcr(filter_headers=["authorization"])
def test_tool_usage_information_is_appended_to_agent():
from datetime import datetime
from datetime import datetime, timezone
from crewai.tools import BaseTool
from crewai.utilities.datetime_compat import UTC
@@ -930,7 +930,7 @@ def test_tool_usage_information_is_appended_to_agent():
return "Howdy!"
fixed_datetime = datetime(2025, 2, 10, 12, 0, 0, tzinfo=UTC)
with patch("crewai.tools.tool_usage.datetime") as mock_datetime:
with patch("crewai.tools.tool_usage.datetime", autospec=True) as mock_datetime:
mock_datetime.now.return_value = fixed_datetime
mock_datetime.fromtimestamp = datetime.fromtimestamp
mock_datetime.side_effect = lambda *args, **kw: datetime(*args, **kw)

View File

@@ -1,5 +1,5 @@
"""Test datetime compatibility module."""
from datetime import timezone
from datetime import datetime, timedelta, timezone
from crewai.utilities.datetime_compat import UTC
@@ -9,6 +9,27 @@ def test_utc_timezone_compatibility():
assert UTC == timezone.utc
assert UTC.tzname(None) == "UTC"
# Verify it works with datetime.now()
from datetime import datetime
dt = datetime.now(UTC)
assert dt.tzinfo == timezone.utc
def test_utc_timezone_edge_cases():
"""Test UTC timezone handling in edge cases."""
# Test with leap year
leap_date = datetime(2024, 2, 29, tzinfo=UTC)
assert leap_date.tzinfo == timezone.utc
# Test DST transition dates
dst_date = datetime(2024, 3, 10, 2, 0, tzinfo=UTC) # US DST start
assert dst_date.tzinfo == timezone.utc
# Test with minimum/maximum dates
min_date = datetime.min.replace(tzinfo=UTC)
max_date = datetime.max.replace(tzinfo=UTC)
assert min_date.tzinfo == timezone.utc
assert max_date.tzinfo == timezone.utc
# Test timezone offset calculations
dt = datetime(2024, 1, 1, tzinfo=UTC)
offset = dt.utcoffset()
assert offset == timedelta(0) # UTC should always have zero offset