magic-base 0.1.0__tar.gz → 0.1.2__tar.gz

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.
Files changed (67) hide show
  1. {magic_base-0.1.0/src/magic_base.egg-info → magic_base-0.1.2}/PKG-INFO +1 -1
  2. {magic_base-0.1.0 → magic_base-0.1.2}/pyproject.toml +10 -1
  3. magic_base-0.1.2/src/magic_base/__init__.py +19 -0
  4. {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base/config/base_config.py +2 -2
  5. magic_base-0.1.2/src/magic_base/constants/tables.py +10 -0
  6. magic_base-0.1.2/src/magic_base/context/application_context.py +160 -0
  7. magic_base-0.1.2/src/magic_base/data_access/config/base_database_config.py +353 -0
  8. magic_base-0.1.2/src/magic_base/data_access/manager/base_database_manager.py +298 -0
  9. magic_base-0.1.2/src/magic_base/data_access/model/base_entity.py +241 -0
  10. magic_base-0.1.2/src/magic_base/data_access/repository/base_repository.py +249 -0
  11. magic_base-0.1.2/src/magic_base/data_access/repository/base_repository_core_mixin.py +234 -0
  12. magic_base-0.1.2/src/magic_base/data_access/repository/base_repository_cud_mixin.py +373 -0
  13. magic_base-0.1.2/src/magic_base/data_access/repository/base_repository_query_mixin.py +462 -0
  14. magic_base-0.1.2/src/magic_base/data_access/repository/base_sqlalchemy_repository.py +308 -0
  15. magic_base-0.1.2/src/magic_base/data_access/service/base_service.py +141 -0
  16. magic_base-0.1.2/src/magic_base/data_access/service/base_service_core_mixin.py +108 -0
  17. magic_base-0.1.2/src/magic_base/data_access/service/base_service_cud_mixin.py +295 -0
  18. magic_base-0.1.2/src/magic_base/data_access/service/base_service_query_mixin.py +264 -0
  19. magic_base-0.1.2/src/magic_base/data_access/util/__init__.py +10 -0
  20. magic_base-0.1.2/src/magic_base/data_access/util/base_data_command.py +233 -0
  21. magic_base-0.1.2/src/magic_base/data_access/util/base_db_command.py +136 -0
  22. magic_base-0.1.2/src/magic_base/data_access/util/base_db_table_util.py +350 -0
  23. magic_base-0.1.2/src/magic_base/data_access/util/base_db_util.py +311 -0
  24. magic_base-0.1.2/src/magic_base/data_access/util/base_type_converter.py +117 -0
  25. magic_base-0.1.2/src/magic_base/i18n/__init__.py +16 -0
  26. magic_base-0.1.2/src/magic_base/i18n/factory.py +30 -0
  27. magic_base-0.1.2/src/magic_base/i18n/language.py +40 -0
  28. magic_base-0.1.2/src/magic_base/i18n/languages/__init__.py +5 -0
  29. magic_base-0.1.2/src/magic_base/i18n/languages/en_US.py +16 -0
  30. magic_base-0.1.2/src/magic_base/i18n/languages/zh_CN.py +16 -0
  31. magic_base-0.1.2/src/magic_base/i18n/provider.py +19 -0
  32. magic_base-0.1.2/src/magic_base/utils/__init__.py +4 -0
  33. magic_base-0.1.2/src/magic_base/utils/base_csv_validator.py +127 -0
  34. {magic_base-0.1.0 → magic_base-0.1.2/src/magic_base.egg-info}/PKG-INFO +1 -1
  35. {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base.egg-info/SOURCES.txt +26 -2
  36. magic_base-0.1.0/src/magic_base/data_access/config/base_database_config.py +0 -85
  37. magic_base-0.1.0/src/magic_base/data_access/manager/base_database_manager.py +0 -0
  38. magic_base-0.1.0/src/magic_base/data_access/model/base_model.py +0 -10
  39. magic_base-0.1.0/src/magic_base/data_access/repository/base_repository.py +0 -84
  40. magic_base-0.1.0/src/magic_base/data_access/service/base_service.py +0 -0
  41. magic_base-0.1.0/src/magic_base/types/__init__.py +0 -0
  42. {magic_base-0.1.0 → magic_base-0.1.2}/LICENSE +0 -0
  43. {magic_base-0.1.0 → magic_base-0.1.2}/README.md +0 -0
  44. {magic_base-0.1.0 → magic_base-0.1.2}/setup.cfg +0 -0
  45. {magic_base-0.1.0/src/magic_base → magic_base-0.1.2/src/magic_base/config}/__init__.py +0 -0
  46. {magic_base-0.1.0/src/magic_base/config → magic_base-0.1.2/src/magic_base/crypto}/__init__.py +0 -0
  47. {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base/crypto/base_cert.py +0 -0
  48. {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base/crypto/base_crypto.py +0 -0
  49. {magic_base-0.1.0/src/magic_base/crypto → magic_base-0.1.2/src/magic_base/data_access}/__init__.py +0 -0
  50. {magic_base-0.1.0/src/magic_base/data_access → magic_base-0.1.2/src/magic_base/data_access/config}/__init__.py +0 -0
  51. {magic_base-0.1.0/src/magic_base/data_access/config → magic_base-0.1.2/src/magic_base/data_access/manager}/__init__.py +0 -0
  52. {magic_base-0.1.0/src/magic_base/data_access/manager → magic_base-0.1.2/src/magic_base/data_access/model}/__init__.py +0 -0
  53. {magic_base-0.1.0/src/magic_base/data_access/model → magic_base-0.1.2/src/magic_base/data_access/repository}/__init__.py +0 -0
  54. {magic_base-0.1.0/src/magic_base/data_access/repository → magic_base-0.1.2/src/magic_base/data_access/service}/__init__.py +0 -0
  55. {magic_base-0.1.0/src/magic_base/data_access/service → magic_base-0.1.2/src/magic_base/detector}/__init__.py +0 -0
  56. {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base/detector/base_detector.py +0 -0
  57. {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base/detector/base_hardware_define.py +0 -0
  58. {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base/detector/base_hardware_result.py +0 -0
  59. {magic_base-0.1.0/src/magic_base/detector → magic_base-0.1.2/src/magic_base/exceptions}/__init__.py +0 -0
  60. {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base/exceptions/base_exceptions.py +0 -0
  61. {magic_base-0.1.0/src/magic_base/exceptions → magic_base-0.1.2/src/magic_base/platform}/__init__.py +0 -0
  62. {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base/platform/base_platform_adapter.py +0 -0
  63. {magic_base-0.1.0/src/magic_base/platform → magic_base-0.1.2/src/magic_base/types}/__init__.py +0 -0
  64. {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base/types/base_types.py +0 -0
  65. {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base.egg-info/dependency_links.txt +0 -0
  66. {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base.egg-info/requires.txt +0 -0
  67. {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: magic-base
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: Magic 平台公共基类库 - 提供统一的抽象基类和核心接口
5
5
  Author: wxd123
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "magic-base"
7
- version = "0.1.0"
7
+ version = "0.1.2"
8
8
  description = "Magic 平台公共基类库 - 提供统一的抽象基类和核心接口"
9
9
  readme = "README.md"
10
10
  authors = [{name = "wxd123"}]
@@ -43,5 +43,14 @@ Repository = "https://github.com/wxd123/magic-base.git"
43
43
  [dependency-groups]
44
44
  dev = [
45
45
  "build>=1.4.4",
46
+ "magic-base",
46
47
  "twine>=6.2.0",
47
48
  ]
49
+
50
+ [tool.uv.workspace]
51
+ members = [
52
+ ".",
53
+ ]
54
+
55
+ [tool.uv.sources]
56
+ magic-base = { workspace = true, editable = true }
@@ -0,0 +1,19 @@
1
+ # magic_base/__init__.py
2
+
3
+ from magic_base.config.base_config import BaseConfig
4
+ from magic_base.data_access.config.base_database_config import BaseDatabaseConfig, MagicDatabaseConfig
5
+ from magic_base.data_access.manager.base_database_manager import BaseDatabaseManager, MagicDatabaseManager
6
+ from magic_base.data_access.model.base_entity import Base, BaseEntity, MagicBaseEntity
7
+ from magic_base.data_access.repository.base_repository import BaseRepository, MagicBaseRepository
8
+ from magic_base.data_access.service.base_service import BaseService, MagicBaseService
9
+ from magic_base.context.application_context import ApplicationContext
10
+ from magic_base.utils.base_csv_validator import CSVValidator
11
+ __all__ = [
12
+ 'ApplicationContext',
13
+ 'BaseConfig', 'BaseDatabaseConfig', 'MagicDatabaseConfig',
14
+ 'BaseDatabaseManager', 'MagicDatabaseManager',
15
+ 'Base', 'BaseEntity', 'MagicBaseEntity',
16
+ 'BaseRepository', 'MagicBaseRepository',
17
+ 'BaseService', 'MagicBaseService',
18
+ 'CSVValidator'
19
+ ]
@@ -1,4 +1,4 @@
1
- # magic_base/config/base.py
1
+ # magic_base/config/base_config.py
2
2
  """
3
3
  配置管理基类
4
4
  """
@@ -7,7 +7,7 @@ from abc import ABC, abstractmethod
7
7
  from typing import Any, Dict, Optional
8
8
 
9
9
 
10
- class ConfigBase(ABC):
10
+ class BaseConfig(ABC):
11
11
  """配置管理基类"""
12
12
 
13
13
  @abstractmethod
@@ -0,0 +1,10 @@
1
+ # magic_base/constants/tables.py
2
+ """数据库表名常量"""
3
+
4
+
5
+
6
+
7
+ # 辅助表
8
+ SCHEMA_VERSION_TABLE = 'magic_schema_version'
9
+
10
+
@@ -0,0 +1,160 @@
1
+ # magic_base/core/context.py
2
+
3
+ import threading
4
+ from typing import Optional, Generic, TypeVar, Dict
5
+
6
+ from magic_base.data_access.config.base_database_config import BaseDatabaseConfig
7
+ from magic_base.data_access.manager.base_database_manager import BaseDatabaseManager
8
+
9
+
10
+ # 定义泛型变量
11
+ ContextType = TypeVar('ContextType')
12
+
13
+ class ApplicationContext(Generic[ContextType]):
14
+ """全局应用上下文 - 泛型基类
15
+
16
+ 提供全局单例级别的上下文管理,支持数据库配置、数据库管理器以及项目特定的上下文信息。
17
+ 使用线程锁保证多线程环境下的线程安全。
18
+
19
+ 每个项目可以继承此类并指定自己的上下文类型,从而获得类型安全的上下文访问。
20
+
21
+ 泛型参数:
22
+ ContextType: 项目特定上下文的类型,可以是任何自定义类或数据结构
23
+
24
+ 类属性:
25
+ _lock: 线程锁,用于保证初始化与重置操作的原子性
26
+ db_config: 数据库配置对象,用于存储数据库连接参数
27
+ db_manager: 数据库管理器对象,用于执行数据库操作
28
+ _contexts: 项目特定的上下文对象,类型由泛型参数ContextType决定
29
+
30
+ 使用示例:
31
+ # 定义项目特定上下文类
32
+ class MyContext:
33
+ user_id: str
34
+ tenant_id: str
35
+
36
+ # 初始化全局上下文
37
+ ApplicationContext[MyContext].initialize(
38
+ db_config=my_db_config,
39
+ db_manager=my_db_manager,
40
+ context=MyContext(user_id="123", tenant_id="tenant1")
41
+ )
42
+
43
+ # 获取上下文
44
+ ctx = ApplicationContext[MyContext].get_context()
45
+ db_mgr = ApplicationContext[MyContext].get_db_manager()
46
+ """
47
+
48
+ _lock = threading.Lock()
49
+
50
+ # 共享属性(所有项目都需要)
51
+ db_config: Optional[BaseDatabaseConfig] = None
52
+ """数据库配置对象,可选,未设置时为None"""
53
+
54
+ db_manager: Optional[BaseDatabaseManager] = None
55
+ """数据库管理器对象,可选,未设置时为None"""
56
+
57
+
58
+ # 业务上下文字典(按 key 存储)
59
+ _contexts: Dict[str, ContextType] = {}
60
+ """项目特定上下文对象,类型由泛型参数ContextType决定,未设置时为None"""
61
+
62
+ @classmethod
63
+ def initialize(cls,
64
+ project_name: str,
65
+ db_config: Optional[BaseDatabaseConfig] = None,
66
+ db_manager: Optional[BaseDatabaseManager] = None,
67
+ context: Optional[ContextType] = None):
68
+ """初始化全局上下文
69
+
70
+ 使用线程锁保证初始化操作的线程安全性。允许部分初始化,即可以只设置部分属性,
71
+ 未传入的参数对应的属性将保持原值不变(如果之前已设置)或保持为None。
72
+
73
+ 参数:
74
+ project_name: 项目名称,用于区分各个模块的自定义上下文
75
+ db_config: 数据库配置对象,可选,如果提供则替换现有的db_config
76
+ db_manager: 数据库管理器对象,可选,如果提供则替换现有的db_manager
77
+ context: 项目特定的上下文对象,可选,如果提供则替换现有的context
78
+
79
+ 注意:
80
+ 此方法不是全量替换,而是增量更新。若希望完全重置所有属性,请先调用reset()方法。
81
+
82
+ 示例:
83
+ # 仅初始化数据库管理器
84
+ ApplicationContext.initialize(db_manager=my_manager)
85
+
86
+ # 初始化所有属性
87
+ ApplicationContext.initialize(
88
+ db_config=config,
89
+ db_manager=manager,
90
+ context=my_context
91
+ )
92
+ """
93
+ with cls._lock:
94
+ if db_config is not None and cls.db_config is None:
95
+ cls.db_config = db_config
96
+ if db_manager is not None and cls.db_manager is None:
97
+ cls.db_manager = db_manager
98
+ if project_name is not None and context is not None:
99
+ cls._contexts[project_name] = context
100
+
101
+ @classmethod
102
+ def get_db_manager(cls) -> BaseDatabaseManager:
103
+ """获取数据库管理器实例
104
+
105
+ 返回:
106
+ BaseDatabaseManager: 已初始化的数据库管理器对象
107
+
108
+ 异常:
109
+ RuntimeError: 当db_manager尚未初始化(为None)时抛出
110
+
111
+ 示例:
112
+ db_manager = ApplicationContext.get_db_manager()
113
+ result = db_manager.query("SELECT * FROM users")
114
+ """
115
+ if cls.db_manager is None:
116
+ raise RuntimeError("Database manager not initialized")
117
+ return cls.db_manager
118
+
119
+ @classmethod
120
+ def get_context(cls,project_name: str) -> ContextType:
121
+ """获取项目特定的上下文
122
+
123
+ 返回:
124
+ ContextType: 项目特定的上下文对象,类型由泛型参数决定
125
+
126
+ 异常:
127
+ RuntimeError: 当context尚未初始化(为None)时抛出
128
+
129
+ 示例:
130
+ ctx = ApplicationContext[MyContext].get_context()
131
+ print(ctx.user_id) # 类型安全,IDE可提供代码补全
132
+ """
133
+ if cls._contexts is None:
134
+ raise RuntimeError("Context not initialized")
135
+ return cls._contexts[project_name]
136
+
137
+ @classmethod
138
+ def reset(cls):
139
+ """重置全局上下文
140
+
141
+ 将所有的类属性(db_config, db_manager, context)重置为None。
142
+ 使用线程锁保证重置操作的线程安全性。
143
+
144
+ 通常在以下场景使用:
145
+ - 单元测试的清理阶段,避免测试用例之间的状态污染
146
+ - 应用重新初始化前,需要清空旧的状态
147
+ - 切换不同的运行时环境
148
+
149
+ 示例:
150
+ # 测试用例清理
151
+ def tearDown(self):
152
+ ApplicationContext.reset()
153
+ """
154
+ with cls._lock:
155
+ cls.db_config = None
156
+ cls.db_manager = None
157
+ cls._contexts = None
158
+
159
+
160
+ __all__ = ['ApplicationContext']
@@ -0,0 +1,353 @@
1
+ """
2
+ 数据库配置基类
3
+ """
4
+ from abc import ABC, abstractmethod
5
+ from typing import Dict, Any, Optional
6
+ from pathlib import Path
7
+ from enum import Enum
8
+
9
+
10
+ class DatabaseType(Enum):
11
+ """数据库类型枚举
12
+
13
+ 定义了支持的数据库类型,用于统一配置不同数据库的连接参数。
14
+
15
+ 成员:
16
+ SQLITE: SQLite 轻量级文件数据库
17
+ POSTGRESQL: PostgreSQL 关系型数据库
18
+ MYSQL: MySQL 关系型数据库
19
+ """
20
+ SQLITE = "sqlite"
21
+ POSTGRESQL = "postgresql"
22
+ MYSQL = "mysql"
23
+
24
+
25
+ class BaseDatabaseConfig(ABC):
26
+ """数据库配置抽象基类
27
+
28
+ 定义了数据库配置的标准接口,所有具体数据库配置类都应继承此类。
29
+ 提供获取连接字符串和引擎选项的核心方法。
30
+ """
31
+
32
+ @abstractmethod
33
+ def get_connection_string(self) -> str:
34
+ """获取数据库连接字符串
35
+
36
+ 根据配置的数据库类型和参数,生成符合 SQLAlchemy 格式的连接字符串。
37
+
38
+ 返回:
39
+ str: 数据库连接字符串,格式如 "sqlite:///path/to/db.db" 或
40
+ "postgresql://user:pass@localhost:5432/dbname"
41
+ """
42
+ pass
43
+
44
+ @abstractmethod
45
+ def get_engine_options(self) -> Dict[str, Any]:
46
+ """获取引擎选项
47
+
48
+ 返回 SQLAlchemy 引擎初始化时所需的参数字典,包括连接池配置、日志设置等。
49
+
50
+ 返回:
51
+ Dict[str, Any]: 引擎选项字典,可直接传递给 SQLAlchemy create_engine 函数
52
+ """
53
+ pass
54
+
55
+ @abstractmethod
56
+ def get_db_path(self) -> str:
57
+ """获取数据库文件路径(仅限于sqlite)
58
+
59
+ 返回 sqlite数据库文件路径。
60
+
61
+ """
62
+ pass
63
+
64
+
65
+ class MagicDatabaseConfig(BaseDatabaseConfig):
66
+ """
67
+ Magic 系列统一数据库配置
68
+
69
+ 为 Magic 系列项目提供统一的数据库配置管理,支持 SQLite、PostgreSQL 和 MySQL。
70
+ 自动处理数据库文件的目录创建、路径解析等细节。
71
+
72
+ 设计原则:
73
+ 只做一件事:提供统一的数据库配置,不涉及业务逻辑。
74
+
75
+ 类属性:
76
+ MAGIC_DATA_DIR: Magic 默认数据存储目录,位于用户家目录下的 magic/data
77
+ """
78
+
79
+ MAGIC_DATA_DIR = Path.home() / "magic" / "data"
80
+ """Magic 默认数据目录,路径为 ~/magic/data"""
81
+
82
+ # 数据库路径
83
+ db_path = None
84
+ def __init__(
85
+ self,
86
+ db_type: DatabaseType = DatabaseType.SQLITE,
87
+ **kwargs
88
+ ):
89
+ """
90
+ 初始化数据库配置
91
+
92
+ 参数:
93
+ db_type: 数据库类型,默认为 SQLite。可选值见 DatabaseType 枚举
94
+ **kwargs: 连接参数,根据数据库类型不同而不同
95
+
96
+ 不同数据库类型支持的 kwargs 参数:
97
+ SQLite:
98
+ - path: 数据库文件路径(可选),默认为 "magic.db"
99
+ 可以是相对路径或绝对路径
100
+ - echo: 是否打印 SQL 日志(可选),默认为 False
101
+ - pool_size: 连接池大小(可选),默认为 10
102
+ - max_overflow: 连接池溢出限制(可选),默认为 20
103
+ - pool_pre_ping: 连接前检查(可选),默认为 True
104
+ - pool_recycle: 连接回收时间(秒,可选),默认为 3600
105
+
106
+ PostgreSQL:
107
+ - host: 数据库主机地址(可选),默认为 "localhost"
108
+ - port: 数据库端口(可选),默认为 5432
109
+ - user: 数据库用户名(可选),默认为空字符串
110
+ - password: 数据库密码(可选),默认为空字符串
111
+ - database: 数据库名称(可选),默认为 "magic"
112
+ - echo: 是否打印 SQL 日志(可选),默认为 False
113
+ - pool_size: 连接池大小(可选),默认为 10
114
+ - max_overflow: 连接池溢出限制(可选),默认为 20
115
+ - pool_pre_ping: 连接前检查(可选),默认为 True
116
+ - pool_recycle: 连接回收时间(秒,可选),默认为 3600
117
+
118
+ MySQL:
119
+ - host: 数据库主机地址(可选),默认为 "localhost"
120
+ - port: 数据库端口(可选),默认为 3306
121
+ - user: 数据库用户名(可选),默认为空字符串
122
+ - password: 数据库密码(可选),默认为空字符串
123
+ - database: 数据库名称(可选),默认为 "magic"
124
+ - echo: 是否打印 SQL 日志(可选),默认为 False
125
+ - pool_size: 连接池大小(可选),默认为 10
126
+ - max_overflow: 连接池溢出限制(可选),默认为 20
127
+ - pool_pre_ping: 连接前检查(可选),默认为 True
128
+ - pool_recycle: 连接回收时间(秒,可选),默认为 3600
129
+
130
+ 示例:
131
+ # 默认 SQLite 配置
132
+ config = MagicDatabaseConfig()
133
+
134
+ # 自定义 SQLite 路径
135
+ config = MagicDatabaseConfig(
136
+ DatabaseType.SQLITE,
137
+ path="./myapp/custom.db",
138
+ echo=True
139
+ )
140
+
141
+ # PostgreSQL 配置
142
+ config = MagicDatabaseConfig(
143
+ DatabaseType.POSTGRESQL,
144
+ host="localhost",
145
+ port=5432,
146
+ user="magic_user",
147
+ password="secure_pass",
148
+ database="magic_db"
149
+ )
150
+ """
151
+ self.db_type = db_type
152
+ """数据库类型"""
153
+
154
+ self.kwargs = kwargs
155
+ """连接参数字典"""
156
+
157
+ self._engine_options_cache = None
158
+ """引擎选项缓存,避免重复计算"""
159
+
160
+ if db_type == DatabaseType.SQLITE:
161
+ # 本地数据库路径,服务于 sqlite
162
+ self.db_path = self._get_sqlite_path()
163
+ """SQLite 数据库文件路径(仅 SQLite 类型有效)"""
164
+ else:
165
+ self.db_path = None
166
+
167
+ def get_connection_string(self) -> str:
168
+ """统一构建连接字符串
169
+
170
+ 根据数据库类型调用对应的构建方法,返回符合 SQLAlchemy 格式的连接字符串。
171
+
172
+ 返回:
173
+ str: 数据库连接字符串
174
+
175
+ 异常:
176
+ ValueError: 当数据库类型不支持时抛出
177
+ """
178
+ if self.db_type == DatabaseType.SQLITE:
179
+ return self._build_sqlite()
180
+ elif self.db_type == DatabaseType.POSTGRESQL:
181
+ return self._build_postgresql()
182
+ elif self.db_type == DatabaseType.MYSQL:
183
+ return self._build_mysql()
184
+ else:
185
+ raise ValueError(f"Unsupported database type: {self.db_type}")
186
+
187
+ def _get_sqlite_path(self) -> str:
188
+ """获取 SQLite 数据库路径
189
+
190
+ 处理 SQLite 数据库文件路径的逻辑:
191
+ 1. 如果用户未指定 path 参数,使用默认文件名并放在 MAGIC_DATA_DIR 下
192
+ 2. 如果用户指定了 path 参数:
193
+ - 绝对路径:直接使用
194
+ - 相对路径:相对于当前工作目录
195
+ 3. 自动创建目标目录(如果不存在)
196
+
197
+ 返回:
198
+ str: SQLite 数据库文件的完整路径字符串
199
+ """
200
+ path = self.kwargs.get("path", "magic.db")
201
+
202
+ # 判断是否使用默认目录
203
+ if "path" not in self.kwargs:
204
+ # 用户没有指定 path,使用默认目录
205
+ path = self.MAGIC_DATA_DIR / path
206
+ self.MAGIC_DATA_DIR.mkdir(parents=True, exist_ok=True)
207
+ else:
208
+ # 用户指定了 path,处理相对路径
209
+ path_obj = Path(path)
210
+ if not path_obj.is_absolute():
211
+ # 相对路径:相对于当前工作目录
212
+ path = Path.cwd() / path_obj
213
+ else:
214
+ path = path_obj
215
+
216
+ # 确保目录存在
217
+ path.parent.mkdir(parents=True, exist_ok=True)
218
+
219
+ return str(path)
220
+
221
+ def _build_sqlite(self) -> str:
222
+ """构建 SQLite 连接字符串
223
+
224
+ 返回:
225
+ str: SQLite 连接字符串,格式如 "sqlite:///path/to/database.db"
226
+ """
227
+ return f"sqlite:///{self.db_path}"
228
+
229
+ def _build_postgresql(self) -> str:
230
+ """构建 PostgreSQL 连接字符串
231
+
232
+ 返回:
233
+ str: PostgreSQL 连接字符串,格式如 "postgresql://user:pass@host:port/database"
234
+ """
235
+ host = self.kwargs.get("host", "localhost")
236
+ port = self.kwargs.get("port", 5432)
237
+ user = self.kwargs.get("user", "")
238
+ password = self.kwargs.get("password", "")
239
+ database = self.kwargs.get("database", "magic")
240
+
241
+ auth = f"{user}:{password}@" if user and password else f"{user}@" if user else ""
242
+ return f"postgresql://{auth}{host}:{port}/{database}"
243
+
244
+ def _build_mysql(self) -> str:
245
+ """构建 MySQL 连接字符串
246
+
247
+ 使用 PyMySQL 驱动,返回格式为 "mysql+pymysql://..."
248
+
249
+ 返回:
250
+ str: MySQL 连接字符串,格式如 "mysql+pymysql://user:pass@host:port/database"
251
+ """
252
+ host = self.kwargs.get("host", "localhost")
253
+ port = self.kwargs.get("port", 3306)
254
+ user = self.kwargs.get("user", "")
255
+ password = self.kwargs.get("password", "")
256
+ database = self.kwargs.get("database", "magic")
257
+
258
+ auth = f"{user}:{password}@" if user and password else f"{user}@" if user else ""
259
+ return f"mysql+pymysql://{auth}{host}:{port}/{database}"
260
+
261
+ def get_engine_options(self) -> Dict[str, Any]:
262
+ """获取引擎选项
263
+
264
+ 返回 SQLAlchemy 引擎初始化参数,包括连接池配置和日志设置。
265
+ 结果会被缓存以提高性能。
266
+
267
+ SQLite 特殊处理:
268
+ 自动添加 connect_args = {"check_same_thread": False} 以支持多线程访问
269
+
270
+ 返回:
271
+ Dict[str, Any]: 引擎选项字典,包含以下配置:
272
+ - echo: 是否打印 SQL 日志
273
+ - pool_size: 连接池大小
274
+ - max_overflow: 连接池溢出限制
275
+ - pool_pre_ping: 连接前是否检查可用性
276
+ - pool_recycle: 连接回收时间(秒)
277
+ - connect_args: 连接参数(仅 SQLite)
278
+ """
279
+ if self._engine_options_cache:
280
+ return self._engine_options_cache
281
+
282
+ # 默认选项
283
+ default_options = {
284
+ "echo": self.kwargs.get("echo", False),
285
+ "pool_size": self.kwargs.get("pool_size", 10),
286
+ "max_overflow": self.kwargs.get("max_overflow", 20),
287
+ "pool_pre_ping": self.kwargs.get("pool_pre_ping", True),
288
+ "pool_recycle": self.kwargs.get("pool_recycle", 3600),
289
+ }
290
+
291
+ # SQLite 特殊配置
292
+ if self.db_type == DatabaseType.SQLITE:
293
+ default_options["connect_args"] = {"check_same_thread": False}
294
+
295
+ self._engine_options_cache = default_options
296
+ return self._engine_options_cache
297
+
298
+ def get_data_dir(self) -> Path:
299
+ """获取数据目录
300
+
301
+ 仅 SQLite 数据库支持此方法,返回默认数据存储目录。
302
+
303
+ 返回:
304
+ Path: Magic 默认数据目录路径对象
305
+
306
+ 异常:
307
+ RuntimeError: 当数据库类型不是 SQLite 时抛出
308
+ """
309
+ if self.db_type != DatabaseType.SQLITE:
310
+ raise RuntimeError("Data directory only available for SQLite")
311
+ return self.MAGIC_DATA_DIR
312
+
313
+ def get_db_path(self) -> str:
314
+ """获取数据库文件路径
315
+
316
+ 返回:
317
+ str: 数据库文件的完整路径字符串(仅 SQLite 类型有效)
318
+ """
319
+ return self.db_path
320
+
321
+
322
+
323
+ # 使用示例
324
+ if __name__ == "__main__":
325
+ # 1. 默认 SQLite(最常用)
326
+ config = MagicDatabaseConfig()
327
+ print(config.get_connection_string())
328
+ # 输出: sqlite:///Users/xxx/magic/data/magic.db
329
+
330
+ # 2. 自定义 SQLite
331
+ config = MagicDatabaseConfig(
332
+ DatabaseType.SQLITE,
333
+ path="./myapp.db",
334
+ echo=True
335
+ )
336
+
337
+ # 3. PostgreSQL
338
+ config = MagicDatabaseConfig(
339
+ DatabaseType.POSTGRESQL,
340
+ host="localhost",
341
+ user="magic",
342
+ password="secret",
343
+ database="magic_db"
344
+ )
345
+
346
+ # 4. MySQL
347
+ config = MagicDatabaseConfig(
348
+ DatabaseType.MYSQL,
349
+ host="192.168.1.100",
350
+ user="root",
351
+ password="pass123",
352
+ database="magic_prod"
353
+ )