# polarion-rest-api-python **Repository Path**: yyt1998/polarion-rest-api-python ## Basic Information - **Project Name**: polarion-rest-api-python - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-18 - **Last Updated**: 2026-09-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Polarion REST API Python 客户端 > 第一次使用请先看 [`API_REFERENCE.md`](API_REFERENCE.md):其中说明客户端构造、 > CRUD、API 分类和命令行参数。Polarion 2606 全部 284 个操作的逐方法输入/输出见 > [`POLARION_2606_API_REFERENCE.md`](POLARION_2606_API_REFERENCE.md)。 这是一个面向 Siemens Polarion REST API 的同步 Python 客户端。它既能直接发送任意 HTTP method/path/body,也提供了 JSON:API 资源、关系、分页和 Work Item CRUD 的便捷 封装。自定义字段会原样透传,不依赖一套很快过时的固定模型。 > 当前状态:`0.3.0`。代码已包含离线单元测试;接入真实实例前,请以该实例自带的 > OpenAPI/Swagger 为最终依据。 ## 官方 API 结论 Polarion REST 根地址通常是: ```text https:///polarion/rest/v1 ``` API 使用 JSON:API 风格,但支持批量创建、更新和删除,因此并不完全等同于标准 JSON:API。外部程序最常用 PAT: ```http Authorization: Bearer Accept: application/json ``` REST API 默认可能未启用,管理员需设置 `com.siemens.polarion.rest.enabled=true`;Swagger UI 还需单独启用。权限同时受 REST 端点权限和对象级 Read/Create/Update/Delete 权限控制。 官方资料: - [REST API 介绍](https://developer.siemens.com/polarion/overview.html) - [启用 REST API](https://developer.siemens.com/polarion/enable-rest-api.html) - [地址与版本规则](https://developer.siemens.com/polarion/access-rest-api.html) - [认证](https://developer.siemens.com/polarion/authentication.html) - [授权与两层权限模型](https://developer.siemens.com/polarion/authorization.html) - [基础概念、字段、分页和查询](https://developer.siemens.com/polarion/basic-concepts.html) - [CRUD、关系和高级场景](https://developer.siemens.com/polarion/advanced-concepts.html) - [最新官方 OpenAPI](https://developer.siemens.com/polarion/rest-api-spec.html) 目标服务器自己的规范通常在: ```text https:///polarion/sdk/index.html#restapi ``` ## 安装 要求 Python 3.9+: ```powershell python -m venv .venv .venv\Scripts\Activate.ps1 python -m pip install -e ".[dev]" ``` 运行测试: ```powershell python -m pytest ``` ## 配置 推荐把凭据放在环境变量中,不要写进源码或提交到 Git: ```powershell $env:POLARION_URL = "https://polarion.example.com" $env:POLARION_TOKEN = "" ``` `POLARION_URL` 可以是服务器地址、以 `/polarion` 结尾的应用地址,或完整的 `/polarion/rest/v1` 地址。 可选变量: | 变量 | 用途 | |---|---| | `POLARION_API_VERSION` | 默认 `v1` | | `POLARION_TOKEN_TYPE` | `pat`、`jwt` 或 `tcss` | | `POLARION_USER_ID` | TCSSO 必填的用户 ID | | `POLARION_REST_TOKEN` | Polarion 页面内会话令牌;与 Bearer token 二选一 | | `POLARION_TIMEOUT` | 连接和读取阶段使用的超时秒数(环境构造器使用单值) | | `POLARION_VERIFY_SSL` | `true`/`false` 或 CA bundle 路径 | | `POLARION_ALLOW_HTTP` | 是否显式允许明文 HTTP,默认 `false` | | `POLARION_STRICT_PARTIAL` | 遇到成功响应中的 `meta.errors` 时是否抛错 | 也可以显式构造: ```python import os from polarion_rest_api import PolarionClient client = PolarionClient( "https://polarion.example.com/polarion/rest/v1", token=os.environ["POLARION_TOKEN"], timeout=(10, 60), # 连接、读取超时 verify=True, # 默认校验证书 ) ``` JWT 会额外发送 `X-Polarion-token-type: jwt`: ```python client = PolarionClient( "https://polarion.example.com", token=get_current_jwt, token_type="jwt", ) ``` `token` 可以是返回字符串的函数,便于短期 JWT 自动刷新。TCSSO 使用 `token_type="tcss", user_id="..."`。 ## Polarion 2606 完整 API `client.api` 直接对应 Siemens 公开的 Polarion 2606 API,覆盖 **39 个分类、156 条 路径、284 个 HTTP 操作**。这是唯一的分类接口入口;每个操作都有明确的 Python 签名、路径参数、query 参数、请求体类型和成功返回状态: ```python with PolarionClient.from_env() as client: projects = client.api.projects.get_projects( page_size=100, fields={"projects": "id,name"}, ) work_item = client.api.work_items.get_work_item( "MY_PROJECT", "WI-123", fields={"workitems": "id,title,status"}, ) # 可按 operationId、路径、摘要、分类和 HTTP 方法检索。 attachment_getters = client.api.search("attachment", method="GET") ``` 39 个分组属性为: ```text ai, collections, custom_fields, document_attachments, document_comments, document_parts, documents, enumerations, externally_linked_work_items, feature_selections, icons, jobs, license, linked_oslc_resources, linked_work_items, metadata, page_attachments, page_comments, pages, plans, project_templates, projects, revisions, roles, test_record_attachments, test_records, test_run_attachments, test_run_comments, test_runs, test_step_result_attachments, test_step_results, test_steps, user_groups, users, work_item_approvals, work_item_attachments, work_item_comments, work_item_work_records, work_items ``` 完整的方法表见 [`POLARION_2606_API_REFERENCE.md`](POLARION_2606_API_REFERENCE.md),纯 HTTP 路由表见 [`POLARION_REST_ENDPOINTS.md`](POLARION_REST_ENDPOINTS.md)。 方法名由 Siemens `operationId` 转为 snake_case。例如 `getWorkItem` 对应 `client.api.work_items.get_work_item()`。`client.work_items()` 高级 CRUD 封装和 `client.request()` 任意请求入口仍然保留,但不存在第二套分类 API。 ## Work Item 增删改查 ```python from polarion_rest_api import PolarionClient, Ref, RichText with PolarionClient.from_env() as client: work_items = client.work_items("MY_PROJECT") # 增:Polarion 创建集合资源时,客户端自动包装为 {"data": [...]}。 created_document = work_items.create( attributes={ "title": "Python 创建的任务", "type": "task", # 这是 Work Item 的业务类型 "description": RichText.plain("通过 REST API 创建"), }, relationships={ "assignee": [Ref("users", "alice")], }, ) created = created_document["data"][0] # 最稳妥的做法是复用服务端返回的不透明 id 和 links.self。 resource_id = created["id"] self_url = created["links"]["self"] # 查 item_document = client.get_resource( self_url, fields={"workitems": ["@basic", "title", "status", "severity"]}, include=["author"], ) # 改:单资源 PATCH 的 data 是对象,id 必须与 URL 所指资源一致。 client.update_resource( self_url, "workitems", resource_id, attributes={"title": "修改后的标题", "severity": "major"}, ) # 列表/过滤;迭代器会跟随服务端返回的 links.next,而不是自行猜页码。 for item in work_items.iter( query="type:task AND status:open", sort="~created", fields={"workitems": ["title", "status"]}, page_size=100, max_items=500, ): print(item["id"], item.get("attributes", {}).get("title")) # 删:Work Item 没有传统的单条 DELETE;必须向集合端点发送 data 数组。 client.delete_resources( work_items.path, [Ref("workitems", resource_id)], ) ``` 如果手上只有 URL 使用的本地 ID(例如 `WI-123`),集合包装会先读取一次以获得完整、 不透明的 JSON:API 资源 ID: ```python item = client.work_items("MY_PROJECT").item("WI-123") document = item.get() item.update(attributes={"title": "新标题"}) item.delete() # 自动采用 Work Item 的集合 DELETE ``` 若已经保存了服务端返回的完整 ID,可避免额外 GET: ```python item = client.work_items("MY_PROJECT").item( "WI-123", resource_id="MY_PROJECT/WI-123", ) item.update(attributes={"status": "open"}) ``` 注意:多值字段的 PATCH 是**整体替换**。给 assignee 增加一个用户时,应先读取旧列表, 再提交包含旧用户和新用户的完整列表,否则旧值会丢失。 ## 任意资源的通用 CRUD 不同资源开放的 HTTP 动词并不一致,所以通用集合要求显式声明删除模式: ```python projects = client.collection( "projects", "projects", delete_mode="item", # 也可为 collection / unsupported ) project = projects.item("MY_PROJECT", resource_id="MY_PROJECT") project.get(fields={"projects": "@all"}) project.update(attributes={"name": "New name"}) # project.delete() # 仅在确认目标实例 OpenAPI 支持时调用 ``` 底层方法保留完整控制权: ```python # 任意 GET document = client.request( "GET", "projects/MY_PROJECT/workitems", params={"query": "status:open", "fields[workitems]": "title,status"}, ) # 任意 action 或目标版本新增的端点 result = client.request( "POST", "projects/MY_PROJECT/workitems/WI-123/actions/someAction", json={"custom": "payload"}, ) # DELETE 带 JSON body(Polarion 的批量删除需要它) client.request( "DELETE", "projects/MY_PROJECT/workitems", json={"data": [{"type": "workitems", "id": "MY_PROJECT/WI-123"}]}, ) ``` ### 关系 ```python from polarion_rest_api import Ref resource_path = "projects/MY_PROJECT/workitems/WI-123" client.add_relationship( resource_path, "assignee", [Ref("users", "alice"), Ref("users", "bob")], ) client.replace_relationship(resource_path, "assignee", [Ref("users", "alice")]) client.replace_relationship(resource_path, "assignee", None) # 清空 ``` 具体关系端点是否支持 POST/PATCH/DELETE,仍应查目标服务器 OpenAPI。 ### 分页、字段和 include ```python pages = client.iter_pages( "projects/MY_PROJECT/workitems", query="type:requirement", sort=["created", "id"], fields={ "workitems": ["title", "status", "author"], "users": ["name"], }, include=["author"], page_size=50, max_pages=20, ) for page in pages: print(page.get("meta", {}).get("totalCount")) ``` 查询使用 Polarion 的 `query` 语法,不是标准 JSON:API 的 `filter[...]`。分页从 1 开始, 默认页大小和上限由服务器配置。大量使用 `@all` 或深层 include 会显著增加服务器负担。 ## 命令行 安装后可直接调用: ```powershell # 查 polarion-rest get projects/MY_PROJECT/workitems/WI-123 ` --fields "workitems=@basic,title,status" # 列表与过滤 polarion-rest list projects/MY_PROJECT/workitems ` --query "type:task AND status:open" ` --sort "~created" ` --fields "workitems=title,status" # 增 polarion-rest create projects/MY_PROJECT/workitems ` --type workitems ` --attributes '{"title":"CLI task","type":"task"}' # 改;--id 是完整 JSON:API 资源 ID polarion-rest update projects/MY_PROJECT/workitems/WI-123 ` --type workitems ` --id MY_PROJECT/WI-123 ` --attributes '{"title":"Updated"}' # Work Item 删:集合端点 + 完整资源 ID polarion-rest delete-many projects/MY_PROJECT/workitems ` --type workitems MY_PROJECT/WI-123 # 任意请求;body 也可写成 "@payload.json" 或 -(stdin) polarion-rest request PATCH projects/MY_PROJECT/workitems/WI-123 ` --body "@payload.json" ``` CLI 全局参数(例如 `--url`、`--token`、`--insecure`)应放在子命令前。生产环境建议使用 环境变量,避免 token 进入 shell 历史和进程参数。 ## 错误、安全与限制 - 401、403、404、409、413、429、5xx 等会映射到不同异常子类;异常会保留官方 `errors[]`,但不会打印 token。 - 204/205 正确返回 `None`;HTML 错误页、文本和附件二进制不会被强制当 JSON 解析。 - 默认拒绝 HTTP、跨域分页/self 链接、REST 根路径之外的绝对链接和重定向,避免凭据 泄漏。可信内网的 HTTP 必须显式 `allow_insecure_http=True`。 - 某些请求虽然返回 200,仍会在 `meta.errors` 中报告 include 截断或关系无权限。 使用 `strict_partial=True` 可将其视为异常。 - Polarion 返回的资源 ID 与链接应视为不透明值;优先保存并复用 `data.id` 和 `links.self`。 - 并非所有 Polarion 对象都有完整 CRUD。公共文档和本客户端无法替代目标服务器的 OpenAPI、字段元数据以及权限配置。 - 测试真实写操作时,请使用专用测试项目,并在确认创建响应后按资源 ID 精确清理; 客户端不会提供“按查询删除全部”之类的危险快捷方式。 完整演示见 [`examples/workitem_crud.py`](examples/workitem_crud.py)。