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.
@@ -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
  ### 变更
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ashareapi
3
- Version: 0.1.3
3
+ Version: 0.1.4
4
4
  Summary: A股数据 API 官方 Python SDK —— 行情 / K线 / 财务 / 资金 / 龙虎榜 / 板块 / 因子选股(含 MCP)
5
5
  Author: ashareapi
6
6
  License-Expression: MIT
@@ -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
- __version__ = "0.1.0"
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)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ashareapi"
7
- version = "0.1.3"
7
+ version = "0.1.4"
8
8
  description = "A股数据 API 官方 Python SDK —— 行情 / K线 / 财务 / 资金 / 龙虎榜 / 板块 / 因子选股(含 MCP)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -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