magic-base 0.1.2__tar.gz → 0.1.3__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.2/src/magic_base.egg-info → magic_base-0.1.3}/PKG-INFO +1 -1
- {magic_base-0.1.2 → magic_base-0.1.3}/pyproject.toml +1 -1
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/__init__.py +2 -0
- magic_base-0.1.3/src/magic_base/config/base_config.py +155 -0
- magic_base-0.1.3/src/magic_base/data_access/model/base_dataclass.py +169 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/data_access/repository/base_repository.py +2 -2
- magic_base-0.1.3/src/magic_base/data_access/repository/base_tree_repository.py +50 -0
- magic_base-0.1.3/src/magic_base/data_access/repository/base_vector_repository.py +53 -0
- magic_base-0.1.3/src/magic_base/data_access/repository/mixin/base_tree_repository_mixin.py +227 -0
- magic_base-0.1.3/src/magic_base/data_access/repository/mixin/base_vector_repository_mixin.py +125 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/data_access/service/base_service.py +76 -50
- magic_base-0.1.3/src/magic_base/data_access/service/base_tree_service.py +56 -0
- magic_base-0.1.3/src/magic_base/data_access/service/base_vector_service.py +58 -0
- magic_base-0.1.3/src/magic_base/data_access/service/mixin/base_tree_service_mixin.py +274 -0
- magic_base-0.1.3/src/magic_base/data_access/service/mixin/base_vector_service_mixin.py +151 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/data_access/util/__init__.py +7 -1
- magic_base-0.1.3/src/magic_base/data_access/util/base_db_command.py +344 -0
- magic_base-0.1.3/src/magic_base/data_access/util/base_uniqueness_checker.py +155 -0
- magic_base-0.1.3/src/magic_base/i18n/factory.py +157 -0
- magic_base-0.1.3/src/magic_base/i18n/language.py +148 -0
- magic_base-0.1.3/src/magic_base/i18n/provider.py +173 -0
- magic_base-0.1.3/src/magic_base/platform/__init__.py +0 -0
- magic_base-0.1.3/src/magic_base/protocol/__init__.py +4 -0
- magic_base-0.1.3/src/magic_base/protocol/pipeline/__init__.py +6 -0
- magic_base-0.1.3/src/magic_base/protocol/pipeline/cmd/command.py +193 -0
- magic_base-0.1.3/src/magic_base/protocol/pipeline/data_class/__init__.py +6 -0
- magic_base-0.1.3/src/magic_base/protocol/pipeline/data_class/command_config.py +53 -0
- magic_base-0.1.3/src/magic_base/protocol/pipeline/data_class/step.py +22 -0
- magic_base-0.1.3/src/magic_base/protocol/pipeline/model.py +132 -0
- magic_base-0.1.3/src/magic_base/protocol/request/request.py +254 -0
- magic_base-0.1.3/src/magic_base/protocol/result/__init__.py +3 -0
- magic_base-0.1.3/src/magic_base/protocol/result/result.py +279 -0
- magic_base-0.1.3/src/magic_base/protocol/result/result_helper.py +128 -0
- magic_base-0.1.3/src/magic_base/types/__init__.py +0 -0
- magic_base-0.1.3/src/magic_base/types/base_types.py +212 -0
- magic_base-0.1.3/src/magic_base/utils/base_csv_validator.py +314 -0
- {magic_base-0.1.2 → magic_base-0.1.3/src/magic_base.egg-info}/PKG-INFO +1 -1
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base.egg-info/SOURCES.txt +29 -6
- magic_base-0.1.2/src/magic_base/config/base_config.py +0 -36
- magic_base-0.1.2/src/magic_base/data_access/util/base_db_command.py +0 -136
- magic_base-0.1.2/src/magic_base/i18n/factory.py +0 -30
- magic_base-0.1.2/src/magic_base/i18n/language.py +0 -40
- magic_base-0.1.2/src/magic_base/i18n/provider.py +0 -19
- magic_base-0.1.2/src/magic_base/types/base_types.py +0 -24
- magic_base-0.1.2/src/magic_base/utils/base_csv_validator.py +0 -127
- {magic_base-0.1.2 → magic_base-0.1.3}/LICENSE +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/README.md +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/setup.cfg +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/config/__init__.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/constants/tables.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/context/application_context.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/crypto/__init__.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/crypto/base_cert.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/crypto/base_crypto.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/data_access/__init__.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/data_access/config/__init__.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/data_access/config/base_database_config.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/data_access/manager/__init__.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/data_access/manager/base_database_manager.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/data_access/model/__init__.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/data_access/model/base_entity.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/data_access/repository/__init__.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/data_access/repository/base_sqlalchemy_repository.py +0 -0
- {magic_base-0.1.2/src/magic_base/data_access/service → magic_base-0.1.3/src/magic_base/data_access/repository/mixin}/__init__.py +0 -0
- {magic_base-0.1.2/src/magic_base/data_access/repository → magic_base-0.1.3/src/magic_base/data_access/repository/mixin}/base_repository_core_mixin.py +0 -0
- {magic_base-0.1.2/src/magic_base/data_access/repository → magic_base-0.1.3/src/magic_base/data_access/repository/mixin}/base_repository_cud_mixin.py +0 -0
- {magic_base-0.1.2/src/magic_base/data_access/repository → magic_base-0.1.3/src/magic_base/data_access/repository/mixin}/base_repository_query_mixin.py +0 -0
- {magic_base-0.1.2/src/magic_base/detector → magic_base-0.1.3/src/magic_base/data_access/service}/__init__.py +0 -0
- {magic_base-0.1.2/src/magic_base/exceptions → magic_base-0.1.3/src/magic_base/data_access/service/mixin}/__init__.py +0 -0
- {magic_base-0.1.2/src/magic_base/data_access/service → magic_base-0.1.3/src/magic_base/data_access/service/mixin}/base_service_core_mixin.py +0 -0
- {magic_base-0.1.2/src/magic_base/data_access/service → magic_base-0.1.3/src/magic_base/data_access/service/mixin}/base_service_cud_mixin.py +0 -0
- {magic_base-0.1.2/src/magic_base/data_access/service → magic_base-0.1.3/src/magic_base/data_access/service/mixin}/base_service_query_mixin.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/data_access/util/base_data_command.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/data_access/util/base_db_table_util.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/data_access/util/base_db_util.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/data_access/util/base_type_converter.py +0 -0
- {magic_base-0.1.2/src/magic_base/platform → magic_base-0.1.3/src/magic_base/detector}/__init__.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/detector/base_detector.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/detector/base_hardware_define.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/detector/base_hardware_result.py +0 -0
- {magic_base-0.1.2/src/magic_base/types → magic_base-0.1.3/src/magic_base/exceptions}/__init__.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/exceptions/base_exceptions.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/i18n/__init__.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/i18n/languages/__init__.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/i18n/languages/en_US.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/i18n/languages/zh_CN.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/platform/base_platform_adapter.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/utils/__init__.py +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base.egg-info/dependency_links.txt +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base.egg-info/requires.txt +0 -0
- {magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base.egg-info/top_level.txt +0 -0
|
@@ -4,6 +4,7 @@ from magic_base.config.base_config import BaseConfig
|
|
|
4
4
|
from magic_base.data_access.config.base_database_config import BaseDatabaseConfig, MagicDatabaseConfig
|
|
5
5
|
from magic_base.data_access.manager.base_database_manager import BaseDatabaseManager, MagicDatabaseManager
|
|
6
6
|
from magic_base.data_access.model.base_entity import Base, BaseEntity, MagicBaseEntity
|
|
7
|
+
from magic_base.data_access.model.base_dataclass import BaseDataClass
|
|
7
8
|
from magic_base.data_access.repository.base_repository import BaseRepository, MagicBaseRepository
|
|
8
9
|
from magic_base.data_access.service.base_service import BaseService, MagicBaseService
|
|
9
10
|
from magic_base.context.application_context import ApplicationContext
|
|
@@ -13,6 +14,7 @@ __all__ = [
|
|
|
13
14
|
'BaseConfig', 'BaseDatabaseConfig', 'MagicDatabaseConfig',
|
|
14
15
|
'BaseDatabaseManager', 'MagicDatabaseManager',
|
|
15
16
|
'Base', 'BaseEntity', 'MagicBaseEntity',
|
|
17
|
+
'BaseDataClass',
|
|
16
18
|
'BaseRepository', 'MagicBaseRepository',
|
|
17
19
|
'BaseService', 'MagicBaseService',
|
|
18
20
|
'CSVValidator'
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# magic_base/config/base_config.py
|
|
2
|
+
"""
|
|
3
|
+
配置管理基类
|
|
4
|
+
|
|
5
|
+
提供配置管理的抽象接口,定义了配置获取、设置、加载、保存和重载的标准方法。
|
|
6
|
+
所有具体配置管理实现都应继承此类并实现其抽象方法。
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from abc import ABC, abstractmethod
|
|
10
|
+
from typing import Any, Dict, Optional
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BaseConfig(ABC):
|
|
14
|
+
"""
|
|
15
|
+
配置管理基类(抽象类)
|
|
16
|
+
|
|
17
|
+
定义了配置管理器的标准接口,包括配置的读取、写入、持久化等操作。
|
|
18
|
+
子类需要实现具体的配置存储方式(如文件、数据库、远程配置中心等)。
|
|
19
|
+
|
|
20
|
+
使用示例:
|
|
21
|
+
class MyConfig(BaseConfig):
|
|
22
|
+
def get(self, key: str, default: Any = None) -> Any:
|
|
23
|
+
# 实现获取配置逻辑
|
|
24
|
+
return self._config.get(key, default)
|
|
25
|
+
|
|
26
|
+
def set(self, key: str, value: Any) -> None:
|
|
27
|
+
# 实现设置配置逻辑
|
|
28
|
+
self._config[key] = value
|
|
29
|
+
|
|
30
|
+
def load(self) -> Dict[str, Any]:
|
|
31
|
+
# 实现加载配置逻辑
|
|
32
|
+
return self._config
|
|
33
|
+
|
|
34
|
+
def save(self) -> bool:
|
|
35
|
+
# 实现保存配置逻辑
|
|
36
|
+
return True
|
|
37
|
+
|
|
38
|
+
def reload(self) -> None:
|
|
39
|
+
# 实现重载配置逻辑
|
|
40
|
+
self.load()
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
@abstractmethod
|
|
44
|
+
def get(self, key: str, default: Any = None) -> Any:
|
|
45
|
+
"""
|
|
46
|
+
获取配置值
|
|
47
|
+
|
|
48
|
+
根据指定的键名获取对应的配置值。如果键不存在,返回默认值。
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
key (str): 配置键名,支持点号分隔的嵌套键(如 'database.host')
|
|
52
|
+
default (Any, optional): 当键不存在时返回的默认值。默认为 None
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
Any: 配置值,如果键不存在则返回 default 参数指定的值
|
|
56
|
+
|
|
57
|
+
Raises:
|
|
58
|
+
KeyError: 当键不存在且未提供 default 参数时可能抛出(具体取决于子类实现)
|
|
59
|
+
|
|
60
|
+
Example:
|
|
61
|
+
>>> config.get('app.name')
|
|
62
|
+
'MyApp'
|
|
63
|
+
>>> config.get('app.timeout', 30)
|
|
64
|
+
30
|
|
65
|
+
"""
|
|
66
|
+
pass
|
|
67
|
+
|
|
68
|
+
@abstractmethod
|
|
69
|
+
def set(self, key: str, value: Any) -> None:
|
|
70
|
+
"""
|
|
71
|
+
设置配置值
|
|
72
|
+
|
|
73
|
+
将指定的键值对写入配置中。如果键已存在,则覆盖原有值;
|
|
74
|
+
如果键不存在,则创建新配置项。
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
key (str): 配置键名,支持点号分隔的嵌套键(如 'database.host')
|
|
78
|
+
value (Any): 要设置的配置值,可以是任意可序列化的 Python 对象
|
|
79
|
+
|
|
80
|
+
Raises:
|
|
81
|
+
TypeError: 当 value 类型不被支持时抛出
|
|
82
|
+
ValueError: 当 key 格式无效时抛出
|
|
83
|
+
|
|
84
|
+
Example:
|
|
85
|
+
>>> config.set('app.debug', True)
|
|
86
|
+
>>> config.set('database.port', 3306)
|
|
87
|
+
"""
|
|
88
|
+
pass
|
|
89
|
+
|
|
90
|
+
@abstractmethod
|
|
91
|
+
def load(self) -> Dict[str, Any]:
|
|
92
|
+
"""
|
|
93
|
+
加载配置
|
|
94
|
+
|
|
95
|
+
从存储介质(如文件、数据库等)中读取配置数据并加载到内存中。
|
|
96
|
+
通常用于初始化或手动触发配置加载。
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
Dict[str, Any]: 加载后的配置字典,包含所有配置项
|
|
100
|
+
|
|
101
|
+
Raises:
|
|
102
|
+
FileNotFoundError: 当配置文件不存在时抛出
|
|
103
|
+
PermissionError: 当没有读取权限时抛出
|
|
104
|
+
json.JSONDecodeError: 当配置文件格式错误时抛出(针对 JSON 格式)
|
|
105
|
+
|
|
106
|
+
Example:
|
|
107
|
+
>>> config = MyConfig()
|
|
108
|
+
>>> config.load()
|
|
109
|
+
{'app': {'name': 'MyApp', 'version': '1.0'}}
|
|
110
|
+
"""
|
|
111
|
+
pass
|
|
112
|
+
|
|
113
|
+
@abstractmethod
|
|
114
|
+
def save(self) -> bool:
|
|
115
|
+
"""
|
|
116
|
+
保存配置
|
|
117
|
+
|
|
118
|
+
将当前内存中的配置持久化到存储介质中(如文件、数据库等)。
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
bool: 保存成功返回 True,失败返回 False
|
|
122
|
+
|
|
123
|
+
Raises:
|
|
124
|
+
PermissionError: 当没有写入权限时抛出
|
|
125
|
+
IOError: 当写入过程中发生 I/O 错误时抛出
|
|
126
|
+
|
|
127
|
+
Example:
|
|
128
|
+
>>> if config.save():
|
|
129
|
+
... print("配置保存成功")
|
|
130
|
+
... else:
|
|
131
|
+
... print("配置保存失败")
|
|
132
|
+
"""
|
|
133
|
+
pass
|
|
134
|
+
|
|
135
|
+
@abstractmethod
|
|
136
|
+
def reload(self) -> None:
|
|
137
|
+
"""
|
|
138
|
+
重新加载配置
|
|
139
|
+
|
|
140
|
+
丢弃当前内存中的配置,重新从存储介质加载最新的配置数据。
|
|
141
|
+
通常用于配置热更新场景。
|
|
142
|
+
|
|
143
|
+
注意:重新加载会覆盖所有未保存的配置修改,请谨慎使用。
|
|
144
|
+
|
|
145
|
+
Raises:
|
|
146
|
+
FileNotFoundError: 当配置文件不存在时抛出
|
|
147
|
+
PermissionError: 当没有读取权限时抛出
|
|
148
|
+
|
|
149
|
+
Example:
|
|
150
|
+
>>> # 配置文件被外部修改后
|
|
151
|
+
>>> config.reload() # 重新加载最新配置
|
|
152
|
+
>>> config.get('app.debug')
|
|
153
|
+
True
|
|
154
|
+
"""
|
|
155
|
+
pass
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# magic_base/data_access/model/base_dataclass.py
|
|
2
|
+
from dataclasses import dataclass, asdict, fields, is_dataclass
|
|
3
|
+
from typing import Dict, Any, TypeVar, Type, Union
|
|
4
|
+
import json
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
T = TypeVar('T', bound='BaseDataClass')
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class BaseDataClass:
|
|
11
|
+
"""
|
|
12
|
+
数据类基类
|
|
13
|
+
|
|
14
|
+
提供 to_dict、from_dict、update_from_dict 等通用方法。
|
|
15
|
+
所有使用 @dataclass 装饰的类都应该继承此类。
|
|
16
|
+
|
|
17
|
+
使用示例:
|
|
18
|
+
@dataclass
|
|
19
|
+
class ProjectInfo(BaseDataClass):
|
|
20
|
+
name: str
|
|
21
|
+
version: str = "1.0.0"
|
|
22
|
+
|
|
23
|
+
# 转换
|
|
24
|
+
project = ProjectInfo(name="test")
|
|
25
|
+
data = project.to_dict() # {'name': 'test', 'version': '1.0.0'}
|
|
26
|
+
|
|
27
|
+
# 创建
|
|
28
|
+
new_project = ProjectInfo.from_dict({'name': 'test', 'version': '2.0.0'})
|
|
29
|
+
|
|
30
|
+
# 更新
|
|
31
|
+
project.update_from_dict({'version': '2.0.0'})
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
35
|
+
"""
|
|
36
|
+
将数据类实例转换为字典
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
Dict[str, Any]: 包含所有字段的字典,嵌套的数据类也会被递归转换
|
|
40
|
+
|
|
41
|
+
Example:
|
|
42
|
+
>>> @dataclass
|
|
43
|
+
... class SubConfig(BaseDataClass):
|
|
44
|
+
... key: str
|
|
45
|
+
...
|
|
46
|
+
>>> @dataclass
|
|
47
|
+
... class MainConfig(BaseDataClass):
|
|
48
|
+
... name: str
|
|
49
|
+
... sub: SubConfig
|
|
50
|
+
...
|
|
51
|
+
>>> main = MainConfig(name="test", sub=SubConfig(key="value"))
|
|
52
|
+
>>> main.to_dict()
|
|
53
|
+
{'name': 'test', 'sub': {'key': 'value'}}
|
|
54
|
+
"""
|
|
55
|
+
return self._to_dict_recursive(self)
|
|
56
|
+
|
|
57
|
+
def _to_dict_recursive(self, obj: Any) -> Any:
|
|
58
|
+
"""递归转换嵌套的数据类"""
|
|
59
|
+
if is_dataclass(obj):
|
|
60
|
+
result = {}
|
|
61
|
+
for field in fields(obj):
|
|
62
|
+
value = getattr(obj, field.name)
|
|
63
|
+
result[field.name] = self._to_dict_recursive(value)
|
|
64
|
+
return result
|
|
65
|
+
elif isinstance(obj, list):
|
|
66
|
+
return [self._to_dict_recursive(item) for item in obj]
|
|
67
|
+
elif isinstance(obj, dict):
|
|
68
|
+
return {k: self._to_dict_recursive(v) for k, v in obj.items()}
|
|
69
|
+
else:
|
|
70
|
+
return obj
|
|
71
|
+
|
|
72
|
+
@classmethod
|
|
73
|
+
def from_dict(cls: Type[T], data: Dict[str, Any]) -> T:
|
|
74
|
+
"""
|
|
75
|
+
从字典创建数据类实例
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
data: 包含字段的字典
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
T: 数据类实例
|
|
82
|
+
"""
|
|
83
|
+
if not is_dataclass(cls):
|
|
84
|
+
raise TypeError(f"{cls.__name__} 必须是 dataclass")
|
|
85
|
+
|
|
86
|
+
return cls._from_dict_recursive(cls, data)
|
|
87
|
+
|
|
88
|
+
@classmethod
|
|
89
|
+
def _from_dict_recursive(cls, target_class: Type, data: Dict[str, Any]) -> Any:
|
|
90
|
+
"""递归创建嵌套的数据类"""
|
|
91
|
+
if not is_dataclass(target_class):
|
|
92
|
+
return data
|
|
93
|
+
|
|
94
|
+
field_types = {f.name: f.type for f in fields(target_class)}
|
|
95
|
+
processed = {}
|
|
96
|
+
|
|
97
|
+
for field_name, field_value in data.items():
|
|
98
|
+
if field_name not in field_types:
|
|
99
|
+
continue
|
|
100
|
+
|
|
101
|
+
field_type = field_types[field_name]
|
|
102
|
+
# 处理 Optional 类型(简化处理)
|
|
103
|
+
if hasattr(field_type, '__origin__') and field_type.__origin__ is Union:
|
|
104
|
+
# 提取 Union 中的实际类型
|
|
105
|
+
for arg in field_type.__args__:
|
|
106
|
+
if is_dataclass(arg):
|
|
107
|
+
field_type = arg
|
|
108
|
+
break
|
|
109
|
+
|
|
110
|
+
if is_dataclass(field_type):
|
|
111
|
+
processed[field_name] = cls._from_dict_recursive(field_type, field_value)
|
|
112
|
+
elif isinstance(field_value, list) and field_value:
|
|
113
|
+
# 处理列表中的嵌套数据类
|
|
114
|
+
processed[field_name] = [
|
|
115
|
+
cls._from_dict_recursive(field_type.__args__[0], item)
|
|
116
|
+
if hasattr(field_type, '__args__') and is_dataclass(field_type.__args__[0])
|
|
117
|
+
else item
|
|
118
|
+
for item in field_value
|
|
119
|
+
]
|
|
120
|
+
else:
|
|
121
|
+
processed[field_name] = field_value
|
|
122
|
+
|
|
123
|
+
return target_class(**processed)
|
|
124
|
+
|
|
125
|
+
def update_from_dict(self, data: Dict[str, Any]) -> 'BaseDataClass':
|
|
126
|
+
"""
|
|
127
|
+
从字典更新当前实例
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
data: 包含待更新字段的字典
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
BaseDataClass: 当前实例(支持链式调用)
|
|
134
|
+
"""
|
|
135
|
+
for key, value in data.items():
|
|
136
|
+
if hasattr(self, key):
|
|
137
|
+
current_value = getattr(self, key)
|
|
138
|
+
# 如果当前值是数据类,且新值也是字典,递归更新
|
|
139
|
+
if is_dataclass(current_value) and isinstance(value, dict):
|
|
140
|
+
current_value.update_from_dict(value)
|
|
141
|
+
else:
|
|
142
|
+
setattr(self, key, value)
|
|
143
|
+
return self
|
|
144
|
+
|
|
145
|
+
def to_json(self, indent: int = None) -> str:
|
|
146
|
+
"""
|
|
147
|
+
转换为 JSON 字符串
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
indent: JSON 缩进空格数
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
str: JSON 字符串
|
|
154
|
+
"""
|
|
155
|
+
return json.dumps(self.to_dict(), ensure_ascii=False, indent=indent)
|
|
156
|
+
|
|
157
|
+
@classmethod
|
|
158
|
+
def from_json(cls: Type[T], json_str: str) -> T:
|
|
159
|
+
"""
|
|
160
|
+
从 JSON 字符串创建实例
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
json_str: JSON 字符串
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
T: 数据类实例
|
|
167
|
+
"""
|
|
168
|
+
data = json.loads(json_str)
|
|
169
|
+
return cls.from_dict(data)
|
{magic_base-0.1.2 → magic_base-0.1.3}/src/magic_base/data_access/repository/base_repository.py
RENAMED
|
@@ -5,8 +5,8 @@ from typing import Dict, List, Optional, TypeVar, Generic, Type, Any, get_origin
|
|
|
5
5
|
from sqlalchemy.orm import Session
|
|
6
6
|
from sqlalchemy import inspect, text
|
|
7
7
|
|
|
8
|
-
from .base_repository_cud_mixin import CUDRepositoryMixin
|
|
9
|
-
from .base_repository_query_mixin import QueryRepositoryMixin
|
|
8
|
+
from .mixin.base_repository_cud_mixin import CUDRepositoryMixin
|
|
9
|
+
from .mixin.base_repository_query_mixin import QueryRepositoryMixin
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
T = TypeVar('T')
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# magic_base/data_access/repository/base_tree_repository.py
|
|
2
|
+
"""
|
|
3
|
+
BaseTreeRepository - 树结构专属 Repository 基类
|
|
4
|
+
|
|
5
|
+
定位:
|
|
6
|
+
MagicBaseRepository + TreeRepositoryMixin 的预设组合。
|
|
7
|
+
层次表专属 Repository 直接继承即用。
|
|
8
|
+
|
|
9
|
+
使用方式:
|
|
10
|
+
class SystemHierarchyDefRepository(BaseTreeRepository[SystemHierarchyDefs]):
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
等价于:
|
|
14
|
+
class SystemHierarchyDefRepository(
|
|
15
|
+
MagicBaseRepository[SystemHierarchyDefs],
|
|
16
|
+
TreeRepositoryMixin[SystemHierarchyDefs],
|
|
17
|
+
):
|
|
18
|
+
pass
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from typing import TypeVar
|
|
22
|
+
|
|
23
|
+
from .base_repository import MagicBaseRepository
|
|
24
|
+
from .mixin.base_tree_repository_mixin import TreeRepositoryMixin
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
T = TypeVar('T')
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class BaseTreeRepository(
|
|
31
|
+
MagicBaseRepository[T],
|
|
32
|
+
TreeRepositoryMixin[T],
|
|
33
|
+
):
|
|
34
|
+
"""
|
|
35
|
+
树结构专属 Repository 基类
|
|
36
|
+
|
|
37
|
+
组合:
|
|
38
|
+
- MagicBaseRepository:通用 CRUD(CUD + Query)
|
|
39
|
+
- TreeRepositoryMixin:树专属数据访问
|
|
40
|
+
|
|
41
|
+
提供能力:
|
|
42
|
+
- 通用:create / update / delete / find / find_one / count / paginate
|
|
43
|
+
- 树专属:find_edge / find_children / find_parents / has_parent
|
|
44
|
+
/ find_subtree_by_path / find_edges_by_parents
|
|
45
|
+
/ find_ancestor_path / is_descendant / get_max_order_no
|
|
46
|
+
|
|
47
|
+
注意:
|
|
48
|
+
通常通过子类继承使用,子类需指定泛型类型 T(层次表 ORM 模型)。
|
|
49
|
+
"""
|
|
50
|
+
pass
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# magic_base/data_access/repository/base_vector_repository.py
|
|
2
|
+
"""
|
|
3
|
+
BaseVectorRepository - 向量结构专属 Repository 基类
|
|
4
|
+
|
|
5
|
+
定位:
|
|
6
|
+
MagicBaseRepository + VectorRepositoryMixin 的预设组合。
|
|
7
|
+
向量表专属 Repository 直接继承即用。
|
|
8
|
+
|
|
9
|
+
使用方式:
|
|
10
|
+
class SystemModelMemberVectorRepository(
|
|
11
|
+
BaseVectorRepository[SystemModelMemberVectors]
|
|
12
|
+
):
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
等价于:
|
|
16
|
+
class SystemModelMemberVectorRepository(
|
|
17
|
+
MagicBaseRepository[SystemModelMemberVectors],
|
|
18
|
+
VectorRepositoryMixin[SystemModelMemberVectors],
|
|
19
|
+
):
|
|
20
|
+
pass
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from typing import TypeVar
|
|
24
|
+
|
|
25
|
+
from .base_repository import MagicBaseRepository
|
|
26
|
+
from .mixin.base_vector_repository_mixin import VectorRepositoryMixin
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
T = TypeVar('T')
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class BaseVectorRepository(
|
|
33
|
+
MagicBaseRepository[T],
|
|
34
|
+
VectorRepositoryMixin[T],
|
|
35
|
+
):
|
|
36
|
+
"""
|
|
37
|
+
向量结构专属 Repository 基类
|
|
38
|
+
|
|
39
|
+
组合:
|
|
40
|
+
- MagicBaseRepository:通用 CRUD(CUD + Query)
|
|
41
|
+
- VectorRepositoryMixin:向量专属数据访问
|
|
42
|
+
|
|
43
|
+
提供能力:
|
|
44
|
+
- 通用:create / update / delete / find / find_one / count / paginate
|
|
45
|
+
- 向量专属:find_vector / find_vectors_by_owner
|
|
46
|
+
/ list_encodings / delete_vector
|
|
47
|
+
|
|
48
|
+
注意:
|
|
49
|
+
通常通过子类继承使用,子类需指定泛型类型 T(向量表 ORM 模型)。
|
|
50
|
+
默认字段名:member_key / vector_encoding_key / vector_encoding_value。
|
|
51
|
+
如需自定义字段名,调用时传 owner_field / encoding_field。
|
|
52
|
+
"""
|
|
53
|
+
pass
|