sisyphus-api-engine 2.2.0__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.
- sisyphus_api_engine-2.2.0/.cursor/commands/sisyphus-api-engine.md +54 -0
- sisyphus_api_engine-2.2.0/.gitignore +44 -0
- sisyphus_api_engine-2.2.0/.pre-commit-config.yaml +18 -0
- sisyphus_api_engine-2.2.0/.sisyphus/config.yaml +17 -0
- sisyphus_api_engine-2.2.0/.vscode/settings.json +11 -0
- sisyphus_api_engine-2.2.0/CHANGELOG.md +30 -0
- sisyphus_api_engine-2.2.0/CLAUDE.md +189 -0
- sisyphus_api_engine-2.2.0/LICENSE +22 -0
- sisyphus_api_engine-2.2.0/MANIFEST.in +9 -0
- sisyphus_api_engine-2.2.0/PKG-INFO +323 -0
- sisyphus_api_engine-2.2.0/README.md +298 -0
- sisyphus_api_engine-2.2.0/apirun/__init__.py +7 -0
- sisyphus_api_engine-2.2.0/apirun/cli.py +128 -0
- sisyphus_api_engine-2.2.0/apirun/core/__init__.py +1 -0
- sisyphus_api_engine-2.2.0/apirun/core/models.py +161 -0
- sisyphus_api_engine-2.2.0/apirun/core/runner.py +166 -0
- sisyphus_api_engine-2.2.0/apirun/data_driven/__init__.py +1 -0
- sisyphus_api_engine-2.2.0/apirun/executor/__init__.py +5 -0
- sisyphus_api_engine-2.2.0/apirun/executor/request.py +103 -0
- sisyphus_api_engine-2.2.0/apirun/extractor/__init__.py +1 -0
- sisyphus_api_engine-2.2.0/apirun/keyword.py +24 -0
- sisyphus_api_engine-2.2.0/apirun/parser/__init__.py +1 -0
- sisyphus_api_engine-2.2.0/apirun/result/__init__.py +1 -0
- sisyphus_api_engine-2.2.0/apirun/utils/__init__.py +1 -0
- sisyphus_api_engine-2.2.0/apirun/utils/functions.py +57 -0
- sisyphus_api_engine-2.2.0/apirun/utils/variables.py +122 -0
- sisyphus_api_engine-2.2.0/apirun/validation/__init__.py +1 -0
- sisyphus_api_engine-2.2.0/apirun/websocket/__init__.py +1 -0
- sisyphus_api_engine-2.2.0/docs/Sisyphus-api-engine JSON /350/276/223/345/207/272/350/247/204/350/214/203.md" +973 -0
- sisyphus_api_engine-2.2.0/docs/Sisyphus-api-engine YAML /350/276/223/345/205/245/350/247/204/350/214/203.md" +763 -0
- sisyphus_api_engine-2.2.0/docs/Sisyphus-api-engine/351/234/200/346/261/202/346/226/207/346/241/243.md +714 -0
- sisyphus_api_engine-2.2.0/docs//345/274/200/345/217/221/344/273/273/345/212/241/346/270/205/345/215/225.md +528 -0
- sisyphus_api_engine-2.2.0/pypi_publish.sh +208 -0
- sisyphus_api_engine-2.2.0/pyproject.toml +68 -0
- sisyphus_api_engine-2.2.0/tests/unit/__init__.py +0 -0
- sisyphus_api_engine-2.2.0/tests/unit/conftest.py +1 -0
- sisyphus_api_engine-2.2.0/tests/unit/test_models.py +218 -0
- sisyphus_api_engine-2.2.0/tests/unit/test_request_executor.py +51 -0
- sisyphus_api_engine-2.2.0/tests/unit/test_runner.py +100 -0
- sisyphus_api_engine-2.2.0/tests/unit/test_variables.py +88 -0
- sisyphus_api_engine-2.2.0/tests/unit/test_yaml_cases.py +25 -0
- sisyphus_api_engine-2.2.0/tests/yaml/full_step_types.yaml +57 -0
- sisyphus_api_engine-2.2.0/uv.lock +752 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Sisyphus-api-engine 开发执行准则
|
|
2
|
+
|
|
3
|
+
你现在是一名专注于自动化测试引擎的核心开发工程师。请严格遵循以下工作流与质量控制协议进行 Sisyphus-api-engine 的任务开发:
|
|
4
|
+
|
|
5
|
+
## 1. 核心参考上下文
|
|
6
|
+
|
|
7
|
+
在执行任何代码编写前,必须深度对齐以下文档:
|
|
8
|
+
|
|
9
|
+
- **进度依据**:`docs/开发任务清单.md`(明确当前待办项与优先级)。
|
|
10
|
+
- **业务逻辑**:`docs/Sisyphus-X需求文档.md`(确保功能符合全局设计)。
|
|
11
|
+
- **协议规范**:`docs/Sisyphus-api-engine JSON 输出规范.md` 与 `YAML 输入规范.md`。
|
|
12
|
+
|
|
13
|
+
## 2. 闭环开发与原子化验证
|
|
14
|
+
|
|
15
|
+
每完成一个子功能或 Bug 修复,必须立即执行以下闭环流程,严禁“带病”推进:
|
|
16
|
+
|
|
17
|
+
1. **同步测试补全**:
|
|
18
|
+
|
|
19
|
+
- 单元测试用例:编写脚本并存放在 `tests/unit/`。
|
|
20
|
+
- YAML测试用例:编写集成测试并存放在 `tests/yaml/`。
|
|
21
|
+
- 严禁使用占位符或无效 Mock 数据
|
|
22
|
+
|
|
23
|
+
2. **执行全量验证**:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# 运行全量单元测试
|
|
27
|
+
sisyphus-api-engine --cases tests/unit/
|
|
28
|
+
# 运行全量 YAML 业务案例
|
|
29
|
+
sisyphus-api-engine --cases tests/yaml/
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
3. **准入原则**:只有当上述测试结果均为 **100% Pass** 时,方可进入提交环节。
|
|
34
|
+
|
|
35
|
+
## 3. GitHub 原子化提交规范
|
|
36
|
+
|
|
37
|
+
在任务完成且测试通过后,必须进行规范化的代码提交:
|
|
38
|
+
|
|
39
|
+
- **提交原则**:坚持**原子化提交**(每次提交仅包含一个逻辑改动或一个任务清单项)。
|
|
40
|
+
- **Commit 信息格式**:`<emoji> <type>(<scope>): <subject>`
|
|
41
|
+
- **常用类型参考**:
|
|
42
|
+
- ✨ `:sparkles: feat`: 实现新功能(对应任务清单中的新项)
|
|
43
|
+
- 🐛 `:bug: fix`: 修复 Bug
|
|
44
|
+
- 📝 `:memo: docs`: 文档更新
|
|
45
|
+
- ♻️ `:recycle: refactor`: 代码重构
|
|
46
|
+
- ✅ `:white_check_mark: test`: 增加或修改测试用例
|
|
47
|
+
- ⚡️ `:zap: perf`: 性能优化
|
|
48
|
+
|
|
49
|
+
- **示例**:`✨ feat(engine): 实现 YAML 动态变量解析功能`
|
|
50
|
+
|
|
51
|
+
## 4. 任务状态闭环
|
|
52
|
+
|
|
53
|
+
- **更新进度**:提交代码后,同步更新 `docs/开发任务清单.md` 中的任务状态。
|
|
54
|
+
- **禁止越级**:严禁在当前任务未完成提交前启动清单中的下一个任务。
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*.pyo
|
|
4
|
+
*.pyd
|
|
5
|
+
|
|
6
|
+
# 虚拟环境
|
|
7
|
+
.venv/
|
|
8
|
+
venv/
|
|
9
|
+
env/
|
|
10
|
+
|
|
11
|
+
# 编辑器 / IDE
|
|
12
|
+
# .vscode/
|
|
13
|
+
.idea/
|
|
14
|
+
*.code-workspace
|
|
15
|
+
|
|
16
|
+
# macOS
|
|
17
|
+
.DS_Store
|
|
18
|
+
|
|
19
|
+
# 构建产物
|
|
20
|
+
build/
|
|
21
|
+
dist/
|
|
22
|
+
*.egg-info/
|
|
23
|
+
|
|
24
|
+
# 测试 / 覆盖率
|
|
25
|
+
.pytest_cache/
|
|
26
|
+
.coverage
|
|
27
|
+
.coverage.*
|
|
28
|
+
htmlcov/
|
|
29
|
+
|
|
30
|
+
# Ruff / Pyright / 其他缓存
|
|
31
|
+
.ruff_cache/
|
|
32
|
+
.pyright/
|
|
33
|
+
.mypy_cache/
|
|
34
|
+
.cache/
|
|
35
|
+
|
|
36
|
+
# 日志
|
|
37
|
+
logs/
|
|
38
|
+
*.log
|
|
39
|
+
|
|
40
|
+
# 本地临时文件
|
|
41
|
+
*.swp
|
|
42
|
+
*.swo
|
|
43
|
+
*~
|
|
44
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
|
+
rev: v0.9.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: ruff
|
|
6
|
+
- id: ruff-format
|
|
7
|
+
|
|
8
|
+
- repo: https://github.com/microsoft/pyright
|
|
9
|
+
rev: v1.1.390
|
|
10
|
+
hooks:
|
|
11
|
+
- id: pyright
|
|
12
|
+
|
|
13
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
14
|
+
rev: v5.0.0
|
|
15
|
+
hooks:
|
|
16
|
+
- id: end-of-file-fixer
|
|
17
|
+
- id: trailing-whitespace
|
|
18
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
profiles:
|
|
2
|
+
dev:
|
|
3
|
+
base_url: "http://dev.example.com"
|
|
4
|
+
variables:
|
|
5
|
+
api_key: "dev-key-please-change"
|
|
6
|
+
|
|
7
|
+
prod:
|
|
8
|
+
base_url: "https://api.example.com"
|
|
9
|
+
variables:
|
|
10
|
+
api_key: "prod-key-please-change"
|
|
11
|
+
|
|
12
|
+
active_profile: "dev"
|
|
13
|
+
|
|
14
|
+
variables:
|
|
15
|
+
common_headers:
|
|
16
|
+
User-Agent: "sisyphus-api-engine/2.2.0"
|
|
17
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [2.2.0] - 2026-02-26
|
|
4
|
+
|
|
5
|
+
### 变更
|
|
6
|
+
|
|
7
|
+
- 发布:将核心执行器重构线作为 PyPI 新版本 `2.2.0` 发布,对应当前仓库代码。
|
|
8
|
+
- 文档:更新 README 中的版本说明与发布策略,标记 2.2.0 为最新稳定版,并保留历史 2.1.0 信息。
|
|
9
|
+
- 版本管理:`pyproject.toml` 中版本号由 `0.2.0` 升级为 `2.2.0`,用于对齐现有 PyPI 版本序列。
|
|
10
|
+
|
|
11
|
+
## [0.2.0] - 2026-02-26
|
|
12
|
+
|
|
13
|
+
### 变更
|
|
14
|
+
|
|
15
|
+
- 文档:根据《sisyphus-api-engine 需求规格说明书》与《开发任务清单》重写 `README.md`,明确技术栈(Python 3.12 + uv + Ruff + Pyright)与当前功能边界。
|
|
16
|
+
- 基础设施:补充 `.gitignore`、`.sisyphus/config.yaml`、`LICENSE`、`MANIFEST.in`、`.pre-commit-config.yaml` 等项目必需文件。
|
|
17
|
+
- 工具链:更新 `pyproject.toml` 中的 Python 版本约束与开发依赖,统一使用 uv + Ruff + Pyright 的现代化开发流程。
|
|
18
|
+
- 版本管理:将内部版本号从 `0.1.0` 提升到 `0.2.0`,为后续核心能力与高级特性开发预留演进空间。
|
|
19
|
+
|
|
20
|
+
## [0.1.0] - 2026-02-26
|
|
21
|
+
|
|
22
|
+
### 新增
|
|
23
|
+
|
|
24
|
+
- 项目初始化,从 Sisyphus-X 主项目中独立
|
|
25
|
+
- 核心数据模型 (CaseModel, Config, StepDefinition)
|
|
26
|
+
- YAML 用例加载与校验
|
|
27
|
+
- HTTP 请求执行器
|
|
28
|
+
- CLI 入口 (`sisyphus` 命令)
|
|
29
|
+
- 支持 text / json / allure / html 输出格式
|
|
30
|
+
- 项目目录结构重组为 `apirun/` 包
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## 项目概述
|
|
6
|
+
|
|
7
|
+
sisyphus-api-engine 是 YAML 驱动的接口自动化测试引擎,为 Sisyphus-X 平台提供核心执行器能力。当前仓库是「轻量核心版」,聚焦核心链路:
|
|
8
|
+
|
|
9
|
+
**YAML → Pydantic 模型 → 场景运行器 → HTTP 请求 → JSON 输出**
|
|
10
|
+
|
|
11
|
+
高级特性(数据库、数据驱动、断言引擎、WebSocket 推送等)按任务清单逐步实现。
|
|
12
|
+
|
|
13
|
+
## 常用命令
|
|
14
|
+
|
|
15
|
+
### 环境管理
|
|
16
|
+
```bash
|
|
17
|
+
# 创建虚拟环境(Python 3.12+)
|
|
18
|
+
uv venv -p 3.12 .venv
|
|
19
|
+
source .venv/bin/activate # macOS / Linux
|
|
20
|
+
|
|
21
|
+
# 安装依赖
|
|
22
|
+
uv sync
|
|
23
|
+
|
|
24
|
+
# 开发模式安装(含 dev 依赖)
|
|
25
|
+
uv pip install -e ".[dev]"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### 代码质量检查
|
|
29
|
+
```bash
|
|
30
|
+
# 代码格式化(Ruff)
|
|
31
|
+
uv run ruff format .
|
|
32
|
+
|
|
33
|
+
# 静态检查(Ruff)
|
|
34
|
+
uv run ruff check .
|
|
35
|
+
|
|
36
|
+
# 类型检查(Pyright)
|
|
37
|
+
uv run pyright
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 测试执行
|
|
41
|
+
```bash
|
|
42
|
+
# 运行所有单元测试
|
|
43
|
+
uv run python -m pytest tests/unit -v
|
|
44
|
+
|
|
45
|
+
# 运行单个 YAML 用例并输出 JSON
|
|
46
|
+
sisyphus --case tests/yaml/simple_get.yaml -O json
|
|
47
|
+
|
|
48
|
+
# 批量执行目录下所有 YAML 用例
|
|
49
|
+
sisyphus --cases tests/yaml/ -O json
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Pre-commit 钩子
|
|
53
|
+
```bash
|
|
54
|
+
# 安装 pre-commit 钩子(推荐)
|
|
55
|
+
pre-commit install
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## 核心架构
|
|
59
|
+
|
|
60
|
+
### 数据流
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
YAML 用例
|
|
64
|
+
↓
|
|
65
|
+
load_case() → Pydantic 模型校验
|
|
66
|
+
↓
|
|
67
|
+
run_case() → 场景运行器
|
|
68
|
+
↓
|
|
69
|
+
execute_request_step() → HTTP 请求执行
|
|
70
|
+
↓
|
|
71
|
+
JSON 输出(符合内部规范)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 关键模块
|
|
75
|
+
|
|
76
|
+
| 模块 | 文件 | 职责 |
|
|
77
|
+
|------|------|------|
|
|
78
|
+
| **数据模型** | `apirun/core/models.py` | 所有 YAML 结构的 Pydantic 模型定义 |
|
|
79
|
+
| **场景运行器** | `apirun/core/runner.py` | `load_case()` 加载 YAML,`run_case()` 执行用例 |
|
|
80
|
+
| **请求执行器** | `apirun/executor/request.py` | HTTP 请求发送与响应处理 |
|
|
81
|
+
| **变量渲染** | `apirun/utils/variables.py` | `{{var}}` / `{{func()}}` 模板递归渲染 |
|
|
82
|
+
| **内置函数** | `apirun/utils/functions.py` | `random()`, `timestamp()` 等模板函数 |
|
|
83
|
+
| **CLI 入口** | `apirun/cli.py` | `sisyphus` 命令实现 |
|
|
84
|
+
|
|
85
|
+
### 变量系统
|
|
86
|
+
|
|
87
|
+
**渲染规则**(`apirun/utils/variables.py`):
|
|
88
|
+
- `{{var_name}}` → 从 `variables` 字典读取
|
|
89
|
+
- `{{func_name(arg1, arg2)}}` → 调用内置函数(见 `BUILTIN_FUNCTIONS`)
|
|
90
|
+
- 支持递归渲染 dict / list / str 结构
|
|
91
|
+
|
|
92
|
+
**变量优先级**:
|
|
93
|
+
1. `config.variables`(场景级)
|
|
94
|
+
2. `config.environment.variables`(环境级,覆盖场景级)
|
|
95
|
+
|
|
96
|
+
### 关键类型设计
|
|
97
|
+
|
|
98
|
+
**`StepDefinition.keyword_type`** 决定步骤类型:
|
|
99
|
+
- `request` → HTTP 请求(当前已实现)
|
|
100
|
+
- `assertion` → 独立断言步骤(预留)
|
|
101
|
+
- `extract` → 变量提取步骤(预留)
|
|
102
|
+
- `db` → 数据库操作(预留)
|
|
103
|
+
- `custom` → 自定义关键字(预留)
|
|
104
|
+
|
|
105
|
+
**YAML 模型字段别名**:
|
|
106
|
+
- `RequestStepParams.json` 使用 `alias="json"`(避免与 Python 内置冲突)
|
|
107
|
+
|
|
108
|
+
## 开发约定
|
|
109
|
+
|
|
110
|
+
### 代码风格
|
|
111
|
+
- **Python 版本**: 3.12+
|
|
112
|
+
- **代码风格**: Google Python Style(Ruff 配置)
|
|
113
|
+
- **注释语言**: 统一使用中文,解释「意图」而非「语法」
|
|
114
|
+
- **类型注解**: 尽量补全,保持 Pyright 通过
|
|
115
|
+
- **行长度**: 100 字符(`ruff.line-length = 100`)
|
|
116
|
+
|
|
117
|
+
### 测试要求
|
|
118
|
+
- 单元测试位于 `tests/unit/`
|
|
119
|
+
- YAML 集成用例位于 `tests/yaml/`
|
|
120
|
+
- 新增/修改功能时需同步补充测试
|
|
121
|
+
|
|
122
|
+
### 提交规范
|
|
123
|
+
建议使用前缀:
|
|
124
|
+
- `feat:` - 新功能
|
|
125
|
+
- `fix:` - Bug 修复
|
|
126
|
+
- `refactor:` - 重构
|
|
127
|
+
- `docs:` - 文档更新
|
|
128
|
+
- `test:` - 测试相关
|
|
129
|
+
- `chore:` - 构建/工具链
|
|
130
|
+
|
|
131
|
+
## 配置文件
|
|
132
|
+
|
|
133
|
+
### `.sisyphus/config.yaml`
|
|
134
|
+
统一环境配置:
|
|
135
|
+
```yaml
|
|
136
|
+
profiles:
|
|
137
|
+
dev:
|
|
138
|
+
base_url: "http://dev.example.com"
|
|
139
|
+
variables:
|
|
140
|
+
api_key: "dev-key"
|
|
141
|
+
prod:
|
|
142
|
+
base_url: "https://api.example.com"
|
|
143
|
+
variables:
|
|
144
|
+
api_key: "prod-key"
|
|
145
|
+
|
|
146
|
+
active_profile: "dev"
|
|
147
|
+
|
|
148
|
+
variables:
|
|
149
|
+
common_headers:
|
|
150
|
+
User-Agent: "sisyphus-api-engine/0.2.0"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### CLI 输出格式
|
|
154
|
+
- `-O text`(默认):人类可读文本输出
|
|
155
|
+
- `-O json`:机器可读 JSON(符合 `docs/Sisyphus-api-engine JSON 输出规范.md`)
|
|
156
|
+
- `-O allure` / `-O html`:预留
|
|
157
|
+
|
|
158
|
+
## 版本说明
|
|
159
|
+
|
|
160
|
+
- **当前版本**: `0.2.0`(核心执行器重构线)
|
|
161
|
+
- **PyPI 已发布版本**: `2.1.0`(完整引擎,与当前仓库解耦)
|
|
162
|
+
- **版本变更记录**: 见 `CHANGELOG.md`
|
|
163
|
+
|
|
164
|
+
## 扩展点
|
|
165
|
+
|
|
166
|
+
### 添加新的内置函数
|
|
167
|
+
在 `apirun/utils/functions.py` 中:
|
|
168
|
+
1. 实现函数(签名参考现有函数)
|
|
169
|
+
2. 注册到 `BUILTIN_FUNCTIONS` 字典
|
|
170
|
+
|
|
171
|
+
### 自定义关键字
|
|
172
|
+
继承 `apirun/keyword.Keyword` 基类:
|
|
173
|
+
```python
|
|
174
|
+
from apirun.keyword import Keyword
|
|
175
|
+
|
|
176
|
+
class MyKeyword(Keyword):
|
|
177
|
+
name = "my_keyword"
|
|
178
|
+
|
|
179
|
+
def execute(self, **kwargs):
|
|
180
|
+
# 实现逻辑
|
|
181
|
+
return result
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## 重要文档
|
|
185
|
+
|
|
186
|
+
- 需求规格说明:`docs/Sisyphus-api-engine需求文档.md`
|
|
187
|
+
- YAML 输入规范:`docs/Sisyphus-api-engine YAML 输入规范.md`
|
|
188
|
+
- JSON 输出规范:`docs/Sisyphus-api-engine JSON 输出规范.md`
|
|
189
|
+
- 开发任务清单:`docs/开发任务清单.md`
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 koco-co
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|