Skip to content

Commit 0bf8a7f

Browse files
author
zhansheng.lzs
committed
refactor(v2): promote SDK implementation to package root
Finalize the 2.0 package layout, move 1.x APIs under legacy_1x, and align tests, packaging, CI, examples, and documentation with the new import paths.
1 parent dea0cc2 commit 0bf8a7f

408 files changed

Lines changed: 2959 additions & 4194 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/unit_test.yml‎

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ on:
99
- 'main'
1010

1111
jobs:
12-
test:
12+
current:
1313
if: ${{ !(github.event_name == 'pull_request' && startsWith(github.event.pull_request.title, 'docs:')) }}
1414

1515
runs-on: ${{ matrix.os }}
@@ -18,7 +18,6 @@ jobs:
1818
os: [ ubuntu-latest ]
1919
python-version: [ '3.9', '3.12', '3.13', '3.14' ]
2020

21-
2221
steps:
2322
- name: Checkout repository
2423
uses: actions/checkout@v4
@@ -55,10 +54,55 @@ jobs:
5554
run: |
5655
python -m pip list --format=columns
5756
58-
- name: Run tests with coverage
57+
- name: Run current tests with coverage
5958
run: |
60-
coverage run -m pytest tests/unit
59+
coverage run -m pytest tests --ignore=tests/legacy_1x
6160
6261
- name: Generate coverage report
6362
run: |
6463
coverage report -m
64+
65+
legacy:
66+
if: ${{ !(github.event_name == 'pull_request' && startsWith(github.event.pull_request.title, 'docs:')) }}
67+
68+
runs-on: ${{ matrix.os }}
69+
strategy:
70+
matrix:
71+
os: [ ubuntu-latest ]
72+
python-version: [ '3.9', '3.12', '3.13', '3.14' ]
73+
74+
steps:
75+
- name: Checkout repository
76+
uses: actions/checkout@v4
77+
78+
- name: Set up Python ${{ matrix.python-version }}
79+
uses: actions/setup-python@v5
80+
with:
81+
python-version: ${{ matrix.python-version }}
82+
83+
- name: Cache pip dependencies
84+
uses: actions/cache@v4
85+
with:
86+
path: ~/.cache/pip
87+
key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml') }}
88+
restore-keys: |
89+
${{ runner.os }}-pip-
90+
91+
- name: Update setuptools
92+
run: |
93+
pip install --upgrade pip
94+
pip install setuptools==68.2.2 wheel==0.41.2
95+
96+
- name: Set PYTHONPATH
97+
run: |
98+
echo "PYTHONPATH=$PYTHONPATH:${{ github.workspace }}/src" >> $GITHUB_ENV
99+
100+
- name: Install dependencies
101+
run: |
102+
export PIP_DEFAULT_TIMEOUT=300
103+
pip install -r requirements.txt
104+
pip install -r requirements-test.txt
105+
106+
- name: Run archived legacy tests
107+
run: |
108+
python -m pytest tests/legacy_1x

‎.gitignore‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,5 +144,5 @@ cython_debug/
144144
# Local design/analysis docs — kept out of the public repo
145145
/md/
146146

147-
# Local PyPI investigation tooling; the CI guard lives in tests/unit/.
147+
# Local PyPI investigation tooling; the CI guard lives in tests/legacy_1x/unit/.
148148
/scripts/

‎.pre-commit-config.yaml‎

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,36 @@ repos:
33
rev: v4.3.0
44
hooks:
55
- id: check-ast
6-
exclude: ^tests/legacy/
6+
exclude: ^tests/legacy_1x/legacy/
77
- id: sort-simple-yaml
8-
exclude: ^tests/legacy/
8+
exclude: ^tests/legacy_1x/legacy/
99
- id: check-yaml
1010
exclude: |
1111
(?x)^(
1212
meta.yaml
13-
| tests/legacy/
13+
| tests/legacy_1x/legacy/
1414
)$
1515
- id: check-xml
16-
exclude: ^tests/legacy/
16+
exclude: ^tests/legacy_1x/legacy/
1717
- id: check-toml
18-
exclude: ^tests/legacy/
18+
exclude: ^tests/legacy_1x/legacy/
1919
- id: check-docstring-first
20-
exclude: ^tests/legacy/
20+
exclude: ^tests/legacy_1x/legacy/
2121
- id: check-json
22-
exclude: ^tests/legacy/
22+
exclude: ^tests/legacy_1x/legacy/
2323
- id: fix-encoding-pragma
24-
exclude: ^tests/legacy/
24+
exclude: ^tests/legacy_1x/legacy/
2525
- id: detect-private-key
26-
exclude: ^tests/legacy/
26+
exclude: ^tests/legacy_1x/legacy/
2727
- id: trailing-whitespace
28-
exclude: ^tests/legacy/
28+
exclude: ^tests/legacy_1x/legacy/
2929
- repo: https://github.com/asottile/add-trailing-comma
3030
rev: v3.1.0
3131
hooks:
3232
- id: add-trailing-comma
3333
# examples/01_atomic_capabilities/audio is ported verbatim from the sibling repo's
3434
# samples/ tree, whose hooks exempt samples/.
35-
exclude: ^(tests/legacy|examples/01_atomic_capabilities/audio)/
35+
exclude: ^(tests/legacy_1x/legacy|examples/01_atomic_capabilities/audio)/
3636
- repo: https://github.com/pre-commit/mirrors-mypy
3737
rev: v1.7.0
3838
hooks:
@@ -45,7 +45,7 @@ repos:
4545
pb2\.py$
4646
| grpc\.py$
4747
| ^docs
48-
| ^tests/legacy/
48+
| ^tests/legacy_1x/legacy/
4949
| ^examples/01_atomic_capabilities/audio/
5050
| \.html$
5151
| \.pyi$
@@ -67,13 +67,13 @@ repos:
6767
hooks:
6868
- id: black
6969
args: [ --line-length=79 ]
70-
exclude: ^(tests/legacy|examples/01_atomic_capabilities/audio)/
70+
exclude: ^(tests/legacy_1x/legacy|examples/01_atomic_capabilities/audio)/
7171
- repo: https://github.com/PyCQA/flake8
7272
rev: 6.1.0
7373
hooks:
7474
- id: flake8
7575
args: [ "--extend-ignore=E203"]
76-
exclude: ^(tests/legacy|examples/01_atomic_capabilities/audio)/
76+
exclude: ^(tests/legacy_1x/legacy|examples/01_atomic_capabilities/audio)/
7777
- repo: https://github.com/pylint-dev/pylint
7878
rev: v3.0.2
7979
hooks:
@@ -122,6 +122,7 @@ repos:
122122
--disable=C0114, # Disable missing module docstring for quick dev
123123
--disable=C0115, # Disable missing class docstring for quick dev
124124
--disable=C0116, # Disable missing function or method docstring for quick dev
125+
--disable=E0603, # Absolute self-imports and lazy exports in reinforcement
125126
]
126127
# Tests get their own entry (pylint 3.0.2 discovers rcfiles from the
127128
# invocation CWD, not per linted-file directory, so a tests/pylintrc
@@ -132,7 +133,7 @@ repos:
132133
- id: pylint
133134
name: pylint (tests)
134135
files: ^tests/
135-
exclude: ^tests/legacy/
136+
exclude: ^tests/legacy_1x/legacy/
136137
args: [
137138
--disable=W0511,
138139
--disable=W0718,
@@ -190,19 +191,19 @@ repos:
190191
hooks:
191192
- id: eslint
192193
files: \.(js|jsx)$
193-
exclude: '(.*js_third_party.*|^tests/legacy/)'
194+
exclude: '(.*js_third_party.*|^tests/legacy_1x/legacy/)'
194195
args: [ '--fix' ]
195196
- repo: https://github.com/thibaudcolas/pre-commit-stylelint
196197
rev: v14.4.0
197198
hooks:
198199
- id: stylelint
199200
files: \.(css)$
200-
exclude: '(.*css_third_party.*|^tests/legacy/)'
201+
exclude: '(.*css_third_party.*|^tests/legacy_1x/legacy/)'
201202
args: [ '--fix' ]
202203
- repo: https://github.com/pre-commit/mirrors-prettier
203204
rev: 'v3.0.0'
204205
hooks:
205206
- id: prettier
206207
additional_dependencies: [ 'prettier@3.0.0' ]
207208
files: \.(tsx?)$
208-
exclude: ^tests/legacy/
209+
exclude: ^tests/legacy_1x/legacy/

‎MANIFEST.in‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
include dashscope/v2/tokenizers/qwen.tiktoken
1+
include dashscope/tokenizers/qwen.tiktoken
22
include dashscope/py.typed
33
include dashscope/__init__.pyi
44
include NOTICE

‎README.md‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ By default each frame is incremental. Pass `incremental_output=False` to receive
194194
Failures raise a typed `DashScopeError` by default (both non-2xx HTTP statuses and HTTP-200-with-a-business-error land here):
195195

196196
```python
197-
from dashscope.v2 import errors
197+
from dashscope import errors
198198

199199
try:
200200
client.chat.completions.create(model="qwen-plus", messages=["hi"])
@@ -447,6 +447,32 @@ The 1.x module-level API is unchanged and still supported — you can adopt 2.0
447447
| `dashscope.set_region(region, workspace_id)` | `dashscope.Client(region=..., workspace=...)` |
448448
| OpenAI-compatible via `dashscope.aigc.chat_completion.Completions` | `dashscope.Client(protocol="openai")` |
449449

450+
### Package layout and compatibility
451+
452+
The 2.0 implementation is directly under `dashscope`; the former
453+
`dashscope.v2` namespace has been removed. Existing root 1.x exports remain
454+
available. Old deep modules such as `dashscope.aigc` and `dashscope.client`
455+
have moved under `dashscope.legacy_1x`. The 2.0 Agentic RL workflow lives in
456+
`dashscope.finetune`; its 1.x job-management surface is under
457+
`dashscope.legacy_1x.finetune`.
458+
459+
`dashscope.save_api_key` now comes from `dashscope._config`. It accepts an
460+
optional key-file path, expands `~`, creates missing parent directories, and
461+
writes UTF-8. Logs from the current client use the independent
462+
`dashscope._logging` logger hierarchy and do not reconfigure the shared
463+
`dashscope` root logger.
464+
465+
### Development tests
466+
467+
```bash
468+
python -m pytest tests --ignore=tests/legacy_1x -q # current
469+
python -m pytest tests/legacy_1x -q # archived compatibility
470+
python -m pytest tests -q # everything
471+
```
472+
473+
For current coverage, run `coverage run -m pytest tests
474+
--ignore=tests/legacy_1x`, then `coverage report -m`.
475+
450476
## License
451477

452478
This project is licensed under the Apache License (Version 2.0).

‎README_zh.md‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ for text in stream.text_stream: # 内容增量
194194
失败默认抛出类型化的 `DashScopeError`(非 2xx 的 HTTP 状态码,以及 HTTP 200 但业务报错,都会归入这里):
195195

196196
```python
197-
from dashscope.v2 import errors
197+
from dashscope import errors
198198

199199
try:
200200
client.chat.completions.create(model="qwen-plus", messages=["hi"])
@@ -447,6 +447,29 @@ examples/
447447
| `dashscope.set_region(region, workspace_id)` | `dashscope.Client(region=..., workspace=...)` |
448448
| OpenAI 兼容通过 `dashscope.aigc.chat_completion.Completions` | `dashscope.Client(protocol="openai")` |
449449

450+
### 包布局与兼容策略
451+
452+
2.0 实现直接位于 `dashscope` 根包,原 `dashscope.v2` 命名空间已移除。
453+
包根已有的 1.x 导出继续可用;`dashscope.aigc`、`dashscope.client` 等旧
454+
deep import 已移至 `dashscope.legacy_1x` 下。2.0 Agentic RL 工作流位于
455+
`dashscope.finetune`,1.x 任务管理接口位于 `dashscope.legacy_1x.finetune`。
456+
457+
`dashscope.save_api_key` 现在来自 `dashscope._config`,仍接受可选的 key
458+
文件路径,并会展开 `~`、创建缺失的父目录、按 UTF-8 写入。当前客户端使用
459+
独立的 `dashscope._logging` logger 层级,不会重新配置共享的 `dashscope`
460+
根 logger。
461+
462+
### 开发测试
463+
464+
```bash
465+
python -m pytest tests --ignore=tests/legacy_1x -q # 当前实现
466+
python -m pytest tests/legacy_1x -q # 归档兼容套件
467+
python -m pytest tests -q # 全量
468+
```
469+
470+
当前实现的 coverage 使用 `coverage run -m pytest tests
471+
--ignore=tests/legacy_1x`,随后执行 `coverage report -m`。
472+
450473
## 许可证
451474

452475
本项目采用 Apache License (Version 2.0) 许可证。

‎dashscope/__init__.py‎

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
from dashscope.legacy_1x.api_entities.http_request import (
4242
close_shared_sync_session,
4343
)
44-
from dashscope.legacy_1x.common.api_key import save_api_key
4544
from dashscope.legacy_1x.common.env import (
4645
MAAS_REGIONS,
4746
api_key,
@@ -51,8 +50,8 @@
5150
base_websocket_api_url,
5251
validate_workspace_id,
5352
)
54-
from dashscope.finetune.deployments import Deployments
55-
from dashscope.finetune.finetunes import FineTunes
53+
from dashscope.legacy_1x.finetune.deployments import Deployments
54+
from dashscope.legacy_1x.finetune.finetunes import FineTunes
5655
from dashscope.legacy_1x.embeddings.batch_text_embedding import (
5756
BatchTextEmbedding,
5857
)
@@ -78,8 +77,13 @@
7877
list_tokenizers,
7978
)
8079

81-
# dashscope 2.0 public surface (implementation lives in dashscope/v2/).
82-
from dashscope.v2 import AsyncClient, Client, WsConnection, chat, settings
80+
# dashscope 2.0 public surface.
81+
from dashscope import errors
82+
from dashscope._config import Config, Settings, save_api_key, settings
83+
from dashscope._quickstart import chat
84+
from dashscope.client import AsyncClient, Client
85+
from dashscope.errors import DashScopeError, ErrorCode
86+
from dashscope.transport.ws_connection import WsConnection, WsTask
8387

8488
# cn-beijing defaults to the legacy dashscope.aliyuncs.com endpoints;
8589
# its MaaS URLs are only reachable via an explicit set_region() call.
@@ -229,8 +233,14 @@ def __dir__():
229233
# dashscope 2.0
230234
"AsyncClient",
231235
"Client",
236+
"Config",
237+
"DashScopeError",
238+
"ErrorCode",
239+
"Settings",
232240
"WsConnection",
241+
"WsTask",
233242
"chat",
243+
"errors",
234244
"set_region",
235245
]
236246

‎dashscope/__init__.pyi‎

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,18 @@ from typing import (
1414
# ---------------------------------------------------------------------------
1515
# dashscope 2.0
1616
# ---------------------------------------------------------------------------
17-
from dashscope.v2 import AsyncClient as AsyncClient
18-
from dashscope.v2 import Client as Client
19-
from dashscope.v2 import WsConnection as WsConnection
20-
from dashscope.v2 import chat as chat
21-
from dashscope.v2 import settings as settings
17+
from dashscope import errors as errors
18+
from dashscope._config import Config as Config
19+
from dashscope._config import Settings as Settings
20+
from dashscope._config import save_api_key as save_api_key
21+
from dashscope._config import settings as settings
22+
from dashscope._quickstart import chat as chat
23+
from dashscope.client import AsyncClient as AsyncClient
24+
from dashscope.client import Client as Client
25+
from dashscope.errors import DashScopeError as DashScopeError
26+
from dashscope.errors import ErrorCode as ErrorCode
27+
from dashscope.transport.ws_connection import WsConnection as WsConnection
28+
from dashscope.transport.ws_connection import WsTask as WsTask
2229

2330
# ---------------------------------------------------------------------------
2431
# Config
@@ -29,7 +36,9 @@ base_compatible_api_url: str
2936
base_http_api_url: str
3037
base_websocket_api_url: str
3138

32-
def save_api_key(api_key: str, file_path: Optional[str] = ...) -> None: ...
39+
def save_api_key(
40+
api_key: str, api_key_file_path: Optional[str] = ...
41+
) -> None: ...
3342
def close_shared_aio_session() -> None: ...
3443
def close_shared_sync_session() -> None: ...
3544
def set_region(region: str, workspace_id: Optional[str] = ...) -> None: ...
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ def clear(self) -> None:
321321
self._explicit.clear()
322322
if had_log_level:
323323
# pylint: disable=import-outside-toplevel
324-
from dashscope.v2._logging import reset_log_level
324+
from dashscope._logging import reset_log_level
325325

326326
reset_log_level()
327327

@@ -496,7 +496,7 @@ def log_level(self) -> Optional[str]:
496496
@log_level.setter
497497
def log_level(self, value: str) -> None:
498498
# pylint: disable=import-outside-toplevel
499-
from dashscope.v2._logging import set_log_level
499+
from dashscope._logging import set_log_level
500500

501501
set_log_level(value)
502502
with self._lock:

0 commit comments

Comments
 (0)