ashareapi 0.1.3__tar.gz → 0.1.4__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.
- {ashareapi-0.1.3 → ashareapi-0.1.4}/CHANGELOG.md +18 -0
- {ashareapi-0.1.3 → ashareapi-0.1.4}/PKG-INFO +1 -1
- {ashareapi-0.1.3 → ashareapi-0.1.4}/ashareapi/__init__.py +1 -2
- {ashareapi-0.1.3 → ashareapi-0.1.4}/ashareapi/client.py +15 -1
- {ashareapi-0.1.3 → ashareapi-0.1.4}/pyproject.toml +1 -1
- {ashareapi-0.1.3 → ashareapi-0.1.4}/tests/test_convert.py +21 -0
- {ashareapi-0.1.3 → ashareapi-0.1.4}/LICENSE +0 -0
- {ashareapi-0.1.3 → ashareapi-0.1.4}/MANIFEST.in +0 -0
- {ashareapi-0.1.3 → ashareapi-0.1.4}/README.md +0 -0
- {ashareapi-0.1.3 → ashareapi-0.1.4}/ashareapi/_code.py +0 -0
- {ashareapi-0.1.3 → ashareapi-0.1.4}/ashareapi/errors.py +0 -0
- {ashareapi-0.1.3 → ashareapi-0.1.4}/ashareapi.egg-info/SOURCES.txt +0 -0
- {ashareapi-0.1.3 → ashareapi-0.1.4}/examples/quickstart.py +0 -0
- {ashareapi-0.1.3 → ashareapi-0.1.4}/setup.cfg +0 -0
- {ashareapi-0.1.3 → ashareapi-0.1.4}/tests/test_endpoint_coverage.py +0 -0
|
@@ -7,6 +7,24 @@
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [0.1.4] — 2026-09-26
|
|
11
|
+
|
|
12
|
+
### 修复
|
|
13
|
+
- **`finance()` 返回值退化**:`/v1/finance` 的 `data` 是**表列表**
|
|
14
|
+
(`[[利润表行], [资产负债表行], [现金流量表行]]`),旧实现把它套成
|
|
15
|
+
`pd.DataFrame([[{...}], [{...}], [{...}]])` → **退化的 3×1「单元格里是 list」**,不可用。
|
|
16
|
+
现改为**原样返回表列表**(`list[list[dict]]`,对齐 JS SDK 的 `Row[][]`)。
|
|
17
|
+
- **多段结构原样返回**:`shareholder()` / `calendar()` 的 `data` 是 `{tables, data}` 多段对象
|
|
18
|
+
→ 原样返回该 dict(行为未变,本轮补文档与测试锁定)。
|
|
19
|
+
- **User-Agent 版本漂移**:`client.py` 的 `__version__` 曾是 `0.1.0`(包已是 `0.1.3`)
|
|
20
|
+
→ **UA 报的是旧版本**。现版本号**单一事实源**在 `client.py`,`__init__.py` 从它 re-export。
|
|
21
|
+
|
|
22
|
+
### 测试
|
|
23
|
+
- 新增 `test_frame_table_list_not_wrapped`(表列表**不套** DataFrame)
|
|
24
|
+
- 新增 `test_frame_sectioned_dict_passthrough`(多段 dict 原样返回)
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
10
28
|
## [0.1.3] — 2026-09-23
|
|
11
29
|
|
|
12
30
|
### 变更
|
|
@@ -9,10 +9,9 @@
|
|
|
9
9
|
|
|
10
10
|
文档:https://ashareapi.com/docs · 端点清单:https://ashareapi.com/endpoints
|
|
11
11
|
"""
|
|
12
|
-
from .client import AShareAPI
|
|
12
|
+
from .client import AShareAPI, __version__
|
|
13
13
|
from .errors import (AShareError, APIError, AuthError, EmptyResultError, RateLimitError,
|
|
14
14
|
UpstreamError)
|
|
15
15
|
|
|
16
|
-
__version__ = "0.1.3"
|
|
17
16
|
__all__ = ["AShareAPI", "AShareError", "AuthError", "RateLimitError", "EmptyResultError",
|
|
18
17
|
"UpstreamError", "APIError", "__version__"]
|
|
@@ -9,7 +9,9 @@ import requests
|
|
|
9
9
|
from ._code import normalize_code
|
|
10
10
|
from .errors import APIError, AuthError, EmptyResultError, RateLimitError, UpstreamError
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
# ⚠️ 版本**单一事实源**(`__init__.py` 从这里 re-export;`_request` 的 User-Agent 也用它)
|
|
13
|
+
# 2026-09-26 修正:此前这里是 `0.1.0`(包已 0.1.3)→ **UA 报的是 0.1.0**,版本漂移。
|
|
14
|
+
__version__ = "0.1.4"
|
|
13
15
|
|
|
14
16
|
DEFAULT_BASE = "https://api.ashareapi.com"
|
|
15
17
|
FREE_ENDPOINTS = (
|
|
@@ -89,6 +91,15 @@ class AShareAPI:
|
|
|
89
91
|
|
|
90
92
|
2026-09-23 实测:部分端点 ``data`` 直接是数组,部分是 Markdown 但都带 **``structured``**
|
|
91
93
|
结构化数组 → 这里**零 Markdown 解析** ✓
|
|
94
|
+
|
|
95
|
+
⚠️ **2026-09-26 修正 —— 三种返回形态,不能一律套 DataFrame**:
|
|
96
|
+
· 单表(多数端点)→ ``DataFrame``(未装 pandas → ``list[dict]``)
|
|
97
|
+
· **表列表**(``/v1/finance``:``[[利润表行],[资产负债行],[现金流行]]``)
|
|
98
|
+
→ 返回**列表**(``list[list[dict]]``,对齐 JS SDK 的 ``Row[][]``)。
|
|
99
|
+
旧实现会 ``pd.DataFrame([[{...}],[{...}],[{...}]])`` → **退化的 3×1「单元格里是 list」**,
|
|
100
|
+
不是可用结果(2026-09-26 实测确认)。
|
|
101
|
+
· **多段结构**(``/v1/shareholder``、``/v1/calendar``:``{tables, data}``)
|
|
102
|
+
→ 原样返回该 dict(与 JS SDK 一致)。
|
|
92
103
|
"""
|
|
93
104
|
if self.raw:
|
|
94
105
|
return body
|
|
@@ -97,6 +108,9 @@ class AShareAPI:
|
|
|
97
108
|
rows = body["data"]
|
|
98
109
|
if rows is None:
|
|
99
110
|
return body.get("data", body) # 无表格字段(health / challenge / usage)→ 返回整个信封
|
|
111
|
+
# ⭐ 表列表(首元素是 list)→ 不套 DataFrame(套了就是退化的 3×1 单元格为 list)
|
|
112
|
+
if rows and isinstance(rows[0], list):
|
|
113
|
+
return rows # list[list[dict]],对齐 JS SDK 的 Row[][]
|
|
100
114
|
try:
|
|
101
115
|
import pandas as pd
|
|
102
116
|
return pd.DataFrame(rows)
|
|
@@ -49,6 +49,27 @@ def test_frame_non_table_passthrough():
|
|
|
49
49
|
assert cli._frame({"ok": True, "data": {"k": "v"}}) == {"k": "v"}
|
|
50
50
|
|
|
51
51
|
|
|
52
|
+
def test_frame_table_list_not_wrapped():
|
|
53
|
+
"""表列表(/v1/finance)→ 原样返回 list[list[dict]],**不套 DataFrame**
|
|
54
|
+
|
|
55
|
+
旧实现会 pd.DataFrame([[{...}],[{...}],[{...}]]) → 退化的 3×1「单元格里是 list」。
|
|
56
|
+
"""
|
|
57
|
+
cli = AShareAPI()
|
|
58
|
+
tabs = [[{"EndDate": "2026-06-30", "OperatingRevenue": 1}],
|
|
59
|
+
[{"EndDate": "2026-06-30", "TotalAssets": 2}]]
|
|
60
|
+
r = cli._frame({"ok": True, "data": tabs})
|
|
61
|
+
assert r == tabs
|
|
62
|
+
assert isinstance(r[0], list) # 仍是表列表,不是 DataFrame
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def test_frame_sectioned_dict_passthrough():
|
|
66
|
+
"""多段结构(/v1/shareholder、/v1/calendar)→ 原样返回 dict(含 tables/data)"""
|
|
67
|
+
cli = AShareAPI()
|
|
68
|
+
sec = {"tables": [{"title": "十大股东", "slug": "top10_holders", "rows": [{"name": "A"}]}],
|
|
69
|
+
"data": {"top10_holders": [{"name": "A"}]}}
|
|
70
|
+
assert cli._frame({"ok": True, "data": sec}) == sec
|
|
71
|
+
|
|
72
|
+
|
|
52
73
|
def test_raw_mode_returns_envelope():
|
|
53
74
|
cli = AShareAPI(raw=True)
|
|
54
75
|
b = {"ok": True, "data": [{"x": 1}], "elapsed_ms": 12}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|