Skip to content

Commit edc630d

Browse files
committed
Replace datetime.utcnow with datetime.now(timezone.utc)
Signed-off-by: Madhav Kandukuri <[email protected]>
1 parent 37ec635 commit edc630d

File tree

15 files changed

+122
-116
lines changed

15 files changed

+122
-116
lines changed

mcpgateway/db.py

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@
105105
connect_args=connect_args,
106106
)
107107

108+
# ---------------------------------------------------------------------------
109+
# 6. Function to return UTC timestamp
110+
# ---------------------------------------------------------------------------
111+
def utc_now():
112+
return datetime.now(timezone.utc)
113+
108114
# Session factory
109115
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
110116

@@ -181,7 +187,7 @@ class ToolMetric(Base):
181187

182188
id: Mapped[int] = mapped_column(primary_key=True)
183189
tool_id: Mapped[str] = mapped_column(String, ForeignKey("tools.id"), nullable=False)
184-
timestamp: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
190+
timestamp: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now)
185191
response_time: Mapped[float] = mapped_column(Float, nullable=False)
186192
is_success: Mapped[bool] = mapped_column(Boolean, nullable=False)
187193
error_message: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
@@ -207,7 +213,7 @@ class ResourceMetric(Base):
207213

208214
id: Mapped[int] = mapped_column(primary_key=True)
209215
resource_id: Mapped[int] = mapped_column(Integer, ForeignKey("resources.id"), nullable=False)
210-
timestamp: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
216+
timestamp: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now)
211217
response_time: Mapped[float] = mapped_column(Float, nullable=False)
212218
is_success: Mapped[bool] = mapped_column(Boolean, nullable=False)
213219
error_message: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
@@ -233,7 +239,7 @@ class ServerMetric(Base):
233239

234240
id: Mapped[int] = mapped_column(primary_key=True)
235241
server_id: Mapped[str] = mapped_column(String, ForeignKey("servers.id"), nullable=False)
236-
timestamp: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
242+
timestamp: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now)
237243
response_time: Mapped[float] = mapped_column(Float, nullable=False)
238244
is_success: Mapped[bool] = mapped_column(Boolean, nullable=False)
239245
error_message: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
@@ -259,7 +265,7 @@ class PromptMetric(Base):
259265

260266
id: Mapped[int] = mapped_column(primary_key=True)
261267
prompt_id: Mapped[int] = mapped_column(Integer, ForeignKey("prompts.id"), nullable=False)
262-
timestamp: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
268+
timestamp: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now)
263269
response_time: Mapped[float] = mapped_column(Float, nullable=False)
264270
is_success: Mapped[bool] = mapped_column(Boolean, nullable=False)
265271
error_message: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
@@ -312,8 +318,8 @@ class Tool(Base):
312318
headers: Mapped[Optional[Dict[str, str]]] = mapped_column(JSON)
313319
input_schema: Mapped[Dict[str, Any]] = mapped_column(JSON)
314320
annotations: Mapped[Optional[Dict[str, Any]]] = mapped_column(JSON, default=lambda: {})
315-
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
316-
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
321+
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now)
322+
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now, onupdate=utc_now)
317323
is_active: Mapped[bool] = mapped_column(default=True)
318324
jsonpath_filter: Mapped[str] = mapped_column(default="")
319325

@@ -557,8 +563,8 @@ class Resource(Base):
557563
mime_type: Mapped[Optional[str]]
558564
size: Mapped[Optional[int]]
559565
template: Mapped[Optional[str]] # URI template for parameterized resources
560-
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
561-
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
566+
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now)
567+
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now, onupdate=utc_now)
562568
is_active: Mapped[bool] = mapped_column(default=True)
563569
metrics: Mapped[List["ResourceMetric"]] = relationship("ResourceMetric", back_populates="resource", cascade="all, delete-orphan")
564570

@@ -714,7 +720,7 @@ class ResourceSubscription(Base):
714720
id: Mapped[int] = mapped_column(primary_key=True)
715721
resource_id: Mapped[int] = mapped_column(ForeignKey("resources.id"))
716722
subscriber_id: Mapped[str] # Client identifier
717-
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
723+
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now)
718724
last_notification: Mapped[Optional[datetime]] = mapped_column(DateTime)
719725

720726
resource: Mapped["Resource"] = relationship(back_populates="subscriptions")
@@ -745,8 +751,8 @@ class Prompt(Base):
745751
description: Mapped[Optional[str]]
746752
template: Mapped[str] = mapped_column(Text)
747753
argument_schema: Mapped[Dict[str, Any]] = mapped_column(JSON)
748-
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
749-
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
754+
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now)
755+
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now, onupdate=utc_now)
750756
is_active: Mapped[bool] = mapped_column(default=True)
751757
metrics: Mapped[List["PromptMetric"]] = relationship("PromptMetric", back_populates="prompt", cascade="all, delete-orphan")
752758

@@ -894,8 +900,8 @@ class Server(Base):
894900
name: Mapped[str] = mapped_column(unique=True)
895901
description: Mapped[Optional[str]]
896902
icon: Mapped[Optional[str]]
897-
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
898-
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
903+
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now)
904+
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now, onupdate=utc_now)
899905
is_active: Mapped[bool] = mapped_column(default=True)
900906
metrics: Mapped[List["ServerMetric"]] = relationship("ServerMetric", back_populates="server", cascade="all, delete-orphan")
901907

@@ -1014,8 +1020,8 @@ class Gateway(Base):
10141020
description: Mapped[Optional[str]]
10151021
transport: Mapped[str] = mapped_column(default="SSE")
10161022
capabilities: Mapped[Dict[str, Any]] = mapped_column(JSON)
1017-
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
1018-
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
1023+
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now)
1024+
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now, onupdate=utc_now)
10191025
is_active: Mapped[bool] = mapped_column(default=True)
10201026
last_seen: Mapped[Optional[datetime]]
10211027

@@ -1086,8 +1092,8 @@ class SessionRecord(Base):
10861092
__tablename__ = "mcp_sessions"
10871093

10881094
session_id: Mapped[str] = mapped_column(primary_key=True)
1089-
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)) # pylint: disable=not-callable
1090-
last_accessed: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) # pylint: disable=not-callable
1095+
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now) # pylint: disable=not-callable
1096+
last_accessed: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now, onupdate=utc_now) # pylint: disable=not-callable
10911097
data: Mapped[str] = mapped_column(String, nullable=True)
10921098

10931099
messages: Mapped[List["SessionMessageRecord"]] = relationship("SessionMessageRecord", back_populates="session", cascade="all, delete-orphan")
@@ -1101,8 +1107,8 @@ class SessionMessageRecord(Base):
11011107
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
11021108
session_id: Mapped[str] = mapped_column(ForeignKey("mcp_sessions.session_id"))
11031109
message: Mapped[str] = mapped_column(String, nullable=True)
1104-
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)) # pylint: disable=not-callable
1105-
last_accessed: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) # pylint: disable=not-callable
1110+
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now) # pylint: disable=not-callable
1111+
last_accessed: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now, onupdate=utc_now) # pylint: disable=not-callable
11061112

11071113
session: Mapped["SessionRecord"] = relationship("SessionRecord", back_populates="messages")
11081114

mcpgateway/federation/discovery.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
# Standard
1717
import asyncio
1818
from dataclasses import dataclass
19-
from datetime import datetime, timedelta
19+
from datetime import datetime, timedelta, timezone
2020
import logging
2121
import os
2222
import socket
@@ -205,7 +205,7 @@ async def add_peer(self, url: str, source: str, name: Optional[str] = None) -> b
205205
# Skip if already known
206206
if url in self._discovered_peers:
207207
peer = self._discovered_peers[url]
208-
peer.last_seen = datetime.utcnow()
208+
peer.last_seen = datetime.now(timezone.utc)
209209
return False
210210

211211
try:
@@ -218,8 +218,8 @@ async def add_peer(self, url: str, source: str, name: Optional[str] = None) -> b
218218
name=name,
219219
protocol_version=PROTOCOL_VERSION,
220220
capabilities=capabilities,
221-
discovered_at=datetime.utcnow(),
222-
last_seen=datetime.utcnow(),
221+
discovered_at=datetime.now(timezone.utc),
222+
last_seen=datetime.now(timezone.utc),
223223
source=source,
224224
)
225225

@@ -253,7 +253,7 @@ async def refresh_peer(self, url: str) -> bool:
253253
try:
254254
capabilities = await self._get_gateway_info(url)
255255
self._discovered_peers[url].capabilities = capabilities
256-
self._discovered_peers[url].last_seen = datetime.utcnow()
256+
self._discovered_peers[url].last_seen = datetime.now(timezone.utc)
257257
return True
258258
except Exception as e:
259259
logger.warning(f"Failed to refresh peer {url}: {e}")
@@ -303,7 +303,7 @@ async def _cleanup_loop(self) -> None:
303303
"""Periodically clean up stale peers."""
304304
while True:
305305
try:
306-
now = datetime.utcnow()
306+
now = datetime.now(timezone.utc)
307307
stale_urls = [url for url, peer in self._discovered_peers.items() if now - peer.last_seen > timedelta(minutes=10)]
308308
for url in stale_urls:
309309
await self.remove_peer(url)

mcpgateway/federation/forward.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
# Standard
1717
import asyncio
18-
from datetime import datetime
18+
from datetime import datetime, timezone
1919
import logging
2020
from typing import Any, Dict, List, Optional, Set, Tuple, Union
2121

@@ -233,7 +233,7 @@ async def _forward_to_gateway(
233233
result = response.json()
234234

235235
# Update last seen
236-
gateway.last_seen = datetime.utcnow()
236+
gateway.last_seen = datetime.now(timezone.utc)
237237

238238
# Handle response
239239
if "error" in result:
@@ -316,7 +316,7 @@ def _check_rate_limit(self, gateway_url: str) -> bool:
316316
Returns:
317317
True if request allowed
318318
"""
319-
now = datetime.utcnow()
319+
now = datetime.now(timezone.utc)
320320

321321
# Clean old history
322322
self._request_history[gateway_url] = [t for t in self._request_history.get(gateway_url, []) if (now - t).total_seconds() < 60]

mcpgateway/federation/manager.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
# Standard
2020
import asyncio
21-
from datetime import datetime, timedelta
21+
from datetime import datetime, timedelta, timezone
2222
import logging
2323
import os
2424
from typing import Any, Dict, List, Optional, Set
@@ -158,7 +158,7 @@ async def register_gateway(self, db: Session, url: str, name: Optional[str] = No
158158
name=gateway_name,
159159
url=url,
160160
capabilities=capabilities.dict(),
161-
last_seen=datetime.utcnow(),
161+
last_seen=datetime.now(timezone.utc),
162162
)
163163
db.add(gateway)
164164
db.commit()
@@ -195,7 +195,7 @@ async def unregister_gateway(self, db: Session, gateway_id: str) -> None:
195195

196196
# Remove gateway
197197
gateway.is_active = False
198-
gateway.updated_at = datetime.utcnow()
198+
gateway.updated_at = datetime.now(timezone.utc)
199199

200200
# Remove associated tools
201201
db.execute(select(DbTool).where(DbTool.gateway_id == gateway_id)).delete()
@@ -315,7 +315,7 @@ async def forward_request(self, gateway: DbGateway, method: str, params: Optiona
315315
result = response.json()
316316

317317
# Update last seen
318-
gateway.last_seen = datetime.utcnow()
318+
gateway.last_seen = datetime.now(timezone.utc)
319319

320320
# Handle response
321321
if "error" in result:
@@ -351,7 +351,7 @@ async def _run_sync_loop(self, db: Session) -> None:
351351
# Update capabilities
352352
capabilities = await self._initialize_gateway(gateway.url)
353353
gateway.capabilities = capabilities.dict()
354-
gateway.last_seen = datetime.utcnow()
354+
gateway.last_seen = datetime.now(timezone.utc)
355355
gateway.is_active = True
356356

357357
except Exception as e:
@@ -383,7 +383,7 @@ async def _run_health_loop(self, db: Session) -> None:
383383
except Exception as e:
384384
logger.warning(f"Health check failed for {gateway.name}: {e}")
385385
# Mark inactive if not seen recently
386-
if datetime.utcnow() - gateway.last_seen > timedelta(minutes=5):
386+
if datetime.now(timezone.utc) - gateway.last_seen > timedelta(minutes=5):
387387
gateway.is_active = False
388388
self._active_gateways.discard(gateway.url)
389389

mcpgateway/schemas.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
# Standard
2323
import base64
24-
from datetime import datetime
24+
from datetime import datetime, timezone
2525
import json
2626
import logging
2727
from typing import Any, Dict, List, Literal, Optional, Union
@@ -542,7 +542,7 @@ class ResourceNotification(BaseModelWithConfig):
542542

543543
uri: str
544544
content: ResourceContent
545-
timestamp: datetime = Field(default_factory=datetime.utcnow)
545+
timestamp: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
546546

547547

548548
# --- Prompt Schemas ---
@@ -893,10 +893,10 @@ class GatewayRead(BaseModelWithConfig):
893893
description: Optional[str] = Field(None, description="Gateway description")
894894
transport: str = Field(default="SSE", description="Transport used by MCP server: SSE or STREAMABLEHTTP")
895895
capabilities: Dict[str, Any] = Field(default_factory=dict, description="Gateway capabilities")
896-
created_at: datetime = Field(default_factory=datetime.utcnow, description="Creation timestamp")
897-
updated_at: datetime = Field(default_factory=datetime.utcnow, description="Last update timestamp")
896+
created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc), description="Creation timestamp")
897+
updated_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc), description="Last update timestamp")
898898
is_active: bool = Field(default=True, description="Is the gateway active?")
899-
last_seen: Optional[datetime] = Field(default_factory=datetime.utcnow, description="Last seen timestamp")
899+
last_seen: Optional[datetime] = Field(default_factory=lambda: datetime.now(timezone.utc), description="Last seen timestamp")
900900

901901
# Authorizations
902902
auth_type: Optional[str] = Field(None, description="auth_type: basic, bearer, headers or None")
@@ -1030,7 +1030,7 @@ class EventMessage(BaseModelWithConfig):
10301030

10311031
type: str = Field(..., description="Event type (tool_added, resource_updated, etc)")
10321032
data: Dict[str, Any] = Field(..., description="Event payload")
1033-
timestamp: datetime = Field(default_factory=datetime.utcnow)
1033+
timestamp: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
10341034

10351035

10361036
class AdminToolCreate(BaseModelWithConfig):

mcpgateway/services/logging_service.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
# Standard
1313
import asyncio
14-
from datetime import datetime
14+
from datetime import datetime, timezone
1515
import logging
1616
from typing import Any, AsyncGenerator, Dict, List, Optional
1717

@@ -106,7 +106,7 @@ async def notify(self, data: Any, level: LogLevel, logger_name: Optional[str] =
106106
"data": {
107107
"level": level,
108108
"data": data,
109-
"timestamp": datetime.utcnow().isoformat(),
109+
"timestamp": datetime.now(timezone.utc).isoformat(),
110110
},
111111
}
112112
if logger_name:

0 commit comments

Comments
 (0)