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.
- {magic_base-0.1.0/src/magic_base.egg-info → magic_base-0.1.2}/PKG-INFO +1 -1
- {magic_base-0.1.0 → magic_base-0.1.2}/pyproject.toml +10 -1
- magic_base-0.1.2/src/magic_base/__init__.py +19 -0
- {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base/config/base_config.py +2 -2
- magic_base-0.1.2/src/magic_base/constants/tables.py +10 -0
- magic_base-0.1.2/src/magic_base/context/application_context.py +160 -0
- magic_base-0.1.2/src/magic_base/data_access/config/base_database_config.py +353 -0
- magic_base-0.1.2/src/magic_base/data_access/manager/base_database_manager.py +298 -0
- magic_base-0.1.2/src/magic_base/data_access/model/base_entity.py +241 -0
- magic_base-0.1.2/src/magic_base/data_access/repository/base_repository.py +249 -0
- magic_base-0.1.2/src/magic_base/data_access/repository/base_repository_core_mixin.py +234 -0
- magic_base-0.1.2/src/magic_base/data_access/repository/base_repository_cud_mixin.py +373 -0
- magic_base-0.1.2/src/magic_base/data_access/repository/base_repository_query_mixin.py +462 -0
- magic_base-0.1.2/src/magic_base/data_access/repository/base_sqlalchemy_repository.py +308 -0
- magic_base-0.1.2/src/magic_base/data_access/service/base_service.py +141 -0
- magic_base-0.1.2/src/magic_base/data_access/service/base_service_core_mixin.py +108 -0
- magic_base-0.1.2/src/magic_base/data_access/service/base_service_cud_mixin.py +295 -0
- magic_base-0.1.2/src/magic_base/data_access/service/base_service_query_mixin.py +264 -0
- magic_base-0.1.2/src/magic_base/data_access/util/__init__.py +10 -0
- magic_base-0.1.2/src/magic_base/data_access/util/base_data_command.py +233 -0
- magic_base-0.1.2/src/magic_base/data_access/util/base_db_command.py +136 -0
- magic_base-0.1.2/src/magic_base/data_access/util/base_db_table_util.py +350 -0
- magic_base-0.1.2/src/magic_base/data_access/util/base_db_util.py +311 -0
- magic_base-0.1.2/src/magic_base/data_access/util/base_type_converter.py +117 -0
- magic_base-0.1.2/src/magic_base/i18n/__init__.py +16 -0
- magic_base-0.1.2/src/magic_base/i18n/factory.py +30 -0
- magic_base-0.1.2/src/magic_base/i18n/language.py +40 -0
- magic_base-0.1.2/src/magic_base/i18n/languages/__init__.py +5 -0
- magic_base-0.1.2/src/magic_base/i18n/languages/en_US.py +16 -0
- magic_base-0.1.2/src/magic_base/i18n/languages/zh_CN.py +16 -0
- magic_base-0.1.2/src/magic_base/i18n/provider.py +19 -0
- magic_base-0.1.2/src/magic_base/utils/__init__.py +4 -0
- magic_base-0.1.2/src/magic_base/utils/base_csv_validator.py +127 -0
- {magic_base-0.1.0 → magic_base-0.1.2/src/magic_base.egg-info}/PKG-INFO +1 -1
- {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base.egg-info/SOURCES.txt +26 -2
- magic_base-0.1.0/src/magic_base/data_access/config/base_database_config.py +0 -85
- magic_base-0.1.0/src/magic_base/data_access/manager/base_database_manager.py +0 -0
- magic_base-0.1.0/src/magic_base/data_access/model/base_model.py +0 -10
- magic_base-0.1.0/src/magic_base/data_access/repository/base_repository.py +0 -84
- magic_base-0.1.0/src/magic_base/data_access/service/base_service.py +0 -0
- magic_base-0.1.0/src/magic_base/types/__init__.py +0 -0
- {magic_base-0.1.0 → magic_base-0.1.2}/LICENSE +0 -0
- {magic_base-0.1.0 → magic_base-0.1.2}/README.md +0 -0
- {magic_base-0.1.0 → magic_base-0.1.2}/setup.cfg +0 -0
- {magic_base-0.1.0/src/magic_base → magic_base-0.1.2/src/magic_base/config}/__init__.py +0 -0
- {magic_base-0.1.0/src/magic_base/config → magic_base-0.1.2/src/magic_base/crypto}/__init__.py +0 -0
- {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base/crypto/base_cert.py +0 -0
- {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base/crypto/base_crypto.py +0 -0
- {magic_base-0.1.0/src/magic_base/crypto → magic_base-0.1.2/src/magic_base/data_access}/__init__.py +0 -0
- {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
- {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
- {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
- {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
- {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
- {magic_base-0.1.0/src/magic_base/data_access/service → magic_base-0.1.2/src/magic_base/detector}/__init__.py +0 -0
- {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base/detector/base_detector.py +0 -0
- {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base/detector/base_hardware_define.py +0 -0
- {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base/detector/base_hardware_result.py +0 -0
- {magic_base-0.1.0/src/magic_base/detector → magic_base-0.1.2/src/magic_base/exceptions}/__init__.py +0 -0
- {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base/exceptions/base_exceptions.py +0 -0
- {magic_base-0.1.0/src/magic_base/exceptions → magic_base-0.1.2/src/magic_base/platform}/__init__.py +0 -0
- {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base/platform/base_platform_adapter.py +0 -0
- {magic_base-0.1.0/src/magic_base/platform → magic_base-0.1.2/src/magic_base/types}/__init__.py +0 -0
- {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base/types/base_types.py +0 -0
- {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base.egg-info/dependency_links.txt +0 -0
- {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base.egg-info/requires.txt +0 -0
- {magic_base-0.1.0 → magic_base-0.1.2}/src/magic_base.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "magic-base"
|
|
7
|
-
version = "0.1.
|
|
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/
|
|
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
|
|
10
|
+
class BaseConfig(ABC):
|
|
11
11
|
"""配置管理基类"""
|
|
12
12
|
|
|
13
13
|
@abstractmethod
|
|
@@ -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
|
+
)
|