Metadata-Version: 2.4
Name: pyda-config
Version: 0.0.1
Summary: Python Dict Annotation — 受限字面量子集的 .da.py 配置文件校验与加载
Author-email: wangzk <biocory42@gmail.com>
License: MIT
Keywords: config,dict,literal,ast,annotation,validation
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Text Processing
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# PyDA — Python Dict Annotation

受限的 Python 字面量子集,用于**人类可读、可注释、可调试**的配置文件。

扩展名约定 `.da.py`(Dict Annotation),文件内容是一个**裸 dict 表达式**(可嵌套),只能用字面量,不能有任何求值、赋值、导入、调用。通过白名单 AST 校验保证它能被 `ast.literal_eval` 安全求值。

## 为什么

- 比 JSON 多了**注释**和**尾逗号**;
- 比 YAML 多了**结构严格、零歧义**;
- 比「真正的 Python 模块」多了**安全保证**(不执行任意代码,不引用外部符号)。

适合作为纳管多套资源的注册表(集群、服务、账号等)。

## 子集规则

### 允许

| 类型 | 语法 |
|---|---|
| 字典 | `{k: v}` |
| 列表 / 元组 / 集合 | `[...]` / `(...)` / `{...}` |
| 标量 | str / int / float / bool / None |
| 一元正负号 | `-1` / `+2` |
| 嵌套 | 任意深度 |

### 禁止(一旦出现即拒收)

- 裸变量名 `Name`(最关键的安全闸 —— 禁掉它就无法引用任何外部符号)
- 赋值 / 海象 `:=`
- `import`
- 函数调用 `f(...)`
- 二元运算、布尔运算、比较 `a + b` / `a and b` / `a == b`
- 属性 / 下标 / 切片 `a.b` / `a[b]`
- 列表 / 字典 / 集合推导式
- `def` / `class` / `lambda` / `for` / `if` 等一切语句
- `bytes` / `complex` / `...` 常量

## 用法

### 命令行

```bash
python -m pyda clusters.da.py credentials.da.py
# 或 pip install -e . 之后:
pyda clusters.da.py credentials.da.py
```

通过打印 `OK: <file>` 退出 0;不通过逐条报错并退出 1。

### Python API

```python
from pyda import check, load

# 只校验
errors = check("clusters.da.py")
assert errors == []

# 校验 + 求值
cfg = load("clusters.da.py")
print(cfg["clusters"][0]["name"])
```

### 示例 `.da.py` 文件

```python
{
    "name": "a-cluster",
    "port": 22,
    "sudo": False,          # 注释 OK
    "tags": ["cpu", "gpu"],
    "storage": {
        "shared": "/shared/a",
        "quota_gb": 5000,
    },
}
```

被拒收的写法:

```python
HOST = "login01"            # ✗ 赋值
import os                   # ✗ import
{"a": len([1, 2])}          # ✗ 函数调用
{"a": my_var}               # ✗ 裸变量名
config["b"]                 # ✗ 下标
```

## 安装

```bash
pip install -e .
```

仅依赖 Python 标准库。

## License

MIT
