Skip to content

fix(xueqiu): validate hot-stock limits - #620

Closed
alooshxl wants to merge 1 commit into
Panniantong:mainfrom
alooshxl:fix/xueqiu-hot-stocks-limit
Closed

fix(xueqiu): validate hot-stock limits#620
alooshxl wants to merge 1 commit into
Panniantong:mainfrom
alooshxl:fix/xueqiu-hot-stocks-limit

Conversation

@alooshxl

Copy link
Copy Markdown

Problem

get_hot_stocks() documents limit: 最多返回条数(上限 50) but never enforces it. The raw value goes straight into the request and the slice:

data = _get_json(
    f"https://stock.xueqiu.com/v5/stock/hot_stock/list.json"
    f"?size={limit}&type={stock_type}"
)
...
for idx, item in enumerate(items[:limit], 1):

So on main:

  • get_hot_stocks(limit=500) requests size=500 and returns every item the endpoint sends back, above the documented maximum.
  • get_hot_stocks(limit=0) still performs a network request, then returns [].
  • get_hot_stocks(limit=-1) requests size=-1 and, because items[:-1] drops the last element, silently returns a truncated list instead of reporting the bad argument. Stubbing _get_json with a 60-item payload against main produces ?size=-1&type=10 and 59 returned items.

The sibling method get_hot_posts() already handles all three cases; the guards were added in 31b028f (fix(xueqiu): honor and clamp hot-post limits), merged via #578.

Change

  • agent_reach/channels/xueqiu.py: apply the same three guards accepted for get_hot_posts() to get_hot_stocks() — reject a negative limit with ValueError("limit must be non-negative"), clamp with min(limit, 50), and return [] for zero before any request. The normalized value then drives both the size query parameter and the result slice.
  • tests/test_xueqiu_channel.py: four offline regressions beside the existing hot-stock tests, covering the requested size passing through unchanged, clamping to size=50 with at most 50 shaped results from a 60-item payload, and the zero/negative cases with a _get_json double that fails if the network path is reached.

stock_type, ranking, the code/symbol fallback, and every other Xueqiu behavior are untouched.

Verification

Run on this branch (Windows, Python 3.14.5, pytest 9.1.1, ruff 0.16.3, mypy 2.3.0):

Command Result
python -m pytest tests/test_xueqiu_channel.py -v 23 passed
python -m ruff check agent_reach/channels/xueqiu.py tests/test_xueqiu_channel.py All checks passed
python -m mypy agent_reach/channels/xueqiu.py Success: no issues found in 1 source file
python -m ruff check agent_reach tests All checks passed
python -m mypy agent_reach Success: no issues found in 35 source files
git diff --check clean
python -m pytest tests/ -v 4 failed, 558 passed, 28 skipped, 16 subtests passed

The three boundary tests were confirmed to fail before the change (size=500, and the zero/negative cases reaching the request double) and to pass after it.

The 4 failures are pre-existing in this local environment and unrelated to this change: the symlink security tests in tests/test_channels.py and tests/test_reddit_channel.py raise OSError: [WinError 1314] A required privilege is not held by the client because this Windows account cannot create symlinks. They fail identically on main before this change (baseline: 4 failed, 554 passed, 28 skipped), and #616 addresses them separately.

Scope

  • Only get_hot_stocks() changes; get_hot_posts(), search_stock(), quote retrieval, and cookie handling are untouched.
  • No shared limit-normalization helper and no type coercion for non-integer arguments — this mirrors the existing accepted implementation rather than generalizing it.
  • No new network error handling: failures from _get_json still propagate unchanged.

@alooshxl alooshxl closed this by deleting the head repository Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant