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 pydantic import BaseModel
from crewai.flow.persistence.base import FlowPersistence from crewai.flow.persistence.base import FlowPersistence
from crewai.utilities.datetime_compat import UTC
class SQLiteFlowPersistence(FlowPersistence): class SQLiteFlowPersistence(FlowPersistence):
@@ -95,7 +96,7 @@ class SQLiteFlowPersistence(FlowPersistence):
""", ( """, (
flow_uuid, flow_uuid,
method_name, method_name,
datetime.utcnow().isoformat(), datetime.now(UTC).isoformat(),
json.dumps(state_dict), 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 from datetime import timezone
# Provide UTC timezone constant that works in Python 3.10+ UTC = timezone.utc # Equivalent to datetime.UTC (Python 3.11+)
# This is equivalent to datetime.UTC in Python 3.11+
UTC = timezone.utc

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"]) @pytest.mark.vcr(filter_headers=["authorization"])
def test_tool_usage_information_is_appended_to_agent(): 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.tools import BaseTool
from crewai.utilities.datetime_compat import UTC from crewai.utilities.datetime_compat import UTC
@@ -930,7 +930,7 @@ def test_tool_usage_information_is_appended_to_agent():
return "Howdy!" return "Howdy!"
fixed_datetime = datetime(2025, 2, 10, 12, 0, 0, tzinfo=UTC) 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.now.return_value = fixed_datetime
mock_datetime.fromtimestamp = datetime.fromtimestamp mock_datetime.fromtimestamp = datetime.fromtimestamp
mock_datetime.side_effect = lambda *args, **kw: datetime(*args, **kw) mock_datetime.side_effect = lambda *args, **kw: datetime(*args, **kw)

View File

@@ -1,5 +1,5 @@
"""Test datetime compatibility module.""" """Test datetime compatibility module."""
from datetime import timezone from datetime import datetime, timedelta, timezone
from crewai.utilities.datetime_compat import UTC from crewai.utilities.datetime_compat import UTC
@@ -9,6 +9,27 @@ def test_utc_timezone_compatibility():
assert UTC == timezone.utc assert UTC == timezone.utc
assert UTC.tzname(None) == "UTC" assert UTC.tzname(None) == "UTC"
# Verify it works with datetime.now() # Verify it works with datetime.now()
from datetime import datetime
dt = datetime.now(UTC) dt = datetime.now(UTC)
assert dt.tzinfo == timezone.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