Metadata-Version: 2.4
Name: shuguan-handler
Version: 0.0.2
Summary: 遥感数管的工具类插件
Author-email: zyfang <fang.zhiyong@star.vision>
Requires-Python: <3.12,>=3.10.12
Requires-Dist: bce-python-sdk==0.9.70
Requires-Dist: boto3>=1.42.95
Requires-Dist: docker>=7.1.0
Requires-Dist: emails<1.0,>=0.6
Requires-Dist: geopandas==1.1.0
Requires-Dist: jinja2<4.0.0,>=3.1.4
Requires-Dist: kubernetes>=33.1.0
Requires-Dist: minio>=7.2.5
Requires-Dist: numexpr>=2.10.1
Requires-Dist: openpyxl>=3.1.5
Requires-Dist: pillow>=10.4.0
Requires-Dist: pydantic==2.9.2
Requires-Dist: pyinstrument>=5.0.2
Requires-Dist: pysmb>=1.2.11
Requires-Dist: pystac-client>=0.8.3
Requires-Dist: pystac>=1.10.1
Requires-Dist: redis>=5.0.4
Requires-Dist: requests>=2.32.3
Requires-Dist: shapely==2.0.4
Requires-Dist: stac-pydantic>=3.1.1
Requires-Dist: sympy>=1.13.3
Provides-Extra: dev
Requires-Dist: bandit>=1.8.2; extra == 'dev'
Requires-Dist: black>=24.10.0; extra == 'dev'
Requires-Dist: eventlet>=0.36.1; extra == 'dev'
Requires-Dist: isort>=5.13.2; extra == 'dev'
Requires-Dist: pylint==3.2.7; extra == 'dev'
Requires-Dist: pytest-asyncio>=1.3.0; extra == 'dev'
Requires-Dist: pytest>=8.1.1; extra == 'dev'
Description-Content-Type: text/markdown

# shuguan-handler

遥感数管工具类插件，提供统一的对象存储（OSS）操作接口、邮件服务、容器执行、STAC 数据管理等功能。

## OSS 统一接口（OssFile）

`OssFile` 提供与具体 OSS 实现无关的文件操作方法，支持 MinIO、百度 BOS、AWS S3 三种后端。

### 快速使用

```python
from shuguan.handler.file_util import OssFile

# MinIO（minio SDK）
oss = OssFile("minio:9000", "ak", "sk", provider="minio")

# MinIO（boto3 S3 兼容）
oss = OssFile("minio:9000", "ak", "sk", provider="aws")

# 百度 BOS（BOS SDK）
oss = OssFile("bcebos.sdhy.omspcloud.com:8443", "ak", "sk", provider="bos", secure=True)

# 百度 BOS（S3 兼容地址 + boto3）
oss = OssFile("s3.bcebos.sdhy.omspcloud.com:8443", "ak", "sk",
              provider="aws", secure=True, region_name="bj", signature_version="s3v4")

# 通用操作
oss.upload_file("bucket", "key", "/local/file.txt")
oss.download_file("bucket", "key", "/tmp/file.txt")
oss.delete_file("bucket", "key")
for obj in oss.list_objects("bucket", prefix="data/"):
    print(obj)
url = oss.get_presigned_download_url("bucket", "key", expires=3600)
```

### 后端兼容性矩阵

下表记录了各 OSS 后端 + SDK 组合的功能兼容性测试结果（2026-04-28）。

| 功能 | MinIO<br>minio SDK | MinIO<br>boto3 | BOS 官方地址<br>BOS SDK | BOS S3 地址<br>BOS SDK | BOS S3 地址<br>boto3 (s3v4) |
|:---|:---:|:---:|:---:|:---:|:---:|
| `bucket_exists` | ✅ | ✅ | ✅ | ✅ | ✅ |
| `upload_file` | ✅ | ✅ | ✅ | ✅ | ❌ <sup>1</sup> |
| `object_exists` | ✅ | ✅ | ✅ | ✅ | ✅ |
| `list_objects` | ✅ | ✅ | ✅ | ❌ <sup>2</sup> | ✅ |
| `download_file` | ✅ | ✅ | ✅ | ✅ | ❌ <sup>3</sup> |
| `download_file` (进度回调) | ✅ | ✅ | ✅ | ✅ | ❌ <sup>3</sup> |
| `get_presigned_download_url` | ✅ | ✅ | ✅ | ✅ | ✅ |
| `delete_file` | ✅ | ✅ | ✅ | ✅ | ✅ |
| `OssFile.from_url` | ✅ | ✅ | ✅ | ✅ | ✅ |
| `OssFile.get_folder_size` | ✅ | ✅ | ✅ | ❌ <sup>2</sup> | ✅ |
| `OssFile.get_presigned_url` | ✅ | ✅ | ✅ | ✅ | ✅ |
| `OssFile.download_from_url` | ✅ | ✅ | ✅ | ✅ | ❌ <sup>3</sup> |

**通过率：** MinIO minio SDK 17/17 · MinIO boto3 17/17 · BOS 官方+BOS SDK 17/17 · BOS S3+BOS SDK 15/17 · BOS S3+boto3 7/12

> <sup>1</sup> **BadDigestSHA256**: BOS S3 兼容端点的 SHA256 校验机制与标准 boto3 `s3transfer` 不兼容，`upload_file` 时服务端返回 `BadDigestSHA256`。  
> <sup>2</sup> **list_objects JSON 解析失败**: BOS SDK 的 `list_all_objects` 在 S3 兼容端点（`s3.bcebos.*.com`）上调用时，服务端返回 XML 格式响应，而 BOS SDK 期望 JSON 格式，导致解析失败。`get_folder_size` 依赖 `list_objects`，因此连带失败。  
> <sup>3</sup> **依赖上传**: 由于上传失败（注 1），后续的下载和 `download_from_url` 操作因对象不存在而失败，非接口本身问题。

### 推荐配置

根据兼容性测试结果，推荐以下配置方案：

| 存储服务 | 推荐 provider | 说明 |
|:---|:---|:---|
| MinIO | `"minio"` 或 `"aws"` | 两者均 100% 兼容，`"minio"` 使用原生 SDK 更轻量 |
| 百度 BOS（官方地址） | `"bos"` | 使用 BOS SDK，所有功能均正常 |
| 百度 BOS（S3 兼容地址） | `"bos"` | BOS SDK 除 `list_objects` 外均正常；boto3 有 SHA256 校验问题 |
| AWS S3 | `"aws"` | 使用 boto3 原生支持 |

### 已知问题与补丁

#### BOS SDK `_change_user_endpoint` bug（bce-python-sdk==0.9.70）

BOS SDK 的 `_change_user_endpoint` 方法假设任何 4 段域名（如 `bcebos.sdhy.omspcloud.com`）
都是虚拟托管格式 `{bucket}.{region}.bcebos.com`，对比首段与 bucket 名不匹配时直接抛出 `ValueError`。
但实际上只有以 `bcebos.com` 结尾的域名才应做此校验。

**影响**：使用非标准 BOS 域名（私有化部署）时，所有需要 bucket 操作的 API 调用均会失败。

**修复**：`BosOssClient._patch_bos_client()` 在校验前增加 `is_bos_suffixed_host` 检查，
仅对真正的 BOS 域名执行虚拟托管校验。SDK 版本已固定为 `0.9.70`。

### 资源管理

`OssFile` 和底层 `OssClient` 均支持上下文管理器协议，可自动释放连接池资源。

#### 各客户端资源特点

| 客户端 | 持有资源 | close() 行为 |
|:---|:---|:---|
| `MinioOssClient` | urllib3 连接池（maxsize=10） | 清空连接池 `_http.clear()` |
| `BosOssClient` | 短连接（每次请求后自动关闭） | 空操作（无需释放） |
| `AwsOssClient` | urllib3 连接池（maxsize=10） | 调用 boto3 `client.close()` |

#### 最佳实践

```python
from shuguan.handler.file_util import OssFile, OssClientFactory, OssProvider

# ✅ 推荐：使用 with 语句自动释放资源
with OssFile("minio:9000", "ak", "sk", provider="minio") as oss:
    oss.upload_file("bucket", "key", "/local/file.txt")
    oss.download_file("bucket", "key", "/tmp/file.txt")
# 退出 with 块后连接池自动关闭

# ✅ 手动管理（适合长生命周期场景）
oss = OssFile("minio:9000", "ak", "sk", provider="minio")
try:
    oss.upload_file("bucket", "key", "/local/file.txt")
finally:
    oss.close()

# ✅ 工厂缓存清理（应用关闭时调用）
OssClientFactory.clear_cache()  # 关闭所有缓存实例的连接并清空缓存
```

> **说明**：对于长期运行的服务（如 Web 应用），可不主动调用 `close()`，让连接池保持复用。
> 在应用关闭时调用 `OssClientFactory.clear_cache()` 即可。

## 安装

```bash
pip install shuguan-handler
# 或开发环境
uv sync --all-extras
```

## 测试

```bash
# 单元测试
.venv/bin/python -m pytest tests/

# 集成测试（需要真实 OSS 服务，修改 test_integration_oss.py 中的连接配置）
.venv/bin/python tests/test_integration_oss.py
```
