mcp-dbutils 0.15.2__py3-none-any.whl → 0.15.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
mcp_dbutils/base.py CHANGED
@@ -1,24 +1,11 @@
1
1
  """Connection server base class"""
2
2
 
3
- class ConnectionHandlerError(Exception):
4
- """Base exception for connection errors"""
5
- pass
6
-
7
- class ConfigurationError(ConnectionHandlerError):
8
- """Configuration related errors"""
9
- pass
10
-
11
- class ConnectionError(ConnectionHandlerError):
12
- """Connection related errors"""
13
- pass
14
-
15
3
  import json
16
4
  from abc import ABC, abstractmethod
17
5
  from contextlib import asynccontextmanager
18
6
  from datetime import datetime
19
7
  from importlib.metadata import metadata
20
- from typing import AsyncContextManager
21
- from unittest.mock import MagicMock
8
+ from typing import Any, AsyncContextManager, Dict
22
9
 
23
10
  import mcp.server.stdio
24
11
  import mcp.types as types
@@ -28,6 +15,19 @@ from mcp.server import Server
28
15
  from .log import create_logger
29
16
  from .stats import ResourceStats
30
17
 
18
+
19
+ class ConnectionHandlerError(Exception):
20
+ """Base exception for connection errors"""
21
+ pass
22
+
23
+ class ConfigurationError(ConnectionHandlerError):
24
+ """Configuration related errors"""
25
+ pass
26
+
27
+ class ConnectionError(ConnectionHandlerError):
28
+ """Connection related errors"""
29
+ pass
30
+
31
31
  # 常量定义
32
32
  DATABASE_CONNECTION_NAME = "Database connection name"
33
33
  EMPTY_QUERY_ERROR = "SQL query cannot be empty"
@@ -347,14 +347,16 @@ class ConnectionServer:
347
347
 
348
348
  handler.stats.record_connection_start()
349
349
  self.send_log(LOG_LEVEL_DEBUG, f"Handler created successfully for {connection}")
350
- # 处理MagicMock对象,避免JSON序列化错误
350
+ # 使用通用的方式处理统计信息序列化
351
351
  try:
352
- stats_dict = handler.stats.to_dict()
353
- stats_json = json.dumps(stats_dict)
354
- self.send_log(LOG_LEVEL_INFO, f"Resource stats: {stats_json}")
352
+ if hasattr(handler.stats, 'to_dict') and callable(handler.stats.to_dict):
353
+ stats_dict = handler.stats.to_dict()
354
+ stats_json = json.dumps(stats_dict)
355
+ self.send_log(LOG_LEVEL_INFO, f"Resource stats: {stats_json}")
356
+ else:
357
+ self.send_log(LOG_LEVEL_INFO, "Resource stats not available")
355
358
  except TypeError:
356
- # 在测试环境中,stats可能是MagicMock对象
357
- self.send_log(LOG_LEVEL_INFO, "Resource stats: [Mock object in test environment]")
359
+ self.send_log(LOG_LEVEL_INFO, "Resource stats: [Could not serialize stats object]")
358
360
  yield handler
359
361
  except yaml.YAMLError as e:
360
362
  raise ConfigurationError(f"Invalid YAML configuration: {str(e)}")
@@ -364,16 +366,19 @@ class ConnectionServer:
364
366
  if handler:
365
367
  self.send_log(LOG_LEVEL_DEBUG, f"Cleaning up handler for {connection}")
366
368
  handler.stats.record_connection_end()
367
- # 处理MagicMock对象,避免JSON序列化错误
369
+ # 使用通用的方式处理统计信息序列化
368
370
  try:
369
- stats_dict = handler.stats.to_dict()
370
- stats_json = json.dumps(stats_dict)
371
- self.send_log(LOG_LEVEL_INFO, f"Final resource stats: {stats_json}")
371
+ if hasattr(handler.stats, 'to_dict') and callable(handler.stats.to_dict):
372
+ stats_dict = handler.stats.to_dict()
373
+ stats_json = json.dumps(stats_dict)
374
+ self.send_log(LOG_LEVEL_INFO, f"Final resource stats: {stats_json}")
375
+ else:
376
+ self.send_log(LOG_LEVEL_INFO, "Final resource stats not available")
372
377
  except TypeError:
373
- # 在测试环境中,stats可能是MagicMock对象
374
- self.send_log(LOG_LEVEL_INFO, "Final resource stats: [Mock object in test environment]")
375
- # 在测试环境中,handler可能是MagicMock对象,但cleanup可能是AsyncMock
376
- await handler.cleanup()
378
+ self.send_log(LOG_LEVEL_INFO, "Final resource stats: [Could not serialize stats object]")
379
+ # 清理资源
380
+ if hasattr(handler, 'cleanup') and callable(handler.cleanup):
381
+ await handler.cleanup()
377
382
 
378
383
  def _setup_handlers(self):
379
384
  """Setup MCP handlers"""
@@ -163,7 +163,7 @@ class SQLiteServer(ConnectionServer):
163
163
  columns = [desc[0] for desc in cursor.description]
164
164
  formatted_results = [dict(zip(columns, row)) for row in results]
165
165
 
166
- # 在测试环境中,connection可能是MagicMock对象,不能序列化为JSON
166
+ # 使用更通用的方法确定配置名称
167
167
  config_name = connection if isinstance(connection, str) else 'default'
168
168
  result_text = json.dumps({
169
169
  'type': 'sqlite',
@@ -179,7 +179,7 @@ class SQLiteServer(ConnectionServer):
179
179
  return [types.TextContent(type="text", text=result_text)]
180
180
 
181
181
  except sqlite3.Error as e:
182
- # 在测试环境中,connection可能是MagicMock对象,不能序列化为JSON
182
+ # 使用更通用的方法确定配置名称
183
183
  config_name = connection if isinstance(connection, str) else 'default'
184
184
  error_msg = json.dumps({
185
185
  'type': 'sqlite',
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-dbutils
3
- Version: 0.15.2
3
+ Version: 0.15.4
4
4
  Summary: MCP Database Utilities Service
5
5
  Author: Dong Hao
6
6
  License-Expression: MIT
@@ -1,5 +1,5 @@
1
1
  mcp_dbutils/__init__.py,sha256=6LLccQv7je2L4IpY_I3OzSJZcK32VUDJv2IY31y6eYg,1900
2
- mcp_dbutils/base.py,sha256=aTmKLuuLFZEbTH-RdioSBwKhGVrqvQSVlUoDQ-vx6CI,28831
2
+ mcp_dbutils/base.py,sha256=d4kt29NQeE7xZ0DlGpJcpBXS1pY1VnY98gX-xJ-Ehpg,29126
3
3
  mcp_dbutils/config.py,sha256=bmXpOd1fyYfoyUS75I035ChT6t3wP5AyEnJ06e2ZS2o,1848
4
4
  mcp_dbutils/log.py,sha256=mqxi6I_IL-MF1F_pxBtnYZQKOHbGBJ74gsvZHVelr1w,823
5
5
  mcp_dbutils/stats.py,sha256=wMqWPfGnEOg9v5YBtTsARV-1YsFUMM_pKdzitzSU9x4,7137
@@ -14,9 +14,9 @@ mcp_dbutils/postgres/server.py,sha256=_CiJC9PitpI1NB99Q1Bcs5TYADNgDpYMwv88fRHQun
14
14
  mcp_dbutils/sqlite/__init__.py,sha256=fK_3-WylCBYpBAzwuopi8hlwoIGJm2TPAlwcPWG46I0,134
15
15
  mcp_dbutils/sqlite/config.py,sha256=j67TJ8mQJ2D886MthSa-zYMtvUUYyyxYLMlNxkYoqZE,4509
16
16
  mcp_dbutils/sqlite/handler.py,sha256=T5atpRn71IwlTyPKhdpQsGIJb16716SKLBplsl9Wv50,17750
17
- mcp_dbutils/sqlite/server.py,sha256=qhY6OOx_Dzx17wbE1DlVQgnifTqgJJ1BJp9pHmROVkA,7275
18
- mcp_dbutils-0.15.2.dist-info/METADATA,sha256=r9AXHFQU3rrmSHTE3wdUtUXyCK9OydxPSirRBVVZUXs,16714
19
- mcp_dbutils-0.15.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
20
- mcp_dbutils-0.15.2.dist-info/entry_points.txt,sha256=XTjt0QmYRgKOJQT6skR9bp1EMUfIrgpHeZJPZ3CJffs,49
21
- mcp_dbutils-0.15.2.dist-info/licenses/LICENSE,sha256=1A_CwpWVlbjrKdVEYO77vYfnXlW7oxcilZ8FpA_BzCI,1065
22
- mcp_dbutils-0.15.2.dist-info/RECORD,,
17
+ mcp_dbutils/sqlite/server.py,sha256=3W0kB1mrVzcfMjVG3dkmt1R4Mh4lbiXkQsXon7e4i1U,7199
18
+ mcp_dbutils-0.15.4.dist-info/METADATA,sha256=Zuqz-dphdUevGpuzXasySN28wmdg9GExh0jp7V4RCF4,16714
19
+ mcp_dbutils-0.15.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
20
+ mcp_dbutils-0.15.4.dist-info/entry_points.txt,sha256=XTjt0QmYRgKOJQT6skR9bp1EMUfIrgpHeZJPZ3CJffs,49
21
+ mcp_dbutils-0.15.4.dist-info/licenses/LICENSE,sha256=1A_CwpWVlbjrKdVEYO77vYfnXlW7oxcilZ8FpA_BzCI,1065
22
+ mcp_dbutils-0.15.4.dist-info/RECORD,,