fraclab-sdk 0.1.0__py3-none-any.whl → 0.1.1__py3-none-any.whl
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.
- README.md +71 -7
- fraclab_sdk/specs/__init__.py +22 -0
- fraclab_sdk/specs/output.py +33 -0
- fraclab_sdk/workbench/Home.py +162 -0
- fraclab_sdk/workbench/__init__.py +4 -0
- fraclab_sdk/workbench/__main__.py +48 -0
- fraclab_sdk/workbench/pages/1_Snapshots.py +546 -0
- fraclab_sdk/workbench/pages/2_Browse.py +513 -0
- fraclab_sdk/workbench/pages/3_Selection.py +464 -0
- fraclab_sdk/workbench/pages/4_Run.py +325 -0
- fraclab_sdk/workbench/pages/5_Results.py +292 -0
- fraclab_sdk/workbench/pages/6_Algorithm_Edit.py +116 -0
- fraclab_sdk/workbench/pages/7_Schema_Edit.py +149 -0
- fraclab_sdk/workbench/pages/8_Output_Edit.py +144 -0
- fraclab_sdk/workbench/pages/9_Export_Algorithm.py +238 -0
- fraclab_sdk/workbench/pages/__init__.py +1 -0
- fraclab_sdk/workbench/ui_styles.py +91 -0
- fraclab_sdk/workbench/utils.py +43 -0
- {fraclab_sdk-0.1.0.dist-info → fraclab_sdk-0.1.1.dist-info}/METADATA +75 -8
- {fraclab_sdk-0.1.0.dist-info → fraclab_sdk-0.1.1.dist-info}/RECORD +22 -5
- {fraclab_sdk-0.1.0.dist-info → fraclab_sdk-0.1.1.dist-info}/entry_points.txt +1 -0
- {fraclab_sdk-0.1.0.dist-info → fraclab_sdk-0.1.1.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""Shared UI styling utility for Streamlit pages."""
|
|
2
|
+
|
|
3
|
+
import streamlit as st
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def apply_global_styles():
|
|
7
|
+
"""Inject global CSS to hide Streamlit UI elements and apply common styling."""
|
|
8
|
+
st.markdown("""
|
|
9
|
+
<style>
|
|
10
|
+
/* =================================
|
|
11
|
+
1. Hide Streamlit UI Elements
|
|
12
|
+
================================= */
|
|
13
|
+
|
|
14
|
+
/* Hide top header bar */
|
|
15
|
+
header[data-testid="stHeader"] {
|
|
16
|
+
display: none !important;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/* Hide hamburger menu and Deploy button */
|
|
20
|
+
[data-testid="stToolbar"], .stDeployButton {
|
|
21
|
+
display: none !important;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* Hide footer (Made with Streamlit) */
|
|
25
|
+
footer {
|
|
26
|
+
display: none !important;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* Hide element toolbar on tables/dataframes */
|
|
30
|
+
[data-testid="stElementToolbar"] {
|
|
31
|
+
display: none !important;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Adjust main content padding (header hidden, content needs padding) */
|
|
35
|
+
.main .block-container {
|
|
36
|
+
padding-top: 2rem !important;
|
|
37
|
+
padding-bottom: 2rem !important;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* =================================
|
|
41
|
+
2. Button Styling
|
|
42
|
+
================================= */
|
|
43
|
+
|
|
44
|
+
div[data-testid="stButton"] button {
|
|
45
|
+
white-space: nowrap !important;
|
|
46
|
+
border-radius: 6px !important;
|
|
47
|
+
min-width: 60px !important;
|
|
48
|
+
font-weight: 500 !important;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* =================================
|
|
52
|
+
3. Anti-Copy Protection
|
|
53
|
+
================================= */
|
|
54
|
+
|
|
55
|
+
/* Disable text selection on key areas */
|
|
56
|
+
.element-container,
|
|
57
|
+
[data-testid="stDataFrame"],
|
|
58
|
+
[data-testid="stDataEditor"],
|
|
59
|
+
[data-testid="stCode"],
|
|
60
|
+
[data-testid="stJson"] {
|
|
61
|
+
user-select: none;
|
|
62
|
+
-webkit-user-select: none;
|
|
63
|
+
-moz-user-select: none;
|
|
64
|
+
-ms-user-select: none;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* Hide copy buttons on st.code / st.json */
|
|
68
|
+
[data-testid="stCode"] button,
|
|
69
|
+
[data-testid="stJson"] button {
|
|
70
|
+
display: none !important;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* =================================
|
|
74
|
+
4. Component Styling
|
|
75
|
+
================================= */
|
|
76
|
+
|
|
77
|
+
/* Expander header styling */
|
|
78
|
+
.streamlit-expanderHeader {
|
|
79
|
+
font-weight: 600;
|
|
80
|
+
background-color: #f9f9fb;
|
|
81
|
+
border-radius: 6px;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Data Editor border styling */
|
|
85
|
+
[data-testid="stDataEditor"] {
|
|
86
|
+
border: 1px solid #e6e9ef;
|
|
87
|
+
border-radius: 6px;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
</style>
|
|
91
|
+
""", unsafe_allow_html=True)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Shared helpers for the Streamlit workbench."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from fraclab_sdk.config import SDKConfig
|
|
11
|
+
|
|
12
|
+
# Keep a dedicated workspace separate from the installed algorithm library.
|
|
13
|
+
WORKSPACE_ALGOS_SUBDIR = "workspace_algorithms"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def get_workspace_dir(config: SDKConfig) -> Path:
|
|
17
|
+
"""Return the workspace directory for editable algorithms."""
|
|
18
|
+
workspace = config.sdk_home / WORKSPACE_ALGOS_SUBDIR
|
|
19
|
+
workspace.mkdir(parents=True, exist_ok=True)
|
|
20
|
+
return workspace
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def run_workspace_script(workspace: Path, script: str, timeout: int = 30) -> subprocess.CompletedProcess:
|
|
24
|
+
"""Run a Python snippet with the workspace on PYTHONPATH."""
|
|
25
|
+
pythonpath = [str(workspace)]
|
|
26
|
+
existing = os.environ.get("PYTHONPATH")
|
|
27
|
+
if existing:
|
|
28
|
+
pythonpath.append(existing)
|
|
29
|
+
|
|
30
|
+
env = {
|
|
31
|
+
**os.environ,
|
|
32
|
+
"PYTHONPATH": os.pathsep.join(pythonpath),
|
|
33
|
+
"PYTHONUNBUFFERED": "1",
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return subprocess.run(
|
|
37
|
+
[sys.executable, "-c", script],
|
|
38
|
+
cwd=workspace,
|
|
39
|
+
env=env,
|
|
40
|
+
capture_output=True,
|
|
41
|
+
text=True,
|
|
42
|
+
timeout=timeout,
|
|
43
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fraclab-sdk
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: SDK for managing snapshots, algorithms, and run execution
|
|
5
5
|
Requires-Python: >=3.11,<4.0
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -8,19 +8,22 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
8
8
|
Classifier: Programming Language :: Python :: 3.12
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.13
|
|
10
10
|
Classifier: Programming Language :: Python :: 3.14
|
|
11
|
+
Provides-Extra: workbench
|
|
11
12
|
Requires-Dist: fastapi (>=0.115.0,<0.116.0)
|
|
12
13
|
Requires-Dist: matplotlib (>=3.9.2,<4.0.0)
|
|
13
14
|
Requires-Dist: numpy (>=2.1.1,<3.0.0)
|
|
14
15
|
Requires-Dist: pandas (>=2.2.3,<3.0.0)
|
|
16
|
+
Requires-Dist: pyarrow (>=16.0.0) ; extra == "workbench"
|
|
15
17
|
Requires-Dist: pydantic (>=2.10.0,<3.0.0)
|
|
16
18
|
Requires-Dist: rich (>=13.9.0,<14.0.0)
|
|
17
19
|
Requires-Dist: scipy (>=1.13.1,<2.0.0)
|
|
20
|
+
Requires-Dist: streamlit (>=1.30) ; extra == "workbench"
|
|
18
21
|
Requires-Dist: typer (>=0.15.0,<0.16.0)
|
|
19
22
|
Description-Content-Type: text/markdown
|
|
20
23
|
|
|
21
24
|
# Fraclab SDK Reference
|
|
22
25
|
|
|
23
|
-
> 版本: 0.1.
|
|
26
|
+
> 版本: 0.1.1
|
|
24
27
|
> Python: >=3.11
|
|
25
28
|
|
|
26
29
|
Fraclab SDK 是一个算法开发与执行框架,帮助算法开发者快速构建、测试和部署数据处理算法。
|
|
@@ -43,12 +46,26 @@ Fraclab SDK 是一个算法开发与执行框架,帮助算法开发者快速
|
|
|
43
46
|
|
|
44
47
|
## 安装
|
|
45
48
|
|
|
46
|
-
|
|
49
|
+
轻量安装(核心 SDK / CLI,自动带上科学计算依赖):
|
|
47
50
|
|
|
48
51
|
```bash
|
|
49
|
-
pip install
|
|
52
|
+
pip install fraclab-sdk
|
|
50
53
|
```
|
|
51
54
|
|
|
55
|
+
安装并启用 Workbench UI:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install "fraclab-sdk[workbench]"
|
|
59
|
+
fraclab-workbench # CLI entry point
|
|
60
|
+
# 或
|
|
61
|
+
python -m fraclab_sdk.workbench
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 依赖说明
|
|
65
|
+
|
|
66
|
+
- 核心安装会自动安装并锁定:`numpy>=2.1.1`, `pandas>=2.2.3`, `scipy>=1.13.1`, `matplotlib>=3.9.2`, `fastapi>=0.115.0`, `rich>=13.9.0`。无需手动再装,避免版本冲突。
|
|
67
|
+
- 可选 `workbench` 额外安装 UI 依赖:`streamlit>=1.30`, `pyarrow>=16.0.0`(`pandas` 已在核心里)。
|
|
68
|
+
|
|
52
69
|
---
|
|
53
70
|
|
|
54
71
|
## 快速开始:编写你的第一个算法
|
|
@@ -66,13 +83,63 @@ from fraclab_sdk.runtime import DataClient, ArtifactWriter
|
|
|
66
83
|
|
|
67
84
|
### 2. 编写算法入口
|
|
68
85
|
|
|
69
|
-
创建 `main.py`
|
|
86
|
+
创建 `main.py` 作为算法入口文件。
|
|
87
|
+
|
|
88
|
+
#### 入口函数签名约定
|
|
89
|
+
|
|
90
|
+
**算法入口函数必须严格遵循以下签名:**
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
def run(ctx):
|
|
94
|
+
...
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
| 约定 | 要求 | 说明 |
|
|
98
|
+
|------|------|------|
|
|
99
|
+
| 文件名 | `main.py` | 必须是 `main.py`,不能是其他名称 |
|
|
100
|
+
| 函数名 | `run` | 必须是 `run`,区分大小写 |
|
|
101
|
+
| 参数 | 仅 `ctx` 一个参数 | SDK 使用 `module.run(ctx)` 调用,**不支持**其他签名 |
|
|
102
|
+
| 返回值 | 无要求 | 返回值会被忽略 |
|
|
103
|
+
|
|
104
|
+
> **警告**: 以下写法都会导致运行失败:
|
|
105
|
+
> ```python
|
|
106
|
+
> # ❌ 错误: 参数名不影响,但参数个数必须是 1
|
|
107
|
+
> def run(ctx, extra_arg): # TypeError: run() missing required argument
|
|
108
|
+
>
|
|
109
|
+
> # ❌ 错误: 函数名错误
|
|
110
|
+
> def execute(ctx): # AttributeError: module has no attribute 'run'
|
|
111
|
+
>
|
|
112
|
+
> # ❌ 错误: 放在其他文件
|
|
113
|
+
> # algorithm.py 中定义 run() # 不会被加载
|
|
114
|
+
> ```
|
|
115
|
+
|
|
116
|
+
#### 最小可运行模板
|
|
70
117
|
|
|
71
118
|
```python
|
|
72
119
|
# main.py
|
|
73
|
-
|
|
74
|
-
|
|
120
|
+
def run(ctx):
|
|
121
|
+
"""算法入口函数 - 最小模板。
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
ctx: RunContext,包含:
|
|
125
|
+
- ctx.data_client: DataClient 实例
|
|
126
|
+
- ctx.params: dict[str, Any],用户参数
|
|
127
|
+
- ctx.artifacts: ArtifactWriter 实例
|
|
128
|
+
- ctx.logger: logging.Logger 实例
|
|
129
|
+
- ctx.run_context: dict,运行上下文
|
|
130
|
+
"""
|
|
131
|
+
logger = ctx.logger
|
|
132
|
+
logger.info("算法开始执行")
|
|
133
|
+
|
|
134
|
+
# 你的逻辑...
|
|
135
|
+
|
|
136
|
+
logger.info("算法执行完成")
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
#### 完整示例
|
|
75
140
|
|
|
141
|
+
```python
|
|
142
|
+
# main.py
|
|
76
143
|
def run(ctx):
|
|
77
144
|
"""算法入口函数。
|
|
78
145
|
|
|
@@ -333,7 +400,7 @@ aw.write_scalar(
|
|
|
333
400
|
"drsPath": "dist/drs.json"
|
|
334
401
|
},
|
|
335
402
|
"requires": {
|
|
336
|
-
"sdk": "0.1.
|
|
403
|
+
"sdk": "0.1.1",
|
|
337
404
|
"core": "1.0.0"
|
|
338
405
|
},
|
|
339
406
|
"repository": "https://github.com/example/my-algorithm",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
README.md,sha256=
|
|
1
|
+
README.md,sha256=XK2y0q8psA07V2QQHVSFLN4jpZVq5dLHgViwNYck_8M,44415
|
|
2
2
|
fraclab_sdk/__init__.py,sha256=6SycB79WDBLT3QwAWVEMVHMOz_vETyo3ZZ0IbAsmTPE,924
|
|
3
3
|
fraclab_sdk/algorithm/__init__.py,sha256=-tAQkdAWWh_MlQMszsz0XAUR9aJ8oOxu8gUsUTmLyHA,220
|
|
4
4
|
fraclab_sdk/algorithm/export.py,sha256=axOWsDUF6K5Ru2eIb0hcjk8t4md4u-gnZGjK3JaRoGo,39
|
|
@@ -39,9 +39,26 @@ fraclab_sdk/snapshot/__init__.py,sha256=RPp-tt85xnecO4tkXLl1BClcjxVKvmAnhlpyomRz
|
|
|
39
39
|
fraclab_sdk/snapshot/index.py,sha256=8hsRm6QB1taDhUk6cLqkrxQWzwj6E05I0YLB5S0H3Ms,2942
|
|
40
40
|
fraclab_sdk/snapshot/library.py,sha256=3rq2s7nirI5blOzfGet1rtuk-f18qOq5MuAsUP2ruZw,7000
|
|
41
41
|
fraclab_sdk/snapshot/loader.py,sha256=ni9gdFQjAcIavdA9AoMMMtEJeEypOzK0dEbvygaaAh4,7578
|
|
42
|
+
fraclab_sdk/specs/__init__.py,sha256=aOQ8FBSgRLmJGDYZFMOKqhWu0O1YllQcIZfC_gK-Oqs,452
|
|
42
43
|
fraclab_sdk/specs/manifest.py,sha256=D3CyMt07p_uBI5Dw0NFfzUhzS2JZafaGxuxXFZ8J938,2597
|
|
44
|
+
fraclab_sdk/specs/output.py,sha256=Tg1eT6f31TaeKj8pZUABzXJeO55H5ieWAldw93iyRiY,729
|
|
43
45
|
fraclab_sdk/utils/io.py,sha256=L4EoReyx13wQqj0qaloMcNGSuEanZDHEk5A8rI-OCJQ,786
|
|
44
|
-
fraclab_sdk
|
|
45
|
-
fraclab_sdk
|
|
46
|
-
fraclab_sdk
|
|
47
|
-
fraclab_sdk
|
|
46
|
+
fraclab_sdk/workbench/Home.py,sha256=RhSNLH3t3m6LYIrBaryrsME8z5m4BrGDCTdYA352ig8,4487
|
|
47
|
+
fraclab_sdk/workbench/__init__.py,sha256=eZnXHbvRbv6unD1BZ4T7SmyYMF1UKd-Nt6t11QuYSvM,204
|
|
48
|
+
fraclab_sdk/workbench/__main__.py,sha256=Pkh79m5GnE20HlY72c4-7nshpy39jqkkbEIJ5k1lL1g,1333
|
|
49
|
+
fraclab_sdk/workbench/pages/1_Snapshots.py,sha256=522dIziu8-ZuSqI8y_ikeeAYukU0cPV5DcOVZM_awo8,21075
|
|
50
|
+
fraclab_sdk/workbench/pages/2_Browse.py,sha256=yqS0AfBVF4FXtb17elQ9oxU6fTuzl5XLk8c5f8xIW8c,17283
|
|
51
|
+
fraclab_sdk/workbench/pages/3_Selection.py,sha256=q2o_OF5AWa-tZFmJ2XAlVHcAWYKJAIYKncM9Egi8Wog,18319
|
|
52
|
+
fraclab_sdk/workbench/pages/4_Run.py,sha256=BIdzJ7ulWvD84XrIh_7xQ4O1nSuKDfARlAQ4AKJnFFc,12705
|
|
53
|
+
fraclab_sdk/workbench/pages/5_Results.py,sha256=7ZHID3LUDX7eRW38he0jzcF3rlJNy9CFRDwFgMuwuK8,11305
|
|
54
|
+
fraclab_sdk/workbench/pages/6_Algorithm_Edit.py,sha256=nkTv2rQgLQoiXB-RoS8RgUksv0CFhL0hmF0hvH2akNI,4113
|
|
55
|
+
fraclab_sdk/workbench/pages/7_Schema_Edit.py,sha256=PA_5FaPdGdVdO6n3MONCU9_6k3oYMK4DNZUhA0_IKhs,5019
|
|
56
|
+
fraclab_sdk/workbench/pages/8_Output_Edit.py,sha256=CcdBCdK-6YNE1P8cud0mx2zXcYlLAuRwbnv7n-7GLSs,5080
|
|
57
|
+
fraclab_sdk/workbench/pages/9_Export_Algorithm.py,sha256=3YaHc5K4zvxR0K-JS8sk_q59cbK-I6i9F1CdEKZBcpQ,8561
|
|
58
|
+
fraclab_sdk/workbench/pages/__init__.py,sha256=Et0iV4dhbgkeKKuhmffpYzhDjvWM7IheHh3feDQ4J2M,54
|
|
59
|
+
fraclab_sdk/workbench/ui_styles.py,sha256=o06r6Cv1VV8ita2-tmcGYxbdL6-JkPSY2K3AvnSYhuw,2656
|
|
60
|
+
fraclab_sdk/workbench/utils.py,sha256=0rcKo8_zIYHQ2kwuEjAf15ara6okpJViFPyW2F_SPx4,1179
|
|
61
|
+
fraclab_sdk-0.1.1.dist-info/METADATA,sha256=EsM2mrdD3yBelfuq1SmdMNkCJg0f1jRJkwFiVg5P_fw,45324
|
|
62
|
+
fraclab_sdk-0.1.1.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
63
|
+
fraclab_sdk-0.1.1.dist-info/entry_points.txt,sha256=R6jqSgmf7jB4xMgsTe0M-X9j6JtQQfaedku4Dppmwww,158
|
|
64
|
+
fraclab_sdk-0.1.1.dist-info/RECORD,,
|
|
File without changes
|