一个强大的对象控制工具, 覆盖了配置管理、状态管理、上下文管理和生命周期管理。
Project description
功能
- 配置管理
- 基于类型声明的配置
- 支持实时变更
- 上下文管理
- 基于描述器的依赖注入
- 优雅的上下文切换
- 生命周期管理
- 服务编排
- 状态管理
安装
pip install mapgraph
Or
pdm add mapgraph
入门指南
上下文管理
from mapgraph.context import InstanceContext
InstanceContext 实例上下文, 顾名思义是管理 对象 的抽象, 它通过两个维度对 对象 进行管理, 即 名义类型 与 值。
名义类型可以理解为变量名或者是变量类型, 总之它在当前实例上下文是唯一的KEY值很好理解,即是某个被管理的对象
from mapgraph.globals import GLOBAL_INSTANCE_CONTEXT
GLOBAL_INSTANCE_CONTEXT 全局实例上下文, 即最顶层的命名空间, 本质也是一个 InstanceContext。
基本使用
from typing import NewType
from mapgraph.globals import GLOBAL_INSTANCE_CONTEXT
from mapgraph.instance_of import get_instance
MYINT = NewType("MYINT", int)
GLOBAL_INSTANCE_CONTEXT.store(123, "test")
# GLOBAL_INSTANCE_CONTEXT.store({int: 123, str: "test"})
GLOBAL_INSTANCE_CONTEXT.store({list[int]: [1,2,3]})
GLOBAL_INSTANCE_CONTEXT.store({MYINT: -123})
print(get_instance(int)) # 123
print(get_instance(MYINT)) # 123
print(get_instance(MYINT, is_key=True)) # -123
print(get_instance(str)) # test
print(get_instance(list[int])) # [1,2,3]
get_instance可以通过类型获取InstanceContext中的值, 当is_key=True为名义类型匹配, 反之为值匹配.store拥有可变位置参数collection_or_targets类型为Mapping[type, Any] | Any.store(123, "test")等价于.store({int: 123, str: "test"})
因为运行时类型检查器拥有的局限性,所以分别引入了
名义类型与值,它们相互补充
多级实例上下文
from mapgraph.context import InstanceContext
from mapgraph.globals import GLOBAL_INSTANCE_CONTEXT
from mapgraph.instance_of import get_instance
loacl_context = InstanceContext()
GLOBAL_INSTANCE_CONTEXT.store(123, {list[int]: [1,2,3]})
loacl_context.store("test", -123)
print(get_instance(int)) # 123
# print(get_instance(str)) # ValueError: <class 'str'>
with loacl_context.scope():
print(get_instance(str)) # test
print(get_instance(int)) # -123
print(get_instance(list[int])) # [1,2,3]
with loacl_context.scope(inherit=False):
print(get_instance(str)) # test
print(get_instance(int)) # -123
print(get_instance(list[int])) # ValueError: <class 'list[int]'>
.scope拥有关键字参数inherit, 表示是否继承上一级InstanceContext
描述器支持
from typing import NewType
from httpx import AsyncClient
from mapgraph.globals import GLOBAL_INSTANCE_CONTEXT
from mapgraph.instance_of import get_instance, InstanceOf, InstanceOfK, InstanceOfV
OPENAI_API_KEY = NewType("OPENAI_API_KEY", str)
class Test:
client: InstanceOfV[AsyncClient] = InstanceOf(AsyncClient)
openai_api_key: InstanceOfK[OPENAI_API_KEY] = InstanceOf(OPENAI_API_KEY, is_key=True)
GLOBAL_INSTANCE_CONTEXT.store({OPENAI_API_KEY: "test"}, AsyncClient())
test = Test()
print(test.client) # <httpx.AsyncClient object at 0x7f7f7f7f7f7f>
print(test.openai_api_key) # test
InstanceOf 是一个函数会返两种描述器 InstanceOfV[T] 与 InstanceOfK[T], 很好理解 前者被声明为通过 值 匹配, 后者被声明通过 名义类型 匹配。
描述器读取
from typing import NewType
from httpx import AsyncClient
from mapgraph.context import InstanceContext
from mapgraph.globals import GLOBAL_INSTANCE_CONTEXT
from mapgraph.instance_of import get_instance, InstanceOf, InstanceOfK, InstanceOfV
OPENAI_API_KEY = NewType("OPENAI_API_KEY", str)
BASE_URL = NewType("BASE_URL", str)
loacl_context = InstanceContext()
class Test:
client: InstanceOfV[AsyncClient] = InstanceOf(AsyncClient)
openai_api_key: InstanceOfK[OPENAI_API_KEY] = InstanceOf(OPENAI_API_KEY, is_key=True)
base_url: InstanceOfK[BASE_URL] = InstanceOf(BASE_URL, is_key=True)
GLOBAL_INSTANCE_CONTEXT.store({OPENAI_API_KEY: "sk-proj-xxx", BASE_URL: "https://api.openai.com"}, AsyncClient())
loacl_context.store({BASE_URL: "https://api.xxxmy.com"})
test = Test()
print(test.client) # <httpx.AsyncClient object at 0x7f7f7f7f7f7f>
print(test.openai_api_key) # sk-proj-xxx
print(test.base_url) # https://api.openai.com
with loacl_context.scope():
print(test.base_url) # https://api.xxxmy.com
描述器写入
from typing import NewType
from httpx import AsyncClient
from mapgraph.context import InstanceContext
from mapgraph.globals import GLOBAL_INSTANCE_CONTEXT
from mapgraph.instance_of import get_instance, InstanceOf, InstanceOfK, InstanceOfV
OPENAI_API_KEY = NewType("OPENAI_API_KEY", str)
BASE_URL = NewType("BASE_URL", str)
loacl_context = InstanceContext()
class Test:
client: InstanceOfV[AsyncClient] = InstanceOf(AsyncClient)
base_url: InstanceOfK[BASE_URL] = InstanceOf(BASE_URL, is_key=True)
GLOBAL_INSTANCE_CONTEXT.store(
{BASE_URL: "https://api.openai.com"}, AsyncClient()
)
loacl_context.store({BASE_URL: "https://api.xxxmy.com"})
test = Test()
print(id(test.client)) # 139921911645712
print(test.base_url) # https://api.openai.com
with loacl_context.scope():
print(test.base_url) # https://api.xxxmy.com
print(id(test.client)) # 139921911645712
test.base_url = {BASE_URL: BASE_URL("https://api.yyymy.com")}
test.client = AsyncClient()
print(test.base_url) # https://api.yyymy.com
print(id(test.client)) # 140043844997072
print(test.base_url) # https://api.openai.com
print(id(test.client)) # 139921911645712
- 当描述器为
InstanceOfK[T]时, 设置值需要一个Mapping[Type[T], T] - 当描述器为
InstanceOfV[T]时, 设置值需要为T
配置管理
.env
OPENAI_API_KEY = "sk-proj-xxx"
BASE_URL = "https://api.openai.com"
MYINT = 123
MYDICT = {"a": 1}
MYLIST = [1, 2, 3]
from typing import NewType
from mapgraph.config import load_env
from mapgraph.instance_of import InstanceOf
OPENAI_API_KEY = NewType("OPENAI_API_KEY", str)
BASE_URL = NewType("BASE_URL", str)
MYINT = NewType("MYINT", int)
MYLIST = NewType("MYLIST", list[int])
MYDICT = NewType("MYDICT", dict[str, int])
MYBOOL = NewType("MYBOOL", bool)
class ConfigData:
a = InstanceOf(MYINT, is_key=True)
b = InstanceOf(MYLIST, is_key=True)
c = InstanceOf(MYDICT, is_key=True)
d = InstanceOf(MYBOOL, is_key=True)
class Config:
api_key = InstanceOf(OPENAI_API_KEY, is_key=True)
base_url = InstanceOf(BASE_URL, is_key=True)
data = ConfigData()
load_env(
envs=(OPENAI_API_KEY, BASE_URL, MYINT, MYLIST, MYDICT),
envs_kv={MYBOOL: False}, # 设置默认值
dotenv_path=".env"
)
config = Config()
print(config.api_key) # sk-proj-xxx
print(config.base_url) # https://api.openai.com
print(config.data.a) # 123
print(config.data.b) # [1, 2, 3]
print(config.data.c) # {'a': 1}
print(config.data.d) # False
最佳实践是控制所需的最细的粒度, 当配置较为复杂可以进行嵌套
状态管理
生命周期管理
mapgraph.lifecycle提供了launch_services服务自动编排
class BaseService(Protocol):
id: str
@property
def required(self) -> set[str]: ...
async def preparing(self) -> None: ...
async def blocking(self) -> None: ...
async def cleanup(self) -> None: ...
def get_service(self) -> set[BaseService]: ...
- id: 服务的唯一标识符
- required: 服务的依赖
- preparing: 服务的准备阶段
- blocking: 服务的阻塞阶段
- cleanup: 服务的清理阶段
- get_service: 获取服务的依赖
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mapgraph-0.2.8.tar.gz.
File metadata
- Download URL: mapgraph-0.2.8.tar.gz
- Upload date:
- Size: 10.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: pdm/2.22.3 CPython/3.13.2 Linux/6.8.0-1021-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9f56911c8729fb07a84593bb141f7f915941a7189caad3ba64ffe63c607602be
|
|
| MD5 |
46153ad6ec5ee98f09b8f0f996b7ef7f
|
|
| BLAKE2b-256 |
8c87d72df712f719e9f90ce7ff53abc7fdc61c4b950fa884242721adfc6a3646
|
File details
Details for the file mapgraph-0.2.8-py3-none-any.whl.
File metadata
- Download URL: mapgraph-0.2.8-py3-none-any.whl
- Upload date:
- Size: 11.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: pdm/2.22.3 CPython/3.13.2 Linux/6.8.0-1021-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d1b066f1e5592e5ee80ccc2ea6bbe3c61626c859cccf63f840cb028943fc74e6
|
|
| MD5 |
73eba5a8ce72c21f287bb615b985fbec
|
|
| BLAKE2b-256 |
e0dcf485ea71c03398f2b14e334614fc45e789f4244b741c9010cf18d15f6a2d
|